Di Linux, apa yang terjadi pada status suatu proses ketika ia perlu membaca blok dari disk? Apakah itu diblokir? Jika ya, bagaimana proses lain dipilih untuk dijalankan?
Sambil menunggu read()
atau write()
ke / dari deskriptor file kembali, proses akan ditempatkan dalam mode tidur khusus, yang dikenal sebagai "D" atau "Disk Sleep". Ini istimewa, karena prosesnya tidak dapat dihentikan atau diinterupsi saat dalam keadaan seperti itu. Proses menunggu kembalinya ioctl () juga akan ditidurkan dengan cara ini.
Pengecualian untuk ini adalah ketika file (seperti terminal atau perangkat karakter lainnya) dibuka dalam O_NONBLOCK
mode, dilewatkan ketika diasumsikan bahwa perangkat (seperti modem) akan membutuhkan waktu untuk menginisialisasi. Namun, Anda menunjukkan blokir perangkat dalam pertanyaan Anda. Juga, saya belum pernah mencoba ioctl()
yang cenderung memblokir di fd dibuka dalam mode non pemblokiran (setidaknya tidak secara sadar).
Bagaimana proses lain dipilih sepenuhnya bergantung pada penjadwal yang Anda gunakan, serta proses lain apa yang mungkin telah dilakukan untuk mengubah bobotnya dalam penjadwal tersebut.
Beberapa program ruang pengguna dalam keadaan tertentu telah diketahui tetap dalam keadaan ini selamanya, sampai di-boot ulang. Ini biasanya dikelompokkan dengan "zombie" lainnya, tetapi istilah tersebut tidak benar karena secara teknis mereka tidak mati.
Saat suatu proses perlu mengambil data dari disk, proses tersebut secara efektif berhenti berjalan di CPU untuk membiarkan proses lain berjalan karena operasi tersebut mungkin membutuhkan waktu lama untuk diselesaikan - setidaknya 5 md waktu pencarian untuk disk adalah umum, dan 5 md sama dengan 10 juta Siklus CPU, keabadian dari sudut pandang program!
Dari sudut pandang programmer (juga disebut "di ruang pengguna"), ini disebut panggilan sistem pemblokiran . Jika Anda memanggil
write(2)
(yang merupakan pembungkus libc tipis di sekitar panggilan sistem dengan nama yang sama), proses Anda tidak berhenti tepat di batas itu; itu berlanjut, di kernel, menjalankan kode panggilan sistem. Sebagian besar waktu berjalan sampai ke driver pengontrol disk tertentu (nama file → filesystem / VFS → block device → device driver), di mana perintah untuk mengambil blok pada disk dikirimkan ke perangkat keras yang tepat, yang sangat operasi cepat di sebagian besar waktu.LALU proses tersebut dalam keadaan tidur (dalam ruang kernel, pemblokiran disebut tidur - tidak ada yang 'diblokir' dari sudut pandang kernel). Ini akan dibangunkan setelah perangkat keras akhirnya mengambil data yang tepat, kemudian prosesnya akan ditandai sebagai dapat dijalankan dan akan dijadwalkan. Akhirnya, penjadwal akan menjalankan prosesnya.
Akhirnya, di ruang pengguna, panggilan sistem pemblokiran kembali dengan status dan data yang sesuai, dan aliran program terus berjalan.
Dimungkinkan untuk memanggil sebagian besar panggilan sistem I / O dalam mode non-pemblokiran (lihat
O_NONBLOCK
diopen(2)
danfcntl(2)
). Dalam kasus ini, panggilan sistem kembali segera dan hanya melaporkan mengirimkan operasi disk. Pemrogram harus memeriksa secara eksplisit di lain waktu apakah operasi selesai, berhasil atau tidak, dan mengambil hasilnya (misalnya denganselect(2)
). Ini disebut pemrograman asynchronous atau event-based.Sebagian besar jawaban di sini yang menyebutkan status D (yang disebut
TASK_UNINTERRUPTIBLE
dengan nama status Linux) salah. Keadaan D adalah mode tidur khusus yang hanya dipicu di jalur kode ruang kernel, ketika jalur kode itu tidak dapat diganggu (karena akan terlalu rumit untuk diprogram), dengan harapan bahwa itu akan memblokir hanya untuk waktu yang lama. waktu singkat. Saya percaya bahwa kebanyakan "status D" sebenarnya tidak terlihat; mereka berumur sangat pendek dan tidak dapat diamati dengan alat pengambilan sampel seperti 'atas'.Anda dapat menghadapi proses yang tidak dapat terbunuh dalam status D dalam beberapa situasi. NFS terkenal akan hal itu, dan saya sering menjumpainya. Saya pikir ada bentrokan semantik antara beberapa jalur kode VFS, yang mengasumsikan selalu mencapai disk lokal dan deteksi kesalahan cepat (pada SATA, batas waktu kesalahan akan sekitar beberapa 100 ms), dan NFS, yang sebenarnya mengambil data dari jaringan yang mana lebih tangguh dan memiliki pemulihan yang lambat (waktu tunggu TCP 300 detik biasa terjadi). Baca artikel ini untuk solusi keren yang diperkenalkan di Linux 2.6.25 dengan
TASK_KILLABLE
status. Sebelum era ini ada peretasan di mana Anda benar-benar dapat mengirim sinyal ke klien proses NFS dengan mengirimkan SIGKILL ke utas kernelrpciod
, tetapi lupakan tentang trik jelek itu.…sumber
/proc/stat
?Proses yang melakukan I / O akan ditempatkan dalam status D (tidur tidak terputus) , yang membebaskan CPU hingga ada interupsi perangkat keras yang memberi tahu CPU untuk kembali menjalankan program. Lihat
man ps
untuk status proses lainnya.Bergantung pada kernel Anda, ada penjadwal proses , yang melacak runqueue proses yang siap dijalankan. Ini, bersama dengan algoritma penjadwalan, memberi tahu kernel proses mana yang akan ditetapkan ke CPU mana. Ada proses kernel dan proses pengguna yang perlu dipertimbangkan. Setiap proses dialokasikan potongan waktu, yang merupakan bagian dari waktu CPU yang diizinkan untuk digunakan. Setelah proses menggunakan semua bagian waktunya, proses tersebut ditandai sebagai kedaluwarsa dan diberi prioritas lebih rendah dalam algoritme penjadwalan.
Di kernel 2.6 , ada penjadwal kompleksitas waktu O (1) , jadi tidak peduli berapa banyak proses yang Anda jalankan, itu akan menetapkan CPU dalam waktu yang konstan. Ini lebih rumit, karena 2.6 memperkenalkan preemption dan penyeimbangan beban CPU bukanlah algoritma yang mudah. Bagaimanapun, ini efisien dan CPU tidak akan tetap diam saat Anda menunggu I / O.
sumber
Seperti yang telah dijelaskan oleh orang lain, proses dalam status "D" (tidur tak terputus) bertanggung jawab atas hang proses ps. Bagi saya ini telah terjadi berkali-kali dengan RedHat 6.x dan direktori home NFS yang dipasang secara otomatis.
Untuk membuat daftar proses dalam status D Anda dapat menggunakan perintah berikut:
Untuk mengetahui direktori proses saat ini dan, mungkin, disk NFS yang terpasang yang memiliki masalah, Anda dapat menggunakan perintah yang mirip dengan contoh berikut (ganti 31134 dengan nomor proses tidur):
Saya menemukan bahwa memberikan perintah umount dengan sakelar -f (force), ke sistem file nfs yang terkait, dapat membangunkan proses tidur:
sistem file tidak di-unmount, karena sedang sibuk, tetapi proses terkait membangunkan dan saya dapat menyelesaikan masalah tanpa melakukan boot ulang.
sumber
Dengan asumsi proses Anda adalah satu utas, dan Anda menggunakan pemblokiran I / O, proses Anda akan memblokir menunggu I / O selesai. Kernel akan memilih proses lain untuk dijalankan berdasarkan kebaikan, prioritas, waktu berjalan terakhir, dll. Jika tidak ada proses lain yang dapat dijalankan, kernel tidak akan berjalan; sebagai gantinya, ini akan memberi tahu perangkat keras bahwa mesin dalam keadaan diam (yang akan menghasilkan konsumsi daya yang lebih rendah).
Proses yang menunggu I / O selesai biasanya muncul di status D di, misalnya,
ps
dantop
.sumber
Ya, tugas diblokir dalam panggilan sistem read (). Tugas lain yang siap dijalankan, atau jika tidak ada tugas lain yang siap, tugas idle (untuk CPU itu) berjalan.
Pembacaan disk yang memblokir dan normal menyebabkan tugas memasuki status "D" (seperti yang dicatat orang lain). Tugas-tugas semacam itu berkontribusi pada rata-rata pemuatan, meskipun mereka tidak menggunakan CPU.
Beberapa tipe IO lainnya, terutama tty dan jaringan, tidak berperilaku sama - proses berakhir dalam status "S" dan dapat terputus dan tidak dihitung terhadap rata-rata beban.
sumber
Ya, tugas yang menunggu IO diblokir, dan tugas lain dijalankan. Memilih tugas berikutnya dilakukan oleh penjadwal Linux .
sumber
Umumnya proses tersebut akan diblokir. Jika operasi baca ada pada deskriptor file yang ditandai sebagai non-pemblokiran atau jika proses menggunakan IO asinkron, proses tersebut tidak akan diblokir. Juga jika proses memiliki utas lain yang tidak diblokir, mereka dapat terus berjalan.
Keputusan tentang proses mana yang berjalan selanjutnya tergantung pada penjadwal di kernel.
sumber