Apa yang menyebabkan berbagai sinyal dikirim?

28

Terkadang saya sedikit bingung dengan semua sinyal yang dapat diterima oleh suatu proses. Seperti yang saya pahami, suatu proses memiliki pengendali default ( disposisi sinyal ) untuk masing-masing sinyal ini, tetapi ia dapat menyediakan pengendali sendiri dengan memanggil sigaction().

Jadi inilah pertanyaan saya: apa yang menyebabkan setiap sinyal dikirim? Saya menyadari bahwa Anda dapat secara manual mengirim sinyal ke proses yang sedang berjalan melalui -sparameter kill, tetapi bagaimana keadaan alami di mana sinyal ini dikirim? Misalnya, kapan SIGINTdikirim?

Juga, apakah ada batasan pada sinyal yang dapat ditangani? Dapatkah bahkan SIGSEGVsinyal diproses dan kontrol dikembalikan ke aplikasi?

Nathan Osman
sumber
Jawaban yang tepat untuk ini akan menjadi epik, dan pada dasarnya mereplikasi informasi dalam artikel Wikipedia tentang masalah ini, jadi saya hanya akan menunjuk ke sana.
Shawn J. Goff
@Shawn: Artikel Wikipedia memiliki daftar sinyal, tetapi tidak ada presentasi yang jelas tentang siapa yang mengirim sinyal apa.
Gilles 'SO- stop being evil'

Jawaban:

41

Selain proses pemanggilan kill(2), beberapa sinyal dikirim oleh kernel (atau terkadang oleh proses itu sendiri) dalam berbagai keadaan:

  • Driver terminal mengirim sinyal yang sesuai dengan berbagai acara:
    • Pemberitahuan kunci: SIGINT(harap kembali ke loop utama) pada Ctrl+ C, SIGQUIT(silakan segera berhenti) pada Ctrl+ \, SIGTSTP(harap ditangguhkan) pada Ctrl+ Z. Kunci dapat diubah dengan sttyperintah.
    • SIGTTINdan SIGTTOUdikirim ketika proses latar belakang mencoba membaca atau menulis ke terminal pengendali.
    • SIGWINCH dikirim untuk memberi sinyal bahwa ukuran jendela terminal telah berubah.
    • SIGHUPdikirim ke sinyal bahwa terminal telah menghilang (historis karena modem Anda memiliki h ung up , saat ini biasanya karena Anda telah menutup jendela terminal emulator).
  • Beberapa perangkap prosesor dapat menghasilkan sinyal. Detailnya tergantung arsitektur dan sistem; berikut adalah contoh khasnya:
    • SIGBUS untuk memori akses yang tidak selaras;
    • SIGSEGV untuk akses ke halaman yang belum dipetakan;
    • SIGILL untuk instruksi ilegal (opcode buruk);
    • SIGFPEuntuk instruksi floating-point dengan argumen buruk (misalnya sqrt(-1)).
  • Sejumlah sinyal memberi tahu proses target bahwa beberapa peristiwa sistem telah terjadi:
    • SIGALRMmemberitahukan bahwa pengatur waktu yang diatur oleh proses telah kedaluwarsa. Pengatur waktu dapat diatur dengan alarm, setitimerdan lainnya.
    • SIGCHLD memberi tahu proses bahwa salah satu anaknya mati.
    • SIGPIPEdihasilkan ketika suatu proses mencoba untuk menulis ke pipa ketika ujung bacaan telah ditutup (idenya adalah bahwa jika Anda berlari foo | bardan barkeluar, footerbunuh oleh a SIGPIPE).
    • SIGPOLL(Disebut juga SIGIO) memberi tahu proses terjadinya suatu peristiwa yang dapat disurvei. POSIX menentukan acara yang dapat dipantau yang terdaftar melalui I_SETSIG ioctl. Banyak sistem memungkinkan acara yang dapat di-polling pada deskriptor file apa pun, ditetapkan melalui O_ASYNC fcntlflag. Sinyal terkait adalah SIGURG, yang memberitahukan data mendesak pada perangkat (terdaftar melalui I_SETSIG ioctl) atau soket .
    • Pada beberapa sistem, SIGPWRdikirim ke semua proses ketika UPS memberi sinyal bahwa kegagalan daya akan segera terjadi.

Daftar ini tidak lengkap. Sinyal standar didefinisikan dalam signal.h.

Sebagian besar sinyal dapat ditangkap dan ditangani (atau diabaikan) oleh aplikasi. Dua sinyal portabel yang tidak dapat ditangkap adalah SIGKILL(mati saja) dan STOP(hentikan eksekusi).

SIGSEGV( kesalahan segmentasi ) dan sepupunya SIGBUS( kesalahan bus ) dapat ditangkap, tapi itu ide yang buruk kecuali Anda benar-benar tahu apa yang Anda lakukan. Aplikasi umum untuk menangkap mereka adalah mencetak jejak tumpukan atau informasi debug lainnya. Aplikasi yang lebih maju adalah untuk menerapkan semacam manajemen memori dalam proses, atau untuk menjebak instruksi buruk di mesin mesin virtual.

