信号发送
Kill基本用法
发送信号的函数有kill和raise
区别:kill既可以向自身发送信号,也可以向其他进程发送信号;
raise函数向进程自身发送信号。
Int kill(pid_t pid, int siq)
int raise(int signo)
Int kill(pid_t pid, int siq)
参数组合情况解释:
kill(pid_t pid, int siq)
pid>0 将信号sig发给pid进程
pid=0 将信号sig发给同组进程
pid=-1 将信号sig发送给所有进程,调用者进程有权限发送的每一个进程(除了1号进程之外,还有它自身)
pid<-1 将信号sig发送给进程组是pid(绝对值)的每一个进程
子进程向父进程发送信号
sleep函数几点说明
1)sleep函数作用,让进程睡眠。
2)能被信号打断,然后处理信号函数以后,就不再睡眠了,直接向下执行代码.
3)sleep函数的返回值,是剩余的秒数
1、当一个进程调用fork()时,其子进程继承父进程的信号处理方式
因为子进程在开始时复制了父进程的进程映像,所以信号捕捉函数的地址
在子进程中是有意义的!
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
/*
kill()函数与sleep()函数的使用
*/
//信号处理函数
void myhandle(int num)
{
if (num == SIGINT)
{
printf("recv signal SIGINT \n");
}
else if (num == SIGUSR1)
{
printf("recv signal SIGUSR1 \n");
}
else
{
printf("recv signal id num : %d \n", num);
}
}
int main(void)
{
pid_t pid;
printf("main ....begin\n");
//如果在fork之前安装信号,则子进程可以继承信号。
//安装信号 SIGINT
if (signal(SIGINT, myhandle) == SIG_ERR)
{
perror("func signal err\n");
return 0;
}
//安装信号SIGUSER1
if (signal(SIGUSR1, myhandle) == SIG_ERR)
{
perror("func signal err\n");
return 0;
}
pid = fork();
if (pid == -1)
{
printf("fork err....\n");
return 0;
}
#if 0
if (pid == 0)
{
pid = getppid();
kill(pid, SIGUSR1); //向老爹发信号
//raise(pid);//等价
exit(0);//子进程运行完就退出了
}
/*
运行结果:
hzmct@U-64:/study/linuxtest/day02/01signal$ ./dm03_signal
main ....begin
父进程开始睡眠
recv signal SIGUSR1
父进程开始唤醒
父进程开始睡眠
父进程开始唤醒
sleep 函数执行完毕以后返回..
*/
#endif
//---------------------------------------------------
//子进程向同组进程发送信号,父进程和子进程都收到了信号,证明了信号的继承性
#if 0
//因为信号处理函数注册是在fork()之前,父进程注册信号同时
//子进程也注册了此信号,因此信号处理函数会打印2遍
if (pid == 0)
{
pid = getppid();
kill(0, SIGUSR1); //向进程组发信号
exit(0);
}
/*
运行结果:
hzmct@U-64:/study/linuxtest/day02/01signal$ ./dm03_signal
main ....begin
父进程开始睡眠
recv signal SIGUSR1
recv signal SIGUSR1
父进程开始唤醒
父进程开始睡眠
父进程开始唤醒
sleep 函数执行完毕以后返回...
*/
#endif
//----------------------------------------------------
//子进程向 同组进程 发送信号
#if 0
//因为信号处理函数注册是在fork()之前,父进程注册信号同时
//子进程也注册了此信号,因此信号处理函数会打印2遍
if (pid == 0)
{
pid = getppid();
kill(0, SIGUSR1); //向进程组发信号
exit(0);
}
/*
运行结果:
hzmct@U-64:/study/linuxtest/day02/01signal$ ./dm03_signal
main ....begin
父进程开始睡眠
recv signal SIGUSR1
recv signal SIGUSR1
父进程开始唤醒
父进程开始睡眠
父进程开始唤醒
sleep 函数执行完毕以后返回...
*/
#endif
//---------------------------
//子进程向进程组发送信号
#if 1
if (pid == 0)
{
//获取进程组id
pid = getpgrp();
//向进程组发送信号
killpg(pid, SIGUSR1);
exit(0);
}
#endif
/*
运行结果
main ....begin
父进程开始睡眠
recv signal SIGUSR1
父进程开始睡眠
recv signal SIGUSR1
父进程开始唤醒
sleep 函数执行完毕以后返回...
*/
//-------------------------------------------------
int n = 3;
do
{
printf("父进程开始睡眠\n");
n = sleep(n);//sleep函数返回剩余的秒数
printf("父进程开始唤醒\n");
} while (n > 0);
//请思考sleep函数的作用 man sleep
printf("sleep 函数执行完毕以后返回...\n");
return 0;
}