Status Proses Linux

90

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?

Blair
sumber

Jawaban:

87

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_NONBLOCKmode, 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.

Tim Pos
sumber
1
"Proses menunggu kembalinya ioctl () juga akan ditidurkan dengan cara ini". Saya baru saja menghentikan proses userspace saya menunggu pemblokiran IOCTL jadi ini tidak benar. Kecuali saya salah
paham
Akan sangat sulit untuk mengatur waktu ujian seperti itu. Proses yang tidak terputus tidak bisa dimatikan; jika Anda dapat membunuhnya, maka itu hanya memblokir (kernel tidak berada di tengah-tengah bagian mana pun dari ioctl, dan menyalin respons yang sesuai ke ruang pengguna di lokasi yang Anda lewati (atau setidaknya tidak ada di tengah menyalin)). Linux juga telah banyak berubah sejak 2009 saat ini ditulis; fenomena ini jauh lebih sulit diamati seperti dulu.
Tim Post
133

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_NONBLOCKdi open(2)dan fcntl(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 dengan select(2)). Ini disebut pemrograman asynchronous atau event-based.

Sebagian besar jawaban di sini yang menyebutkan status D (yang disebut TASK_UNINTERRUPTIBLEdengan 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_KILLABLEstatus. Sebelum era ini ada peretasan di mana Anda benar-benar dapat mengirim sinyal ke klien proses NFS dengan mengirimkan SIGKILL ke utas kernel rpciod, tetapi lupakan tentang trik jelek itu.…

zerodeux
sumber
2
+1 untuk tanggapan mendetail, tetapi harap perhatikan bahwa utas ini telah menerima jawaban yang diterima selama hampir dua tahun. Tekan tautan "Pertanyaan" jika Anda ingin membantu untuk pertanyaan yang lebih baru. Selamat datang di Stack Overflow, dan terima kasih telah berkontribusi!
GargantuChet
20
Jawaban ini adalah satu-satunya yang menyebutkan NFS, yang di beberapa lingkungan merupakan penjelasan paling umum untuk proses di status D. +1.
Pinko
14
Jawaban yang sangat bagus, terima kasih. Perhatikan juga bahwa proses masuk ke status D sambil menunggu halaman yang telah ditukar, sehingga proses meronta-ronta akan berada di status D untuk waktu yang lama.
cha0site
@zerodeux jawaban yang bagus, tetapi saya pikir skema Anda (nama file -> filesystem / VFS -> blokir perangkat -> driver perangkat) seharusnya (nama file -> VFS -> filesystem (ext3) -> blokir perangkat -> driver perangkat)
c4f4t0r
1
Apakah aman untuk mengasumsikan bahwa waktu yang dihabiskan di kernel menunggu spinlock (yang mungkin atau mungkin tidak terkait dengan disk i / o) semuanya dilaporkan sebagai D-state in /proc/stat?
sumbu
8

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 psuntuk 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.

pengguna224579
sumber
3

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:

cd /proc
for i in [0-9]*;do echo -n "$i :";cat $i/status |grep ^State;done|grep D

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):

# ls -l /proc/31134/cwd
lrwxrwxrwx 1 pippo users 0 Aug  2 16:25 /proc/31134/cwd -> /auto/pippo

Saya menemukan bahwa memberikan perintah umount dengan sakelar -f (force), ke sistem file nfs yang terkait, dapat membangunkan proses tidur:

umount -f /auto/pippo

sistem file tidak di-unmount, karena sedang sibuk, tetapi proses terkait membangunkan dan saya dapat menyelesaikan masalah tanpa melakukan boot ulang.

Valerio Di Giampietro
sumber
1

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, psdan top.

derobert
sumber
Saya meluncurkan beberapa proses menggunakan sekitar 10% dari total memori. Saya perhatikan bahwa banyak dari mereka berada dalam status D. Apakah ini karena IO lambat pada mesin khusus ini? Katakanlah saya memiliki 9 proses, mereka mungkin bersaing untuk IO dan banyak di antaranya berada dalam status D.
Kemin Zhou
@KeminZhou Dibandingkan dengan kecepatan CPU, I / O cukup lambat — bahkan I / O yang cepat. Proses berat I / O tunggal dapat dengan mudah menyibukkan disk magnetik, bahkan SSD. 10 Proses berat I / O bisa sangat sibuk.
derobert
1

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.

MarkR
sumber
0

Ya, tugas yang menunggu IO diblokir, dan tugas lain dijalankan. Memilih tugas berikutnya dilakukan oleh penjadwal Linux .

Martin v. Löwis
sumber
0

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.

Benno
sumber