Akhirnya, izinkan saya menyebutkan sesuatu yang bukan sinyal. Ketika Anda menekan Ctrl+ Ddi awal baris dalam program yang membaca input dari terminal, ini memberi tahu program bahwa akhir file input tercapai. Ini bukan sinyal: itu ditransmisikan melalui API input / output. Seperti Ctrl+ Cdan teman-teman, kunci dapat dikonfigurasi dengan stty.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Dan SIGHUP, modem Anda telah menutup telepon. :-)
Keith
1
Satu hal yang perlu diperhatikan SIGFPE:, agak tidak sengaja, juga ditandai pada integer divide-by-zero, dan kadang-kadang pada integer yang ditandatangani overflow.
ephemient
18

Untuk menjawab pertanyaan kedua Anda terlebih dahulu: SIGSTOPdan SIGKILLtidak dapat ditangkap oleh aplikasi, tetapi setiap sinyal lainnya dapat, bahkan SIGSEGV. Properti ini berguna untuk debugging - misalnya, dengan dukungan pustaka yang tepat, Anda bisa mendengarkan SIGSEGVdan membuat stack backtrace untuk menunjukkan di mana segfault itu terjadi.

Kata resmi (untuk Linux, apa pun yang dilakukan setiap sinyal tersedia dengan mengetikkan man 7 signaldari baris perintah Linux. http://linux.die.net/man/7/signal memiliki informasi yang sama, tetapi tabel lebih sulit dibaca.

Namun, tanpa beberapa pengalaman dengan sinyal, sulit untuk mengetahui dari uraian singkat apa yang mereka lakukan dalam praktik, jadi inilah interpretasi saya:

Dipicu dari keyboard

  • SIGINTterjadi ketika Anda menekan CTRL+C.
  • SIGQUITdipicu oleh CTRL+\, dan dump inti.
  • SIGTSTPmenunda program Anda ketika Anda menekan CTRL+Z. Tidak seperti SIGSTOPitu, itu dapat ditangkap, yang memberikan program seperti vikesempatan untuk mengatur ulang terminal ke keadaan aman sebelum menangguhkan diri.

Interaksi terminal

  • SIGHUP ("hangup") adalah apa yang terjadi ketika Anda menutup xterm (atau memutuskan terminal) saat program Anda sedang berjalan.
  • SIGTTINdan SIGTTOUjeda program Anda jika mencoba membaca dari atau menulis ke terminal saat sedang berjalan di latar belakang. Agar SIGTTOUterjadi, saya pikir program perlu ditulis /dev/tty, bukan hanya stdout default.

Dipicu oleh pengecualian CPU

Ini berarti program Anda mencoba melakukan sesuatu yang salah.

  • SIGILLberarti instruksi prosesor yang ilegal atau tidak dikenal. Ini mungkin terjadi jika Anda mencoba mengakses port I / O prosesor secara langsung, misalnya.
  • SIGFPEberarti ada kesalahan matematika perangkat keras; kemungkinan besar program mencoba membaginya dengan nol.
  • SIGSEGV berarti program Anda mencoba mengakses wilayah memori yang belum dipetakan.
  • SIGBUSberarti program mengakses memori dengan cara yang salah; Saya tidak akan membahas detail untuk ringkasan ini.

Interaksi proses

  • SIGPIPEterjadi jika Anda mencoba menulis ke pipa setelah pembaca pipa menutup ujungnya. Lihat man 7 pipe.
  • SIGCHLDterjadi ketika proses anak yang Anda buat berhenti atau ditangguhkan (oleh SIGSTOPatau serupa).

Berguna untuk pensinyalan diri

  • SIGABRTbiasanya disebabkan oleh program yang memanggil abort()fungsi, dan menyebabkan dump inti secara default. Semacam "tombol panik".
  • SIGALRMdisebabkan oleh alarm()panggilan sistem, yang akan menyebabkan kernel mengirimkan SIGALRMke program setelah beberapa detik. Lihat man 2 alarmdan man 2 sleep.
  • SIGUSR1dan SIGUSR2bagaimanapun digunakan program suka. Mereka bisa berguna untuk pensinyalan antar proses.

Dikirim oleh administrator

Sinyal-sinyal ini biasanya dikirim dari command prompt, melalui killperintah, atau fgatau bgdalam kasus SIGCONT.

  • SIGKILLdan SIGSTOPmerupakan sinyal yang tidak dapat diblokir. Yang pertama selalu mengakhiri proses segera; yang kedua menunda proses.
  • SIGCONT melanjutkan proses yang ditangguhkan.
  • SIGTERMadalah versi yang dapat ditangkap SIGKILL.
Jander
sumber
Sinyal mana yang dikirim saat shutdownperintah digunakan?
Nathan Osman
Itu tergantung pada skrip shutdown. Biasanya, SIGTERMdikirim terlebih dahulu, diikuti dengan penundaan, diikuti oleh SIGKILL. Pada prinsipnya, untuk shutdown yang keras dan langsung, kernel tidak perlu mengirim sinyal sama sekali; itu bisa berhenti menjalankan proses.
Jander