/*
* 题目:
* 编写程序,要去实现如下功能:
父进程创建子进程1和子进程2、子进程1向子进程2发送可靠信号,并传送额外数据为子进程1的pid*2;
子进程2接受可靠信号的值,并发送给父进程,父进程把接受的值进行打印。
提示:用sigqueue和sigaction实现
* */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h> /*
* 父进程中,知道所有子进程的pid,所以父进程向子进程1发送带数据的信号,数据是子进程2的pid
* 子进程1向子进程2发送信号,子进程2向父进程发送信号
* */ //子进程1信号安装回调函数
void handler1(int sign, siginfo_t * info, void *p)
{
if (sign == SIGRTMIN)
{
printf("子进程1接收到父进程发送的数据:子进程2的pid=%d\n", info->si_value.sival_int);
//向子进程2发送带数据的信号
union sigval v1;
v1.sival_int = getpid() * ;
if (sigqueue(info->si_value.sival_int, SIGRTMIN,v1) != )
{
perror("sigqueue() err");
return;
}
//退出子进程1
printf("子进程1 quit\n");
exit();
}
printf("子进程1接收到其他信号");
} //子进程2信号安装回调函数
void handler2(int sign, siginfo_t * info, void *p)
{
if (sign == SIGRTMIN)
{
printf("子进程2接收到数据%d\n", info->si_value.sival_int);
//向父进程发送信号
if (sigqueue(getppid(), SIGRTMIN, info->si_value) != )
{
perror("sigqueue() err");
return;
}
//退出子进程2
printf("子进程2 quit\n");
exit(); }
} //父进程信号安装回调函数
void handlerf(int sign, siginfo_t * info, void *p)
{
if (sign == SIGRTMIN)
{
//打印信号值
printf("父进程接收的值是%d\n", info->si_value.sival_int);
printf("game is over!\n");
exit();
}
} int main(int arg, char *args[])
{
pid_t pid = ;
pid = fork();
if (pid == -)
{
perror("fork() err");
return -;
}
if (pid == )
{
//子进程1
printf("子进程1的pid=%d\n",getpid());
//安装信号SIGRTMIN,等待父进程发送信号
struct sigaction act;
act.sa_sigaction = handler1;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGRTMIN, &act, NULL) != )
{
printf("sigaction() failed !\n");
exit();
}
//等待父进程发送信号
printf("子进程1等待父进程发送信号\n");
while ()
{
printf("子进程1 sleep\n");
sleep();
}
}
if (pid > )
{
//存储子进程1的pid
pid_t pid_1 = pid;
pid = fork();
if (pid == -)
{
perror("fork() err");
exit();
}
if (pid == )
{
//子进程2
printf("子进程2的pid=%d\n",getpid());
//安装信号SIGRTMIN,等待子进程1发送信号
struct sigaction act;
act.sa_sigaction = handler2;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGRTMIN, &act, NULL) != )
{
printf("sigaction() failed !\n");
exit();
}
//等待子进程1发送信号
printf("子进程2等待子进程1发送信号\n");
while ()
{
printf("子进程2 sleep\n");
sleep();
}
} else if (pid > )
{
//父进程
printf("父进程的pid=%d\n",getpid());
//安装信号SIGRTMIN,等待子进程2发送信号
struct sigaction act;
act.sa_sigaction = handlerf;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGRTMIN, &act, NULL) != )
{
printf("sigaction() failed !\n");
exit();
}
sleep();
//向子进程1发送信号
printf("父进程向子进程1发送信号\n");
union sigval v1;
v1.sival_int = pid;
if (sigqueue(pid_1, SIGRTMIN, v1) != )
{
perror("sigqueue() err");
exit();
}
int ret = ;
//等待子进程退出
while ()
{
ret = wait(NULL);
if (ret == -)
{
if (errno == EINTR)
{
continue;
}
break;
}
}
//等待信号到达
while ()
{
sleep();
}
}
}
return ;
} /*
* 错误总结:执行该程序,发现子进程1老是出不来,开始我以为是fork()失败,经过注释代码调试
* 发现问题出现在父进程的发送信号这个函数上,原因是父进程发送信号的时候,,子进程1刚被创建,还没有执行安装信号函数
* 而信号SIGRTMIN的默认行为是终止进程,所以子进程刚被创建好了,就被终止了
*
* 实际上还有一种方法,可以在fork()之前安装3个不同的信号,3个进程分别接收不同的信号加以处理
* */

