信号的基本操作 kill 函数父进程给子进程发送信号 验证 signal 函数的返回值 alarm 函数 raise 函数 abort 函数 pause 函数 进程接收到信号后的处理方式
信号的基本操作
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");
}
打印: