Dari membaca halaman manual pada read()
dan write()
panggilan tampaknya panggilan ini akan terganggu oleh sinyal terlepas dari apakah mereka harus memblokir atau tidak.
Secara khusus, asumsikan
- suatu proses menetapkan handler untuk beberapa sinyal.
- perangkat dibuka (katakanlah, terminal) dengan
O_NONBLOCK
tidak diatur (yaitu beroperasi dalam mode pemblokiran) - proses kemudian membuat
read()
panggilan sistem untuk membaca dari perangkat dan sebagai hasilnya menjalankan jalur kontrol kernel di ruang-kernel. - sementara precess mengeksekusi
read()
di dalam ruang kernel, sinyal di mana handler dipasang sebelumnya dikirim ke proses itu dan handler sinyal dipanggil.
Membaca halaman manual dan bagian yang sesuai di SUSv3 'Volume Antarmuka Sistem (XSH)' , orang menemukan bahwa:
saya. Jika a read()
terganggu oleh sinyal sebelum membaca data apa pun (yaitu harus memblokir karena tidak ada data), ia mengembalikan -1 dengan errno
set ke [EINTR].
ii. Jika a read()
terputus oleh sinyal setelah berhasil membaca beberapa data (yaitu mungkin untuk segera mulai melayani permintaan), ia mengembalikan jumlah byte yang dibaca.
Pertanyaan A):
Apakah saya benar mengasumsikan bahwa dalam kedua kasus (blok / tidak ada blok) pengiriman dan penanganan sinyal tidak sepenuhnya transparan kepada read()
?
Kasus i. tampaknya dapat dimengerti karena pemblokiran read()
biasanya akan menempatkan proses dalam TASK_INTERRUPTIBLE
keadaan sehingga ketika suatu sinyal dikirimkan, kernel menempatkan proses ke dalam TASK_RUNNING
keadaan.
Namun ketika read()
tidak perlu memblokir (kasus ii.) Dan sedang memproses permintaan di kernel-space, saya akan berpikir bahwa kedatangan sinyal dan penanganannya akan transparan seperti kedatangan dan penanganan yang tepat dari HW akan mengganggu. Khususnya saya akan berasumsi bahwa setelah pengiriman sinyal, proses akan sementara ditempatkan ke mode pengguna untuk menjalankan penangan sinyal dari mana ia akan kembali pada akhirnya untuk menyelesaikan pemrosesan yang terputus read()
(dalam ruang kernel) sehingga read()
menjalankan Tentu saja sampai selesai setelah proses kembali ke titik tepat setelah panggilan ke read()
(dalam ruang pengguna), dengan semua byte yang tersedia dibaca sebagai hasilnya.
Tapi ii. tampaknya menyiratkan bahwa read()
terputus, karena data tersedia segera, tetapi mengembalikan hanya beberapa data (bukan semua).
Ini membawa saya ke pertanyaan kedua (dan terakhir) saya:
Pertanyaan B):
Jika asumsi saya di bawah A) benar, mengapa read()
bisa terganggu, meskipun tidak perlu diblokir karena ada data yang tersedia untuk memenuhi permintaan segera? Dengan kata lain, mengapa yang read()
tidak dilanjutkan setelah mengeksekusi penangan sinyal, akhirnya menghasilkan semua data yang tersedia (yang tersedia setelah semua) dikembalikan?
sumber
Untuk menjawab pertanyaan A :
Ya, pengiriman dan penanganan sinyal tidak sepenuhnya transparan untuk
read()
.The
read()
setengah berlari dapat menduduki beberapa sumber sementara itu terganggu oleh sinyal. Dan pengendali sinyal dapat memanggil yang lainread()
(atau syscall safe-signal async lainnya ) juga. Jadiread()
terganggu oleh sinyal harus dihentikan terlebih dahulu untuk melepaskan sumber daya yang digunakannya, jika tidakread()
dipanggil dari penangan sinyal akan mengakses sumber daya yang sama dan menyebabkan masalah reentrant.Karena panggilan sistem selain
read()
dapat dipanggil dari penangan sinyal dan mereka juga dapat menempati rangkaian sumber daya yang sama sepertiread()
halnya. Untuk menghindari masalah reentrant di atas, desain yang paling sederhana dan teraman adalah menghentikan interupsiread()
setiap kali ketika sinyal terjadi selama menjalankannya.sumber