天天看點

Linux應用程式設計---12.信号Linux應用程式設計—12.信号

Linux應用程式設計—12.信号

​ 信号用于核心層與應用層之間、應用層與應用層之間傳遞控制指令。在終端下面通過鍵盤輸入“Ctrl + C”就是向作業系統發送了一個控制指令,告訴系統結束目前程序。

​ 在終端下輸入“kill -l”即可檢視系統支援的是以控制指令。如下圖1所示。

Linux應用程式設計---12.信号Linux應用程式設計—12.信号

圖1 檢視所有控制指令

​ 如圖所示,一共有64個指令。經常使用的“Ctrl + C”就是9号:SIGINT指令,用來結束目前程序。如果父子程序同時運作,在中斷下輸入“Ctrl + C”隻能終止父程序,子程序還在運作。這種情況,我們可以通過控制指令“kill”來結束這個子程序。

​ 檢視控制指令“kill”的說明。

NAME
       kill - send a signal to a process

SYNOPSIS
       kill [options] <pid> [...]

DESCRIPTION
       The  default  signal  for kill is TERM.  Use -l or -L to list available
       signals.  Particularly useful signals include  HUP,  INT,  KILL,  STOP,
       CONT,  and  0.   Alternate  signals may be specified in three ways: -9,
       -SIGKILL or -KILL.  Negative PID values may be  used  to  choose  whole
       process  groups; see the PGID column in ps command output.  A PID of -1
       is special; it indicates all processes except the kill  process  itself
       and init.
           

​ kill指令的作用是發送一個信号到程序。預設情況下這個kill信号是結束程序“TERM”。假如結束程序id号為:7436的程序。在在中斷下輸入:kill 7436即可。

12.1 signal()函數用來改變信号的處理

​ 函數原型,sighandler_t signal(int signum, sighandler_t handler);其中handler是函數指針,typedef void (*sighandler_t)(int);當觸發了某一個信号,會去執行handler入口的函數。原本“SIGINT”的預設功能是結束目前程序,但是如果使用signal()函數重新處理後,當觸發到“SIGINT”後,轉去執行handler函數,覆寫了以前的功能。設計這樣一段程式,使用signal()函數重新改寫SIGINT,當鍵盤輸入“Ctrl + C”後,列印字元串“SIGINT triged.”,然後代碼每隔1秒鐘列印計數值一次。為了友善後續終止這個程序,列印目前程序id号,供終端關閉該程序。

​ 代碼如下:

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

void function(int signl);

int main(void)
{
        int i = 0;
        signal(SIGINT, function);

        printf("Process pid = %d\n.", getpid());

        while(1)
        {
                printf("Count to %d.\n", ++i);
                sleep(1);
        }


        return 0;
}


void function(int signl)
{
        printf("SIGINT triged.\n");
}
           

​ 運作結果:

Linux應用程式設計---12.信号Linux應用程式設計—12.信号

圖2 運作結果

​ 當使用者輸入“Ctrl + C”時,沒有結束目前程序,計數繼續,并且列印SIGINT triged.代碼運作符合預期。結束目前程序可以通過另一個終端輸入:kill 10773.結果如下圖3所示:

Linux應用程式設計---12.信号Linux應用程式設計—12.信号

圖3 通過kill指令結束程序

​ 改寫代碼,使之具有之前的功能——結束目前程序,隻需在被觸發調用的函數後面加上一個退出即可。exit(1)。修改後代碼如下:

void function(int signl)
{
        printf("SIGINT triged.\n");
    	exit(1);
}
           

​ 運作結果如下:

Linux應用程式設計---12.信号Linux應用程式設計—12.信号

圖4 運作結果

12.2 kill()函數

​ kill()函數是向一個程序發送信号。函數原型如下:int kill(pid_t pid, int sig);入參分别是程序id号pid與信号。傳回值,成功:0;失敗:-1。

​ 編寫一段代碼,通過main()函數入參傳入程序id号,并且代碼中通過調用kill()函數将這個程序終止。

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

int main(int *argc, char *argv[])
{
    kill(atoi(argv[1]), SIGKILL);
    
    return 0;
}
           

​ 通過gcc編譯為KILL 可執行檔案,

​ 在終端啟動上一個代碼,代碼正常運作,并且列印程序id号:11099,在另一個終端中執行:./KILL 11099,11099的程序結束。運作結果如下圖5所示:

Linux應用程式設計---12.信号Linux應用程式設計—12.信号

圖5 運作結果

12.3 總結

​ 信号用于核心層與應用層、應用層與應用層之間傳遞控制指令。Linux下有64種信号類型。使用signal()函數可以改寫信号的作用,但有的信号不支援。kill()函數可以向一個程序發送某個信号。

Linux應用程式設計---12.信号Linux應用程式設計—12.信号

繼續閱讀