Linux进程间通信之信号
一:信号
信号通信,其实就是内核向用户空间进程发送信号,只有内核才能发信号,用户空间进程不能发送信号。信号其实已经在内核存在了。
内核可以发送多少种信号呢?
kill -l
64种
命令:kill -9 pid
注:1.告诉内核发送什么信号;
2.告诉内核发给谁。
信号通信的框架
信号的发送(发送信号进程):kill raise alarm
信号的接收(接收信号进程) : pause() sleep while(1)//这3中方式可以
信号的处理(接收信号进程) : signal
1.信号的发送(发送信号进程)
kill :
头文件 #include <signal.h>
#include <sys/types.h>
函数原型 int kill(pid_t pid, int sig);
函数传入值
pid: 正数:要接收信号的进程的进程号
0:信号被发送到所有和pid进程在同一个进程组的进程
-1:信号发给所有的进程表中的进程(除了进程号最大的进程外)
sig:信号
函数返回值
成功:0
出错:-1
raise: 发信号给自己 == kill(getpid(), sig)
头文件 #include <signal.h>
#include <sys/types.h>
函数原型 int raise(int sig);
函数传入值 sig:信号
函数返回值
成功:0
出错:-1
#include "stdio.h"
#include "sys/types.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{
//没有加\n就会出现没有显示
//数据写到了行缓存中去了的
printf("raise before");
raise(9);// _exit()相当于raise,不刷新缓存
// exit()会把上面在行缓存中的数据发给内核,然后输出
printf("raise after\n");
return 0;
}
#include "stdio.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
pid_t pid;
pid=fork();
if(pid > 0 )
{
sleep(8);
//WNOHANG以非阻塞调用,没有子进程状态发生改变
//waitpid不阻塞立即返回此时的返回值为0
if(waitpid(pid,NULL,WNOHANG) == 0)
{
kill(pid,9);//杀死子进程
}
//回收僵尸态子进程,如果没有僵尸态子进程
//则阻塞,null是指忽略子进程退出的状态
wait(NULL);
while(1);
}
if(pid == 0)
{
printf("raise function before\n");
raise(SIGTSTP);
printf("raise funtion after\n");
exit(0);
}
return 0;
}
alarm : 发送闹钟信号的函数:
alarm 与 raise 函数的比较:
相同点:让内核发送信号给当前进程
不同点:
1.alarm 只会发送SIGALARM信号
2.alarm 会让内核定时一段时间之后发送信号, raise会让内核立刻发信号
所需头文件 #include <unistd.h>
函数原型 unsigned int alarm(unsigned int seconds)
函数传入值 seconds:指定秒数
函数返回值 成功:如果调用此alarm()前,进程中已经设置了闹钟时间,则
返回上一个闹钟时间的剩余时间,否则返回0。
出错:-1
2. 信号的接收(接收信号进程)
接收信号的进程,要有什么条件:要想使接收的进程能收到信号,这个进程不能结束 :
sleep
**pause:**进程状态为S(运行到这里会给当前进程发睡眠状态并一直处于睡眠状态)
while(1)
所需头文件 #include <unistd.h>
函数原型 int pause(void);
函数返回值 成功:0,出错:-1
#include "stdio.h"
#include "sys/types.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
int main()
{
int i;
i=0;
printf("pause before\n");
pause();
printf("pause after\n");
while(i< 20)
{
i++;
sleep(1);
printf("process things,i=%d\n",i);
}
return 0;
}
3.信号的处理(接收信号进程)
收到信号的进程,应该怎样处理? 处理的方式:
(1)进程的默认处理方式(内核为用户进程设置的默认处理方式)
A:忽略
B:终止进程
C: 暂停
(2)自己的处理方式:
自己处理信号的方法告诉内核,这样你的进程收到了这个信号就会采用你自己的的处理方式
所需头文件 #include <signal.h>
函数原型 void (*signal(int signum, void (*handler)(int)))(int);
函数传入值 signum:指定信号(告诉内核处理哪一个信号)
handler: 告诉
内核用什么方法去处理
SIG_IGN:忽略该信号。
SIG_DFL:采用系统默认方式处理信号。
自定义的信号处理函数指针
函数返回值
成功:设置之前的信号处理方式
出错:-1
signal 函数有二个参数,第一个参数是一个整形变量(信号值),第二个参数是一个函数指针,是我们自己写的处理函数;
void (*handler)(int)是一个函数指针变量,函数的形式:含有一个整型参数,无返回值的函数,
这个函数的返回值是一个函数指针。
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
void myfun(int signum)
{
int i;
i=0;
while(i < 5)
{
printf("process signal signum=%d\n",signum);
sleep(1);
i++;
}
//信号处理函数处理完之后就回到主函数中继续运行
return; // return main
}
int main()
{
int i;
i=0;
//9s后alarm发的14号信号后,执行信号处理函数
signal(14,myfun);
printf("alarm before\n");
//alarm会给内核发SIGALRM(14号信号)
alarm(9);
printf("alarm after\n");
while(i< 10)
{
i++;
sleep(1);
printf("process things,i=%d\n",i);
}
return 0;
}
#include "stdio.h"
#include "sys/types.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
void myfun(int signum)
{
int i;
i=0;
while(i < 10)
{
printf("process signal signum=%d\n",signum);
sleep(1);
i++;
}
return; // return main
}
int main()
{
int i;
i=0;
signal(14,myfun);
printf("alarm before\n");
alarm(9);
printf("alarm after\n");
signal(14,SIG_IGN);
signal(14,SIG_DFL); //系统会以这条为最新的信号函数去执行,以默认的方式去处理9号信号的
while(i< 20)
{
i++;
sleep(1);
printf("process things,i=%d\n",i);
}
return 0;
}
利用信号实现进程间的通信
#include "stdio.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
void myfun(int signum)
{
int i;
i=0;
while(i <2)
{
printf("receive signum=%d,i=%d\n",signum,i);
sleep(1);
i++;
}
return;
}
void myfun1(int signum)
{
printf("receive signum=%d\n",signum);
wait(NULL);
return ;
}
int main()
{
pid_t pid;
pid=fork();
if(pid > 0 )
{
int i;
i=0;
signal(10,myfun);
signal(17,myfun1);
while(1)
{
printf("parent process things,i=%d\n",i);
sleep(1);
i++;
}
}
if(pid == 0)
{
sleep(5);
kill(getppid(),10);
sleep(5);
exit(0);//kill(getppid(),17)
}
return 0;
}