各位看官們,大家好,上一回中咱們說的是使用信號進行進程間通信的例子,這一回咱們接著上一回的內容,繼續說該例子。閒話休提,言歸正轉。讓我們一起talk C栗子吧!
我們在上一回中舉了使用信號進行進程間通信的例子,在該例子中,我們通過終端發出信號,當進程收到該信號後讓它執行系統對信號定義的默認動作。這一回,我們再來舉一個使用信號進行進程間通信的例子,不過,我們發送和處理信號的方式和上一回的例子不一樣。在接下來的例子中,我們在一個進程中使用kill產生信號,在另外一個進程中接收並且按照自己的方式處理接收到的信號。
在例子中我們使用kill函數給其它進程發送信號,下面是kill函數的原型:
int kill(pid_t pid, int signo);
第一個參數pid表示進程的PID,kill函數將把信號發送給PID與其參數相同的進程; 第二個參數表示信號。該參數表示kill函數發送的信號值。 如果kill成功發送信號,那麼返回0,否則返回-1.
在例子中我們使用signal函數設置接收到信號後的處理方式,下面是signal函數的原型:
void (*signal(int signo, void (*func) (int))) (int)
大家看著這個函數是不是覺得有點亂?先別慌,我們慢慢對它進行分析。
這個函數名叫signal,它用來配置信號處理函數,通俗點說,它就是為某個信號分配一個信號處理函數。它有兩個參數:
一個參數是signo,表示信號值; 另外一個參數是一個名叫func的函數指針,它表示信號處理函數。 也就是說進程接收到signo表示的信號後會使用該函數來處理信號。 參數中的func是一個函數指針,它指向的函數包含一個int類型的參數,表示信號值,該函數返回void。 最後,我們說一下signal函數的返回值,它返回一個函數,該函數就是func指向的信號處理函數。接下來,我們通過具體的代碼來說明它們的用法。
#include
#include
#include
void sig_receive(int signo)
{
printf("received signal :%d \n",signo);
}
int main()
{
pid_t pid;
int pid_res;
int stat_value;
pid = fork();
if(pid > 0)
{
printf("PID: %d -> Father Process send signal\n",getpid());
kill(pid,SIGALRM); //發送信號
}
else if(pid == 0)
{
signal(SIGALRM,sig_receive); //配置信號處理函數
printf("PID: %d -> Son Process receive signal \n",getpid());
}
else
{
printf("Create process failed \n");
return 1;
}
pid_res = wait(&stat_value);
if(pid_res > 0)
{
printf("Son process finished: PID = %d \n",pid_res);
}
return 0;
}
從上面的代碼中可以看到,我們在父進程中使用kill函數發送信號,然後在子進程中使用signal函數配置信號處理函數,當子進程收到信號後,信號處理函數就會對該信號進行處理。
看官們,正文中就不寫代碼了,詳細的代碼放到了我的資源中,大家可以點擊這裡下載使用。
下面是程序的運行結果,請大家參考:
PID: 3208 -> Father Process send signal //父進程發送信號
received signal :14 //信號處理函數在處理信號
PID: 3209 -> Son Process receive signal //子進程收到信號
Son process finished: PID = 3209 //子進程結束,父進程也結束
看官們,從程序的結果中可以看出,父進程發出信號後,子進程收到了信號,並且進行了處理。這說明我們通過信號在兩個進程之間進行了通信。
看官們,有個小的細節不知道大家有沒有發現:程序運行結果中先是執行信號處理函數中的內容,然後才執行子進程中的內容。如果我們把執行的順序調換一下會有什麼現象呢?
把下面這兩行代碼的執行順序調換一下,也是說把printf語句放在signal配置語句的前面。
signal(SIGALRM,sig_receive); //配置信號處理函數
printf("PID: %d -> Son Process receive signal \n",getpid());
重新編譯並且運行程序後,得到以下運行結果:
PID: 2611 -> Father Process send signal //父進程發送信號
Son process finished: PID = 2612 //子進程結束,父進程也結束
從上面的結果中以可以看到,子進程不但沒有收到信號,而且沒有執行。這是什麼原因呢?那是因為父進程發信號的時候子進程可能被阻塞,所以沒有執行。這也是signal函數缺點。
signal函數是早期Unix系統提供的函數,現在的新系統中已經使用sigaction函數取代它,不過在一些老的程序中還是能看到它的身影。下一回中,我們將介紹sigcation函數相關的內容。
各位看官,關於使用信號進行進程間通信的例子咱們就說到這裡。欲知後面還有什麼例子,且聽下回分解 。