Pemrograman C

Cara menggunakan penangan sinyal dalam bahasa C?

Cara menggunakan penangan sinyal dalam bahasa C?
Pada artikel ini kami akan menunjukkan cara menggunakan penangan sinyal di Linux menggunakan bahasa C. Tetapi pertama-tama kita akan membahas apa itu sinyal, bagaimana sinyal itu akan menghasilkan beberapa sinyal umum yang dapat Anda gunakan dalam program Anda dan kemudian kita akan melihat bagaimana berbagai sinyal dapat ditangani oleh suatu program saat program dijalankan. Jadi ayo mulai.

Sinyal

Sinyal adalah peristiwa yang dihasilkan untuk memberi tahu proses atau utas bahwa beberapa situasi penting telah tiba. Ketika sebuah proses atau thread telah menerima sinyal, proses atau thread akan menghentikan apa yang dilakukannya dan mengambil beberapa tindakan. Sinyal mungkin berguna untuk komunikasi antar-proses.

Sinyal Standar

Sinyal didefinisikan dalam file header sinyal.h sebagai konstanta makro. Nama sinyal dimulai dengan "SIG" dan diikuti dengan deskripsi singkat tentang sinyal. Jadi, setiap sinyal memiliki nilai numerik yang unik. Program Anda harus selalu menggunakan nama sinyal, bukan nomor sinyal. Alasannya adalah nomor sinyal dapat berbeda menurut sistem tetapi arti nama akan menjadi standar.

makro NSIG adalah jumlah total sinyal yang ditentukan. Nilai dari NSIG adalah satu lebih besar dari jumlah total sinyal yang ditentukan (Semua nomor sinyal dialokasikan secara berurutan).

Berikut ini adalah sinyal standar:

Nama Sinyal Deskripsi
SIGHUP Tutup prosesnya. Sinyal SIGHUP digunakan untuk melaporkan pemutusan terminal pengguna, mungkin karena koneksi jarak jauh hilang atau hang.
TANDA Mengganggu proses. Ketika pengguna mengetik karakter INTR (biasanya Ctrl + C) sinyal SIGINT dikirim.
SIGQUIT Keluar dari proses. Ketika pengguna mengetik karakter QUIT (biasanya Ctrl + \) sinyal SIGQUIT dikirim.
SIGILL Instruksi ilegal. Ketika upaya dilakukan untuk mengeksekusi instruksi sampah atau hak istimewa, sinyal SIGILL dihasilkan. Juga, SIGILL dapat dihasilkan ketika tumpukan meluap, atau ketika sistem mengalami kesulitan menjalankan penangan sinyal.
SIGTRAP Jejak jebakan. Instruksi breakpoint dan instruksi trap lainnya akan menghasilkan sinyal SIGTRAP. Debugger menggunakan sinyal ini.
SIGABRT Menggugurkan. Sinyal SIGABRT dihasilkan saat fungsi abort() dipanggil. Sinyal ini menunjukkan kesalahan yang dideteksi oleh program itu sendiri dan dilaporkan oleh panggilan fungsi abort().
SIGFPE Pengecualian floating-point. Ketika kesalahan aritmatika fatal terjadi, sinyal SIGFPE dihasilkan.
SIGUSR1 dan SIGUSR2 Sinyal SIGUSR1 dan SIGUSR2 dapat digunakan sesuai keinginan. Berguna untuk menulis penangan sinyal untuk mereka dalam program yang menerima sinyal untuk komunikasi antar-proses yang sederhana simple.

Tindakan Default Sinyal

Setiap sinyal memiliki tindakan default, salah satu dari berikut ini:

Istilah: Proses akan berakhir.
Inti: Proses akan berhenti dan menghasilkan file dump inti.
tanda: Proses akan mengabaikan sinyal.
Berhenti: Proses akan berhenti.
Lanjutan: Proses akan berlanjut dari dihentikan being.

Tindakan default dapat diubah menggunakan fungsi handler. Tindakan default beberapa sinyal tidak dapat diubah. SIGKILL dan SIGABRT tindakan default sinyal tidak dapat diubah atau diabaikan.

Penanganan Sinyal

Jika suatu proses menerima sinyal, proses tersebut memiliki pilihan tindakan untuk jenis sinyal tersebut. Proses dapat mengabaikan sinyal, dapat menentukan fungsi handler, atau menerima tindakan default untuk jenis sinyal tersebut.

