linux進程間通信--信號通信
信號
信號是異步進程間通信方式
進程對信號的響應方式:
<1>忽略
SIGKILL 和 SIGSTOP 不能忽略
<2>捕捉
當進程收到信號,此時執行的信號處理函數
<3>默認
SIGSTOP 改信號用於暫停一個進程,且不能被阻塞,忽略,和處理,默認操作為暫停進程
大部分信號對進程的默認操作方式都是殺死進程
子進程狀態發生改變的時候,操作系統向父進程發送SIGCHLD,默認對它處理方式是忽略
信號的發送與設置
1.信號發送 kill()與raise()
int kill(pid_t pid, int sig);
參數:
pid:可能選擇有以下四種
1. pid大於零時,發送信號給進程號為pid的進程。
2. pid等於零時,信號將送往所有與調用kill()的那個進程屬同一個使用組的進程。
3. pid等於-1時,信號發送給所有的進程表中的進程,除了進程1(init)。
4. pid小於-1時,信號將送往以-pid為組標識的進程。
sig:準備發送的信號代碼,假如其值為零則沒有任何信號送出,但是系統會執行錯誤檢查,通常會利用sig值為零來檢驗某個進程是否仍在執行。
返回值說明: 成功執行時,返回0。失敗返回-1
errno被設為以下的某個值:
EINVAL:指定的信號碼無效(參數 sig 不合法)
EPERM:權限不夠無法傳送信號給指定進程
ESRCH:參數 pid 所指定的進程或進程組不存在
int raise(int signo);
註意:raise函數只允許進程向自身發送信號
實例如下:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, const char *argv[])
{
pid_t pid;
int ret;
if((pid=fork())<0)
{
printf("Fork error\n");
exit(EXIT_FAILURE);
}
if(pid==0)
{
printf("child(pid:%d) is waiting for any signal\n",getpid());
raise(SIGSTOP);//在子進程中使用raise()函數發出SIGSTOP信號,使子進程暫停
exit(EXIT_SUCCESS);
}
else
{
if(waitpid(pid,NULL,WNOHANG)==0)
{
sleep(10);
kill(pid,SIGKILL);
printf("parent kill child process %d\n",pid);
}
}
waitpid(pid,NULL,0);
return 0;
}
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
功能:設置進程對信號處理方式
參數:
@signum 信號的編號
@handler
SIG_IGN : 忽略信號
SIG_DFL : 使用默認處理方式
函數名 : 捕捉方式處理
返回值:
成功返回handler,失敗返回SIG_ERR
練習:
如何進行不阻塞,不輪訓方式回收僵屍態子進程
2.在進程中設置一個定時器
unsigned int alarm(unsigned int seconds);
參數:
@seconds 定時的時間,以秒為單位
註意:
一旦定時時間完成,操作系統就會向進程發送SIGALRM信號
作業:
通過有名管道完成文件傳輸
./A file1 ------->fifo -------> ./B file2
A進程:
讀文件,寫管道
A進程結束條件:文件沒有數據可讀
B進程:
讀管道,寫文件
B進程結束條件:在寫端關閉,讀端不阻塞,如果管道中沒有數據,讀管道會返回0
linux進程間通信--信號通信