Bagikan melalui


I/O sinkron dan asinkron

Lihat juga aplikasi sampel terkait I/O.

Ada dua jenis sinkronisasi input/output (I/O): I/O sinkron dan I/O asinkron. I/O asinkron juga disebut sebagai I/O yang tumpang tindih.

Dalam I/O file sinkron, utas memulai operasi I/O dan segera memasuki status tunggu hingga permintaan I/O selesai. Utas yang melakukan I/O file asinkron mengirimkan permintaan I/O ke kernel dengan memanggil fungsi yang sesuai. Jika permintaan diterima oleh kernel, utas panggilan terus memproses pekerjaan lain sampai kernel memberi sinyal ke utas bahwa operasi I/O selesai. Kemudian mengganggu pekerjaannya saat ini dan memproses data dari operasi I/O seperlunya.

Dua jenis sinkronisasi diilustrasikan dalam gambar berikut.

Cuplikan layar diagram yang mengilustrasikan i/o sinkron dan asinkron.

Dalam situasi di mana permintaan I/O diperkirakan akan memakan banyak waktu, seperti refresh atau pencadangan database besar atau tautan komunikasi yang lambat, I/O asinkron umumnya merupakan cara yang baik untuk mengoptimalkan efisiensi pemrosesan. Namun, untuk operasi I/O yang relatif cepat, overhead pemrosesan permintaan I/O kernel dan sinyal kernel dapat membuat I/O asinkron kurang bermanfaat, terutama jika banyak operasi I/O cepat yang perlu dilakukan. Dalam hal ini, I/O sinkron akan lebih baik. Mekanisme dan detail implementasi tentang cara menyelesaikan tugas-tugas ini bervariasi tergantung pada jenis handel perangkat yang digunakan dan kebutuhan khusus aplikasi. Dengan kata lain, biasanya ada beberapa cara untuk menyelesaikan masalah.

Pertimbangan I/O Sinkron dan Asinkron

Jika file atau perangkat dibuka untuk I/O sinkron (yaitu, FILE_FLAG_OVERLAPPED tidak ditentukan), panggilan berikutnya ke fungsi seperti WriteFile dapat memblokir eksekusi utas panggilan hingga salah satu peristiwa berikut terjadi:

  • Operasi I/O selesai (dalam contoh ini, tulis data).
  • Terjadi kesalahan I/O. (Misalnya, pipa ditutup dari ujung lainnya.)
  • Kesalahan dilakukan dalam panggilan itu sendiri (misalnya, satu atau beberapa parameter tidak valid).
  • Utas lainnya dalam proses memanggil fungsi CancelSynchronousIo menggunakan handle utas yang diblokir, yang mengakhiri I/O untuk utas tersebut dan menyebabkan operasi I/O gagal.
  • Utas yang diblokir dihentikan oleh sistem; misalnya, proses itu sendiri dihentikan, atau utas lain memanggil fungsi TerminateThread menggunakan handel utas yang diblokir. (Ini umumnya dianggap sebagai upaya terakhir dan desain aplikasi yang tidak baik.)

Dalam beberapa kasus, penundaan ini mungkin tidak dapat diterima oleh desain dan tujuan aplikasi, sehingga perancang aplikasi harus mempertimbangkan untuk menggunakan I/O asinkron dengan objek sinkronisasi utas yang sesuai seperti port penyelesaian I/O. Untuk informasi selengkapnya tentang sinkronisasi utas, lihat Tentang Sinkronisasi.

Proses membuka file untuk I/O asinkron dalam panggilannya ke CreateFile dengan menentukan bendera FILE_FLAG_OVERLAPPED di parameter dwFlagsAndAttributes . Jika FILE_FLAG_OVERLAPPED tidak ditentukan, file dibuka untuk I/O sinkron. Ketika file telah dibuka untuk I/O asinkron, penunjuk ke struktur OVERLAPPED diteruskan ke panggilan ke ReadFile dan WriteFile. Saat melakukan I/O sinkron, struktur ini tidak diperlukan dalam panggilan ke ReadFile dan WriteFile.

Catatan

Jika sebuah file atau perangkat dibuka untuk I/O asinkronus, panggilan berikutnya ke fungsi seperti WriteFile menggunakan handle tersebut umumnya akan segera kembali, tetapi dapat juga berperilaku sinkron dalam kaitannya dengan eksekusi yang terblokir. Untuk informasi selengkapnya, lihat I/O disk asinkron muncul sebagai sinkron di Windows.

Meskipun CreateFile adalah fungsi paling umum untuk digunakan untuk membuka file, volume disk, pipa anonim, dan perangkat serupa lainnya, operasi I/O juga dapat dilakukan menggunakan handle typecast dari objek sistem lain seperti soket yang dibuat oleh soket atau menerima fungsi.

Handle untuk objek direktori diperoleh dengan memanggil fungsi CreateFile dengan atribut FILE_FLAG_BACKUP_SEMANTICS. Handel direktori hampir tidak pernah digunakan—aplikasi cadangan adalah salah satu dari beberapa aplikasi yang biasanya akan menggunakannya.