Kami dapat menangani sinyal menggunakan sinyal atau sigasi fungsi. Di sini kita melihat bagaimana yang paling sederhana sinyal() fungsi digunakan untuk menangani sinyal.

int sinyal () (int tanda, batal (*fungsi)(int))

Itu sinyal() akan memanggil fungsi berfungsi jika proses menerima sinyal tanda tangan. Itu sinyal() mengembalikan pointer ke fungsi fungsi jika berhasil atau mengembalikan kesalahan ke errno dan -1 sebaliknya.

Itu fungsi pointer dapat memiliki tiga nilai:

  1. SIG_DFL: Ini adalah penunjuk ke fungsi default sistem SIG_DFL(), dideklarasikan dalam h file header. Ini digunakan untuk mengambil tindakan default dari sinyal.
  2. SIG_IGN: Ini adalah penunjuk ke fungsi abaikan sistem SIG_IGN(),dideklarasikan dalam h file header.
  3. Penunjuk fungsi penangan yang ditentukan pengguna: Jenis fungsi handler yang ditentukan pengguna adalah batal(*)(int), berarti tipe pengembalian batal dan satu argumen tipe int.

Contoh Penangan Sinyal Dasar

#termasuk
#termasuk
#termasuk
void sig_handler(int signum)
//Tipe kembalian fungsi handler harus batal
printf("\nFungsi pengendali di dalam\n");

int utama()
sinyal(SIGINT,sig_handler); // Daftarkan penangan sinyal
for(int i=1;;i++)    //Infinite loop
printf("%d : Di dalam fungsi utama\n",i);
tidur(1); // Tunda selama 1 detik

kembali 0;

Dalam tangkapan layar dari output Contoh1.c, kita dapat melihat bahwa dalam fungsi utama infinite loop sedang dieksekusi. Saat pengguna mengetik Ctrl+C, eksekusi fungsi utama berhenti dan fungsi pengendali sinyal dipanggil. Setelah menyelesaikan fungsi handler, eksekusi fungsi utama dilanjutkan. Saat pengguna mengetik Ctrl+\, prosesnya berhenti.

Abaikan Sinyal Contoh

#termasuk
#termasuk
#termasuk
int utama()
sinyal(SIGINT,SIG_IGN); // Daftarkan penangan sinyal untuk mengabaikan sinyal
for(int i=1;;i++)    //Loop tak terbatas
printf("%d : Di dalam fungsi utama\n",i);
tidur(1); // Tunda selama 1 detik

kembali 0;

Di sini fungsi handler adalah mendaftar ke SIG_IGN() fungsi untuk mengabaikan aksi sinyal. Jadi, ketika pengguna mengetik Ctrl+C,  TANDA TANGAN sinyal dihasilkan tetapi aksinya diabaikan.

Daftar Ulang Contoh Penangan Sinyal

#termasuk
#termasuk
#termasuk
void sig_handler(int tanda tangan)
printf("\nFungsi pengendali di dalam\n");
sinyal(SIGINT,SIG_DFL); // Daftarkan ulang penangan sinyal untuk tindakan default

int utama()
sinyal(SIGINT,sig_handler); // Daftarkan penangan sinyal
for(int i=1;;i++)    //Infinite loop
printf("%d : Di dalam fungsi utama\n",i);
tidur(1); // Tunda selama 1 detik

kembali 0;

Di tangkapan layar dari output Contoh3.c, kita dapat melihat bahwa ketika pengguna pertama kali mengetik Ctrl+C, fungsi handler dipanggil. Dalam fungsi handler, handler sinyal mendaftar ulang ke SIG_DFL untuk tindakan default dari sinyal. Ketika pengguna mengetik Ctrl+C untuk kedua kalinya, proses dihentikan yang merupakan tindakan default TANDA TANGAN sinyal.

Mengirim Sinyal:

Suatu proses juga dapat secara eksplisit mengirim sinyal ke dirinya sendiri atau ke proses lain. fungsi raise() dan kill() dapat digunakan untuk mengirim sinyal. Kedua fungsi dideklarasikan dalam sinyal.h file header.

int kenaikan (int tanda)

Fungsi raise() digunakan untuk mengirim sinyal tanda tangan ke proses pemanggilan (sendiri). Ini mengembalikan nol jika berhasil dan nilai bukan nol jika gagal.

int kill(pid_t pid, int signum)

Fungsi mematikan yang digunakan untuk mengirim sinyal tanda tangan ke proses atau grup proses yang ditentukan oleh pid.

Contoh Penangan Sinyal SIGUSR1

