GNU/Linux >> Belajar Linux >  >> Linux

Sinyal Linux – Contoh Program C untuk Menangkap Sinyal (SIGINT, SIGKILL, SIGSTOP, dll.)

Di bagian 1 dari seri Sinyal Linux, kita mempelajari tentang konsep dasar di balik sinyal Linux.

Berangkat dari bagian sebelumnya, dalam artikel ini kita akan belajar tentang cara menangkap sinyal dalam suatu proses. Kami akan menyajikan aspek praktis penanganan sinyal menggunakan cuplikan kode program C.

Menangkap Sinyal

Seperti yang telah dibahas pada artikel sebelumnya, Jika suatu proses ingin menangani sinyal tertentu maka dalam kode, proses tersebut harus mendaftarkan fungsi penanganan sinyal ke kernel.

Berikut ini adalah prototipe fungsi penanganan sinyal :

void <signal handler func name> (int sig)

Fungsi pengendali sinyal memiliki tipe pengembalian batal dan menerima nomor sinyal yang sesuai dengan sinyal yang perlu ditangani.

Untuk mendapatkan fungsi pengendali sinyal yang terdaftar ke kernel, penunjuk fungsi pengendali sinyal dilewatkan sebagai argumen kedua ke fungsi 'sinyal'. Prototipe dari fungsi sinyal adalah :

void (*signal(int signo, void (*func )(int)))(int);

Ini mungkin tampak seperti deklarasi yang rumit. Jika kita mencoba memecahkan kodenya :

  • Fungsi ini membutuhkan dua argumen.
  • Argumen pertama adalah bilangan bulat (signo) yang menggambarkan nomor sinyal atau nilai sinyal.
  • Argumen kedua adalah penunjuk ke fungsi pengendali sinyal yang menerima bilangan bulat sebagai argumen dan tidak mengembalikan apa pun (void).
  • Sementara fungsi 'sinyal' itu sendiri mengembalikan pointer fungsi yang tipe pengembaliannya batal.

Nah, untuk mempermudah, mari kita gunakan typedef :

typedef void sigfunc(int)

Jadi, di sini kami telah membuat tipe baru 'sigfunc'. Sekarang menggunakan typedef ini, jika kita mendesain ulang prototipe pengendali sinyal :

sigfunc *signal(int, sigfunc*);

Sekarang kita melihat bahwa lebih mudah untuk memahami bahwa fungsi pengendali sinyal menerima integer dan pointer fungsi tipe sigfunc saat mengembalikan pointer fungsi tipe sigfunc.

Contoh Program C untuk Menangkap Sinyal

Sebagian besar pengguna Linux menggunakan kombinasi tombol Ctr+C untuk menghentikan proses di Linux.

Pernahkah Anda memikirkan apa yang terjadi di balik ini. Nah, setiap kali ctrl+c ditekan, sinyal SIGINT dikirim ke proses. Tindakan default dari sinyal ini adalah untuk menghentikan proses. Tapi sinyal ini juga bisa ditangani. Kode berikut menunjukkan ini:

#include<stdio.h>
#include<signal.h>
#include<unistd.h>

void sig_handler(int signo)
{
  if (signo == SIGINT)
    printf("received SIGINT\n");
}

int main(void)
{
  if (signal(SIGINT, sig_handler) == SIG_ERR)
  printf("\ncan't catch SIGINT\n");
  // A long long wait so that we can easily issue a signal to this process
  while(1) 
    sleep(1);
  return 0;
}

Dalam kode di atas, kami telah mensimulasikan proses yang berjalan lama menggunakan loop while tak terbatas.

Fungsi sig_handler digunakan sebagai penangan sinyal. Fungsi ini didaftarkan ke kernel dengan meneruskannya sebagai argumen kedua dari 'sinyal' panggilan sistem dalam fungsi main(). Argumen pertama untuk fungsi 'sinyal' adalah sinyal yang kami maksudkan untuk ditangani oleh penangan sinyal yang dalam kasus ini adalah SIGINT.

Di samping catatan, penggunaan fungsi sleep(1) memiliki alasan di baliknya. Fungsi ini telah digunakan dalam perulangan while sehingga perulangan while dijalankan setelah beberapa waktu (yaitu satu detik dalam kasus ini). Ini menjadi penting karena jika tidak, loop while tak terbatas yang berjalan liar dapat menghabiskan sebagian besar CPU yang membuat komputer menjadi sangat lambat.

