信号的基本操作
kill 函數
#include <sys/types.h>
#include <signal.h>
/*
* 功能:
* 給指定程序發送信号
* 參數:
* pid:
* pid > 0:
* 将信号傳送給程序 ID 為 pid 的程序
* pid = 0:
* 将信号傳送給目前程序所在程序組中的所有程序
* pid = -1:
* 将信号傳送給系統内所有的程序
* pid < -1:
* 将信号傳給指定程序組的所有程序。 這個程序組号等于 pid 的絕對值
* signum:信号的編号
* return:
* 成功:0
* 失敗:-1
*
*/
int kill(pid_t pid, int signum)
父程序給子程序發送信号
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
int main(int argc, char *argv[])
{
pid_t pid;
pid = fork();
if(pid < 0)
{
perror("fork");
}
if(0 == pid)
{
int i = 0;
for(i = 0; i < 5;i++)
{
printf("in son process\n");
sleep(1);
}
}
else
{
printf("in father process\n");
sleep(2);
printf("kill sub process now\n");
kill(pid, SIGINT);
}
return 0;
}
列印:
alarm 函數
#include <unistd.h>
/*
*功能:
* 在 seconds 秒後,向調用程序發送一個 SIGALRM 信号
* SIGALRM 信号的預設動作:終止調用 alarm 函數的程序
* return:
* 若以前沒有設定過定時器,或設定的定時器已逾時,傳回 0
* 否則傳回定時器剩餘的秒數,并重新設定定時器
*/
unsigned int alarm(unsigned int seconds)
例子:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int seconds = 0;
seconds = alarm(5);
printf("seconds = %d\n",seconds);
sleep(2);
seconds = alarm(5);
printf("seconds = %d\n",seconds);
while(1);
return 0;
}
列印:
raise 函數
#include <signal.h>
/*
* 功能:
* 給調用程序本身送一個信号
* 參數:
* signum: 信号的編号
* return:
* 成功: 0
* 失敗: -1
*/
int raise(int signum);
例子:
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
printf("in raise function\n");
sleep(2);
raise(SIGALRM);
sleep(10);
return 0;
}
列印:
abort 函數
#include <stdlib.h>
/*
* 功能:
* 向程序發送一個 SIGABRT 信号, 預設情況下程序會退出
* 注意:
* 即使 SIGABRT 信号被加入阻塞集,一旦程序調用了 abort 函數,程序也還是會被終止,且在終止前會重新整理緩沖區,關檔案描述符
*/
void abord(void);
pause 函數
#include <unistd.h>
/*
* 功能:
* 将調用程序挂起直至捕捉到信号為止
* 這個函數通常用于判斷信号是否已到
* return:
* 直到捕獲到信号,pause 函數才傳回-1,且 errno 被設定成 EINTR
*/
int pause(void)
#include <unistd.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("in pause function\n");
pause();
return 0;
}
列印:
程序接收到信号後的處理方式
執行系統預設動作
忽略此信号
執行自定義信号處理函數
程式中可用函數 signal()改變信号的處理方式
#include <signal.h>
/*
* 功能:
* 注冊信号處理函數(不可用于 SIGKILL、SIGSTOP 信号),即确定收到信号後處理函數的入口位址
* 參數:
* signum:信号編号
* handler:
* 忽略該信号: SIG_IGN
* 執行系統預設動作: SIG_DFL
* 自定義信号處理函數: 信号處理函數名
* return:
* 成功:傳回函數位址,該位址為此信号上一次注冊的信号處理函數的位址
* 失敗:傳回 SIG_ERR
*/
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
注冊信号處理函數
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void signal_handler(int signo);
int main()
{
printf("wait for SIGINT OR SIGQUIT\n");
signal(SIGINT, signal_handler);
signal(SIGQUIT, signal_handler);
pause();
pause();
return 0;
}
void signal_handler(int signo)
{
if(signo == SIGINT)
{
printf("recv SIGINT\n");
}
if(signo == SIGQUIT)
{
printf("recv SIGQUIT\n");
}
}
列印:
操作:ctrl+\ ctrl+c ctrl + z
驗證 signal 函數的傳回值
#include <stdio.h>
#include <signal.h>
#inlcude <unistd.h>
typedef void (*sighandler_t)(int);
void fun1(int signo);
void fun2(int signo);
int main(int argc, char *argv[])
{
sighandler_t previous = NULL;
previous = signal(SIGINT, fun1);
if(previous == NULL)
{
printf("return fun addr is NULL\n");
}
previous = signal(SIGINT, fun2);
if(previous == fun1)
{
printf("return fun addr is fun1\n");
}
previous = signal(SIGQUIT,fun1);
if(previous == NULL)
{
printf("return fun addr is NULL\n");
}
return 0;
}
void fun1(int signo)
{
printf("in fun1\n");
}
void fun2(int signo)
{
printf("in fun2\n");
}
列印: