Ketika suatu proses pada mode pengguna, itu dapat terganggu kapan saja (beralih ke mode kernel). Ketika kernel kembali ke mode pengguna, ia memeriksa apakah ada sinyal yang tertunda (termasuk yang digunakan untuk mematikan proses, seperti SIGTERM
dan SIGKILL
). Ini berarti suatu proses dapat dibunuh hanya setelah kembali ke mode pengguna.
Alasan suatu proses tidak dapat dimatikan dalam mode kernel adalah karena berpotensi merusak struktur kernel yang digunakan oleh semua proses lain di mesin yang sama (cara yang sama membunuh thread dapat berpotensi merusak struktur data yang digunakan oleh utas lain dalam proses yang sama) .
Ketika kernel perlu melakukan sesuatu yang bisa memakan waktu lama (menunggu pada pipa yang ditulis oleh proses lain atau menunggu perangkat keras untuk melakukan sesuatu, misalnya), ia tidur dengan menandai dirinya sebagai tidur dan memanggil penjadwal untuk beralih ke yang lain. proses (jika tidak ada proses non-tidur, itu beralih ke proses "dummy" yang memberitahu CPU untuk sedikit memperlambat dan duduk dalam satu lingkaran - loop menganggur).
Jika sinyal dikirim ke proses tidur, itu harus dibangunkan sebelum akan kembali ke ruang pengguna dan dengan demikian memproses sinyal yang tertunda. Di sini kita memiliki perbedaan antara dua jenis tidur utama:
TASK_INTERRUPTIBLE
, tidur yang terputus. Jika suatu tugas ditandai dengan bendera ini, ia sedang tidur, tetapi dapat dibangunkan oleh sinyal. Ini berarti kode yang menandai tugas sebagai tidur mengharapkan sinyal yang mungkin, dan setelah bangun akan memeriksanya dan kembali dari panggilan sistem. Setelah sinyal ditangani, panggilan sistem berpotensi dapat dimulai kembali secara otomatis (dan saya tidak akan menjelaskan lebih lanjut tentang cara kerjanya).
TASK_UNINTERRUPTIBLE
, tidur tanpa gangguan. Jika tugas ditandai dengan bendera ini, ia tidak diharapkan dibangunkan oleh apa pun selain apa pun yang ditunggu, baik karena tidak dapat dengan mudah dimulai kembali, atau karena program mengharapkan panggilan sistem menjadi atom. Ini juga dapat digunakan untuk tidur yang dikenal sangat singkat.
TASK_KILLABLE
(disebutkan dalam artikel LWN yang ditautkan oleh jawaban ddaa) adalah varian baru.
Ini menjawab pertanyaan pertama Anda. Mengenai pertanyaan kedua Anda: Anda tidak dapat menghindari tidur tanpa gangguan, mereka adalah hal yang normal (itu terjadi, misalnya, setiap kali proses membaca / menulis dari / ke disk); Namun, mereka harus bertahan hanya sepersekian detik. Jika mereka bertahan lebih lama, biasanya itu berarti masalah perangkat keras (atau masalah driver perangkat, yang terlihat sama dengan kernel), di mana driver perangkat sedang menunggu perangkat keras untuk melakukan sesuatu yang tidak akan pernah terjadi. Ini juga bisa berarti Anda menggunakan NFS dan server NFS sedang down (menunggu server untuk pulih; Anda juga dapat menggunakan opsi "intr" untuk menghindari masalah).
Akhirnya, alasan Anda tidak dapat memulihkan adalah alasan yang sama dengan kernel menunggu sampai kembali ke mode pengguna untuk mengirimkan sinyal atau mematikan proses: itu berpotensi merusak struktur data kernel (kode menunggu pada tidur interruptible dapat menerima kesalahan yang memberitahu itu untuk kembali ke ruang pengguna, tempat proses dapat dimatikan; kode yang menunggu pada waktu tidur tanpa gangguan tidak mengharapkan kesalahan).
TASK_UNINTERUPTIBLE
keadaan kapan pun sistem tidak dalam keadaan diam, sehingga dengan paksa mengumpulkan data, menunggu untuk mengirimkan begitu pengguna super keluar? Ini akan menjadi tambang emas bagi peretas untuk mengambil informasi, kembali ke keadaan zombie, dan mengirimkan informasi melalui jaringan saat idle. Beberapa dapat berpendapat bahwa ini adalah salah satu cara untuk menciptakanBlackdoor
kekuatan untuk itu, untuk masuk dan keluar dari sistem apa pun yang diinginkan. Saya sangat percaya celah ini bisa disegel untuk selamanya, dengan menghilangkan `TASK_UNINTERUPTIB