#termasuk
#termasuk
void sig_handler(int signum)
printf("Fungsi pengendali di dalam\n");

int utama()
sinyal(SIGUSR1,sig_handler); // Daftarkan penangan sinyal
printf("Di dalam fungsi utama\n");
menaikkan (SIGUSR1);
printf("Di dalam fungsi utama\n");
kembali 0;

Di sini, proses mengirim sinyal SIGUSR1 ke dirinya sendiri menggunakan fungsi raise().

Raise dengan Kill Contoh Program

#termasuk
#termasuk
#termasuk
void sig_handler(int tanda tangan)
printf("Fungsi pengendali di dalam\n");

int utama()
pid_t pid;
sinyal(SIGUSR1,sig_handler); // Daftarkan penangan sinyal
printf("Di dalam fungsi utama\n");
pid=getpid(); //Proses ID itu sendiri
membunuh(pid,SIGUSR1); // Kirim SIGUSR1 ke dirinya sendiri
printf("Di dalam fungsi utama\n");
kembali 0;

Di sini, proses kirim SIGUSR1 sinyal ke dirinya sendiri menggunakan membunuh() fungsi. getpid() digunakan untuk mendapatkan ID proses itu sendiri.

Pada contoh berikutnya kita akan melihat bagaimana proses induk dan anak berkomunikasi (Inter Process Communication) menggunakan membunuh() dan fungsi sinyal.

Komunikasi Orang Tua Anak dengan Sinyal

#termasuk
#termasuk
#termasuk
#termasuk
void sig_handler_parent(int signum)
printf("Induk : Menerima sinyal respon dari anak \n");

void sig_handler_child(int signum)
printf("Anak : Menerima sinyal dari induk \n");
tidur(1);
membunuh(getppid(),SIGUSR1);

int utama()
pid_t pid;
jika((pid=garpu())<0)
printf("Gagal Garpu\n");
keluar(1);

/* Proses Anak */
lain jika(pid==0)
sinyal(SIGUSR1,sig_handler_child); // Daftarkan penangan sinyal
printf("Anak: menunggu sinyal\n");
berhenti sebentar();

/* Proses Induk */
lain
sinyal(SIGUSR1,sig_handler_parent); // Daftarkan penangan sinyal
tidur(1);
printf("Induk: mengirim sinyal ke Anak\n");
membunuh(pid,SIGUSR1);
printf("Induk: menunggu jawaban\n");
berhenti sebentar();

kembali 0;

Sini, garpu() fungsi membuat proses anak dan mengembalikan nol ke proses anak dan ID proses anak ke proses induk. Jadi, pid telah diperiksa untuk memutuskan proses orang tua dan anak. Dalam proses induk, ia tidur selama 1 detik sehingga proses anak dapat mendaftarkan fungsi pengendali sinyal dan menunggu sinyal dari induk. Setelah 1 detik proses induk kirim SIGUSR1 sinyal ke proses anak dan tunggu sinyal respons dari anak. Dalam proses anak, pertama menunggu sinyal dari orang tua dan ketika sinyal diterima, fungsi handler dipanggil. Dari fungsi handler, proses anak mengirimkan yang lain SIGUSR1 sinyal ke orang tua. Sini getppid() fungsi digunakan untuk mendapatkan ID proses induk.

Kesimpulan

Sinyal di Linux adalah topik besar. Pada artikel ini kita telah melihat bagaimana menangani sinyal dari yang paling dasar, dan juga mendapatkan pengetahuan bagaimana sinyal dihasilkan, bagaimana suatu proses dapat mengirim sinyal ke dirinya sendiri dan proses lainnya, bagaimana sinyal dapat digunakan untuk komunikasi antar proses.

5 Game Arkade Terbaik untuk Linux
Saat ini, komputer adalah mesin serius yang digunakan untuk bermain game. Jika Anda tidak bisa mendapatkan skor tinggi baru, Anda akan tahu apa yang s...
Pertempuran Untuk Wesnoth 1.13.6 Pengembangan Dirilis
Pertempuran Untuk Westnoth 1.13.6 dirilis bulan lalu, adalah rilis pengembangan keenam dalam 1.13.x series dan memberikan sejumlah peningkatan, teruta...
Cara Menginstal League Of Legends di Ubuntu 14.04
Jika Anda adalah penggemar League of Legends, maka ini adalah kesempatan bagi Anda untuk menguji coba League of Legends. Perhatikan bahwa LOL didukung...