Linux Linux程序练习十六(进程间的通信信号版)的更多相关文章

  1. Linux进程间的通信

    一.管道 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: A. 管道是半双工的,数据只能向一个方向流动: B. 需要双工通信时,需要建立起两个管道: C. 只能用于父子进程或者兄弟 ...

  2. c++ 网络编程(三) LINUX/windows 进程间的通信原理与实现代码 基于多进程的服务端实现

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9613027.html 锲子:进程与线程是什么,他们的区别在哪里: 1 进程概念 进程是程序的一 ...

  3. PHP与Linux进程间的通信

    进程间通信预计是公司考察应届毕业生的必考点(嵌入式行业).当然非常多公司考的是算法. 不查阅资料,我脑子里能想到的 [1] 管道, (有名.无名) [2] 父子进程 [3] System V (消息队 ...

  4. 采用虚拟命名管道的字符设备和阻塞型I/O实现进程间的通信实现KWIC程序

    采用虚拟命名管道的字符设备和阻塞型I/O实现进程间的通信实现KWIC程序专业程序代写c++程序代写

  5. c 进程间的通信

    在上篇讲解了如何创建和调用进程 c 进程和系统调用 这篇文章就专门讲讲进程通信的问题 先来看一段下边的代码,这段代码的作用是根据关键字调用一个Python程序来检索RSS源,然后打开那个URL #in ...

  6. posix进程间的通信

    1.无名管道 1.1管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管道: 只能用于父子进程或者兄弟进程之间( ...

  7. [Socket]Socket进程间的通信

    转自:http://blog.csdn.net/giantpoplar/article/details/47657303 前面说到的进程间的通信,所通信的进程都是在同一台计算机上的,而使用socket ...

  8. Nginx学习——Nginx进程间的通信

    nginx进程间的通信 进程间消息传递 共享内存 共享内存还是Linux下提供的最主要的进程间通信方式,它通过mmap和shmget系统调用在内存中创建了一块连续的线性地址空间,而通过munmap或者 ...

  9. swoole进程间如何通信

    Swoole进程间通信的方式 管道pipe 管道用于进程之间的数据交互,Linux系统本身提供了pipe函数用于创建一个半双工通信管道.半双工的通信方式中数据只能单向流动(一端只读一端只写),只能在具 ...

随机推荐

  1. 生成uuid

    function guid(){ if (function_exists('com_create_guid')){ return com_create_guid(); }else{ mt_srand( ...

  2. WPF学习之路(十二)控件(Items控件)

     ListBox 提供了一个选项列表,可以固定或者动态绑定 <StackPanel> <GroupBox Margin="> <GroupBox.Header& ...

  3. jquery操作select(取值,设置选中)

    最近工作中总出现select 和 option问题,整理一下,内容大部分源于网络资料 一.基础取值问题 例如<select class="selector"></ ...

  4. ArrayList vs LinkedList vs Vector

    List概览 List,正如它的名字,表明其是有顺序的.当讨论List的时候,最好拿它跟Set作比较,Set中的元素是无序且唯一:下面是一张类层次结构图,从这张图中,我们可以大致了解java集合类的整 ...

  5. 测试必备技能系列1 :通过mysql命令进行脚本数据导入

    老徐,分享测试项目中实际能解决问题的干货!   今日分享: 如何通过mysql命令行,导入mysql脚本文件数据?   ----- 解决实际的问题: 工作过程中,经常需要导入mysql脚本文件 很多同 ...

  6. json数据处理实战:Kafka+Flume+Morphline+Solr+Hue数据组合索引

    背景:Kafka消息总线的建成,使各个系统的数据得以在kafka节点中汇聚,接下来面临的任务是最大化数据的价值,让数据“慧”说话. 环境准备: Kafka服务器*3. CDH 5.8.3服务器*3,安 ...

  7. HTTP状态码206和416

    HTTP 2xx范围内的状态码表明了:"客户端发送的请求已经被服务器接受并且被成功处理了". TTP/1.1 200 OK是HTTP请求成功后的标准响应 HTTP/1.1 206状 ...

  8. c# winform插件

    插件接口 namespace IMsg { ///<summary> /// 这是插件必须实现的接口,也是主程序与插件通信的唯一接口 /// 换句话说,主程序只认识插件里的这些方法 /// ...

  9. activiti入门

    一.Activiti简介 Activiti 是一个针对商务人士. 开发人员和系统管理员的轻量级的工作流和业务流程管理 (BPM) 平台.它的核心是Java的高速和可靠的 BPMN 2 流程引擎.它是开 ...

  10. 烂泥:学习Nagios(二):Nagios配置

    本文由秀依林枫提供友情赞助,首发于烂泥行天下 nagios安装完毕后,我们现在就来配置nagios.有关nagios的安装,可以参考<烂泥:学习Nagios(一):Nagios安装>这篇文 ...