Bagaimanapun, kembali, ketika proses dijalankan dan kami mencoba untuk menghentikan proses menggunakan Ctrl+C:

$ ./sigfunc
^Creceived SIGINT
^Creceived SIGINT
^Creceived SIGINT
^Creceived SIGINT
^Creceived SIGINT
^Creceived SIGINT
^Creceived SIGINT

Kami melihat pada output di atas bahwa kami mencoba kombinasi tombol ctrl+c beberapa kali tetapi setiap kali proses tidak berhenti. Ini karena sinyal ditangani dalam kode dan ini dikonfirmasi dari cetakan yang kami dapatkan di setiap baris.

SIGKILL, SIGSTOP, dan Sinyal Buatan Pengguna

Selain menangani sinyal standar (seperti INT, TERM dll) yang tersedia. Kami juga dapat memiliki sinyal yang ditentukan pengguna yang dapat dikirim dan ditangani. Berikut adalah kode yang menangani sinyal yang ditentukan pengguna USR1 :

#include<stdio.h>
#include<signal.h>
#include<unistd.h>

void sig_handler(int signo)
{
    if (signo == SIGUSR1)
        printf("received SIGUSR1\n");
    else if (signo == SIGKILL)
        printf("received SIGKILL\n");
    else if (signo == SIGSTOP)
        printf("received SIGSTOP\n");
}

int main(void)
{
    if (signal(SIGUSR1, sig_handler) == SIG_ERR)
        printf("\ncan't catch SIGUSR1\n");
    if (signal(SIGKILL, sig_handler) == SIG_ERR)
        printf("\ncan't catch SIGKILL\n");
    if (signal(SIGSTOP, sig_handler) == SIG_ERR)
        printf("\ncan't catch SIGSTOP\n");
    // A long long wait so that we can easily issue a signal to this process
    while(1) 
        sleep(1);
    return 0;
}

Kami melihat bahwa dalam kode di atas, kami telah mencoba menangani sinyal yang ditentukan pengguna USR1. Juga, seperti yang kita ketahui bahwa dua sinyal KILL dan STOP tidak dapat ditangani. Jadi kami juga mencoba menangani kedua sinyal ini untuk melihat bagaimana panggilan sistem 'sinyal' merespons dalam kasus ini.

Ketika kita menjalankan kode di atas :

$ ./sigfunc

can't catch SIGKILL

can't catch SIGSTOP

Jadi output di atas memperjelas bahwa segera setelah 'sinyal' panggilan sistem mencoba mendaftarkan handler untuk sinyal KILL dan STOP, fungsi sinyal gagal menunjukkan bahwa kedua sinyal ini tidak dapat ditangkap.

Sekarang kami mencoba meneruskan sinyal USR1 ke proses ini menggunakan perintah kill:

$ kill -USR1 2678

dan pada terminal tempat program di atas dijalankan kita melihat :

$ ./sigfunc

can't catch SIGKILL

can't catch SIGSTOP
received SIGUSR1

Jadi kami melihat bahwa sinyal yang ditentukan pengguna USR1 diterima dalam proses dan ditangani dengan benar.


Linux
  1. Linux – Apa Cara Berbeda Untuk Mengatur Izin File Dll Di Gnu/linux?

  2. Apa yang Dilakukan Program Saat Mengirim Sinyal Sigkill?

  3. Cobol Hello World Contoh:Cara Menulis, Mengkompilasi dan Menjalankan Program Cobol di OS Linux

  1. Tcl Hello World Contoh:Cara Menulis, Mengkompilasi dan Menjalankan Program Tcl di OS Linux

  2. 13 Panggilan Sistem Linux Dasar Dijelaskan menggunakan Program Virus Linux yang Menyenangkan

  3. Cara Membuat Thread di Linux (Dengan Program Contoh C)

  1. memanggil fungsi ketika program selesai dengan ctrl c

  2. Bagaimana SIGINT berhubungan dengan sinyal terminasi lainnya seperti SIGTERM, SIGQUIT dan SIGKILL?

  3. Apa yang terjadi saat mengirim SIGKILL ke Proses Zombie di Linux?