05多进程间使用信号进行通信
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#if 1
/*
要求:
3、信号可靠信号不可靠信号相关
编程程序,要去实现如下功能:
父进程创建子进程1和子进程2、子进程1向子进程2发送可靠信号,
并传送额外数据为子进程1的pid*2;
子进程2接受可靠信号的值,并发送给父进程,父进程把接受的值
进行打印。
提示:用sigqueue和sigaction实现
分析:
1因为孩子1的pid和孩子2的pid全部在父进程中
2父进程把孩子2的pid,发给孩子1
3孩子1有了孩子2的pid,孩子1就可以给孩子2发送信号了。
父--->子1---->子2---->父
*/
// kill -l 查看信号
int pidArray[10];//使用全局变量缓存子进程id
void myhandle(int num, siginfo_t *st, void *p)
{
//子进程1接收到了信号
if(num == SIGRTMIN+1)
{
printf("孩子1收到信号值:%d \n", st->si_value.sival_int);
//获取到子进程2的pid
pidArray[1] = st->si_value.sival_int;
}
//子进程2接收到了信号
if(num == SIGRTMIN+2)
{
//孩子2收到信号
printf("孩子2收到信号,值:%d \n", st->si_value.sival_int);
//子进程的pid * 2
pidArray[3] = st->si_value.sival_int;
}
//父进程接收到了信号
if(num == SIGRTMIN+3)
{
//父进程接收到了信号
printf("父进程收到信号,值:%d \n", st->si_value.sival_int);
printf("父进程中的pid[0]:%d pid[1]:%d \n", pidArray[0], pidArray[1]);
}
}
int test()
{
int i = 0;
struct sigaction act;
act.sa_sigaction = myhandle;
act.sa_flags = SA_SIGINFO;//表示信号要传输信息
if(sigaction(SIGRTMIN+1, &act, NULL) == -1){
perror("func sigaction err");
return -1;
}
if(sigaction(SIGRTMIN+2, &act, NULL) == -1){
perror("func sigaction err");
return -1;
}
if(sigaction(SIGRTMIN+3, &act, NULL) == -1){
perror("func sigaction err");
return -1;
}
int pid = 0;
//连续创建2 个子进程
for (i = 0; i < 2; i++)
{
//父进程可以把所有孩子的id缓存下来
pidArray[i] = pid = fork();
if(pid == 0)
{
break;//如果是孩子,不参与fork
}
else if (pid > 0)
{
;
}
}
//子进程1向子进程2发送 子进程1的pid*2
if (pid == 0 && i == 0)
{
printf("子进程1运行\n");
printf("子进程1 sleep\n");
//sleep是可中断的睡眠,只要linux内核发信号,进程就会醒来
printf("进程1 sleep 剩余时间为 %d\n",sleep(5));
printf("子进程1sleep被打断后,全局变量有值了,即子进程1拿到了子进程2的pid:%d\n",pidArray[1]);
//添加额外数据
union sigval mysigval;
mysigval.sival_int = getpid()*2;
printf("子进程1给进程2发送信号getpid()*2:%d \n", getpid()*2);
//向子进程2发送消息
if(sigqueue(pidArray[1], SIGRTMIN+2, mysigval) < 0 )
{
perror("func sigqueue err");
return -1;
}
printf("子进程1给子进程2发完信号啦,即将退出........\n");
exit(0);
}
//子进程2 向父进程发送信号
if (pid == 0 && i == 1)
{
printf("进程2 sleep 剩余时间为 %d\n",sleep(20));
printf("子进程2睡眠醒来,开始发送信号\n");
//添加额外数据
union sigval mysigval;
mysigval.sival_int = pidArray[3];
printf("子进程2给父进程发送信号pidArray[3]:%d \n", pidArray[3]);
//子进程2向父进程发送消息
if(sigqueue(getppid(), SIGRTMIN+3, mysigval) < 0 )
{
perror("func sigqueue err");
return -1;
}
printf("子进程2给父进程发完信号啦,即将退出........\n");
exit(0);
}
//父进程向子进程1发送子进程2的pid
if (pid > 0)
{
printf("父进程运行\n");
//父进程给进程1发信号 把进程2的pid发过去
//添加额外数据
union sigval mysigval;
mysigval.sival_int = pidArray[1];
//向子进程1发送消息
if(sigqueue(pidArray[0], SIGRTMIN+1, mysigval) < 0 )
{
perror("func sigqueue err");
return -1;
}
printf("父进程给子进程1发完信号啦........\n");
}
sleep(2);
int mypid = 0;
//非阻塞等待所有的子进程退出
while ((mypid = waitpid(-1, NULL, WNOHANG)) > 0 )
{
printf("子进程退出pid:%d \n", mypid);
}
printf("hello........\n");
return 0;
}
#endif
进行单独测试父子进程通信,并没有出现以上问题
#if 0
void myhandle(int num, siginfo_t *st, void *p)
{
//子进程1接收到了信号
if(num == SIGRTMIN+1)
{
printf("收到信号值:%d \n", st->si_value.sival_int);
}
}
int test()
{
struct sigaction act;
act.sa_sigaction = myhandle;
act.sa_flags = SA_SIGINFO;//表示信号要传输信息
if(sigaction(SIGRTMIN+1, &act, NULL) == -1){
perror("func sigaction err");
return -1;
}
int pid = 0;
pid = fork();
//子进程给父进程发送信号
if (pid == 0)
{
//添加额外数据
union sigval mysigval;
mysigval.sival_int = 111;
//向子进程1发送消息
if(sigqueue(getppid(), SIGRTMIN+1, mysigval) < 0 )
{
perror("func sigqueue err");
return -1;
}
exit(0);
}
sleep(2);
int mypid = 0;
//非阻塞等待所有的子进程退出
while ((mypid = waitpid(-1, NULL, WNOHANG)) > 0 )
{
printf("子进程退出pid:%d \n", mypid);
}
printf("hello........\n");
return 0;
}
#endif
int main()
{
test();
return 0;
}