Setelah membuka objek file untuk I/O asinkron, struktur OVERLAPPED harus dibuat, diinisialisasi, dan diteruskan dengan benar ke setiap panggilan ke fungsi seperti ReadFile dan WriteFile. Ingatlah hal-hal berikut saat menggunakan struktur TUMPANG TINDIH dalam operasi baca dan tulis asinkron:

  • Jangan mencabut alokasi atau mengubah struktur OVERLAPPED atau penyangga data sampai semua operasi I/O asinkron ke objek file telah selesai.
  • Jika Anda mendeklarasikan pointer Anda ke struktur OVERLAPPED sebagai variabel lokal, jangan keluar dari fungsi lokal sampai semua operasi I/O asinkron pada objek file telah selesai. Jika fungsi lokal keluar lebih awal dari yang diharapkan, struktur OVERLAPPED akan keluar dari jangkauan dan tidak akan dapat diakses oleh fungsi ReadFile atau WriteFile yang ditemuinya di luar fungsi tersebut.

Anda juga dapat membuat event dan menempatkan handle dalam struktur OVERLAPPED; fungsi tunggu kemudian dapat digunakan untuk menunggu penyelesaian operasi I/O dengan menunggu pada handle event.

Seperti yang dinyatakan sebelumnya, ketika bekerja dengan handel asinkron, aplikasi harus berhati-hati saat membuat penentuan tentang kapan harus membebaskan sumber daya yang terkait dengan operasi I/O tertentu pada handel tersebut. Jika handel dialokasikan ulang sebelum waktunya, ReadFile atau WriteFile mungkin melaporkan secara salah sebagai operasi I/O telah selesai. Selanjutnya, fungsi WriteFile terkadang akan mengembalikan TRUE dengan nilai GetLastErrorERROR_SUCCESS, meskipun menggunakan handel asinkron (yang juga dapat mengembalikan FALSE dengan ERROR_IO_PENDING). Programmer yang terbiasa dengan desain I/O sinkron biasanya akan merilis sumber daya buffer data pada saat ini karena TRUE dan ERROR_SUCCESS menandakan operasi selesai. Namun, jika port penyelesaian I/O digunakan dengan handel asinkron ini, paket penyelesaian juga akan dikirim meskipun operasi I/O segera selesai. Dengan kata lain, jika aplikasi membebaskan sumber daya setelah WriteFile mengembalikan TRUE dengan ERROR_SUCCESS selain dalam rutinitas port penyelesaian I/O, aplikasi akan memiliki kondisi kesalahan bebas ganda. Dalam contoh ini, rekomendasinya adalah untuk memungkinkan rutinitas port penyelesaian bertanggung jawab sepenuhnya atas semua operasi pengosongan untuk sumber daya tersebut.

Sistem tidak mempertahankan penunjuk file pada handel asinkron ke file dan perangkat yang mendukung penunjuk file (yaitu, perangkat yang memungkinkan pencarian), oleh karena itu posisi file harus diteruskan ke fungsi baca dan tulis dalam anggota data offset terkait dari struktur OVERLAPPED. Untuk informasi selengkapnya, lihat WriteFile dan ReadFile.

Posisi penunjuk file untuk handel sinkron dikelola oleh sistem saat data dibaca atau ditulis dan juga dapat diperbarui menggunakan fungsi SetFilePointer atau SetFilePointerEx .

Aplikasi juga dapat menunggu pada handel file untuk menyinkronkan penyelesaian operasi I/O, tetapi melakukannya membutuhkan perhatian ekstrem. Setiap kali operasi I/O dimulai, sistem operasi mengatur handel file ke status tidak ditandatangani. Setiap kali operasi I/O selesai, sistem operasi mengatur handel file ke status yang disinyalir. Oleh karena itu, jika aplikasi memulai dua operasi I/O dan menunggu pada handel file, tidak ada cara untuk menentukan operasi mana yang selesai ketika handel diatur ke status sinyal. Jika aplikasi harus melakukan beberapa operasi I/O asinkron pada satu file, aplikasi harus menunggu pada handle peristiwa dalam struktur OVERLAPPED tertentu untuk setiap operasi I/O, bukan pada handle file umum.

Membatalkan Operasi I/O

Untuk membatalkan semua operasi I/O asinkron yang tertunda, gunakan:

  • CancelIo: Fungsi ini hanya membatalkan operasi yang dikeluarkan oleh thread pemanggil untuk handle berkas yang ditentukan.
  • CancelIoEx: Fungsi ini membatalkan semua operasi yang dikeluarkan oleh thread untuk handle file yang ditentukan.

Gunakan CancelSynchronousIo untuk membatalkan operasi I/O sinkron yang tertunda.

Fungsi ReadFileEx dan WriteFileEx memungkinkan aplikasi menentukan rutinitas untuk dijalankan (lihat FileIOCompletionRoutine) ketika permintaan I/O asinkron selesai.

Tulis File

Baca File