Linux应用编程基础--(9)进程间通信

进程间通信概述:
详细的讲述进程间通信在这里绝对是不可能的事情,而且笔者很难有信心说自己对这一部分内容的认识达到了什么样的地步,所以在这一节的开头首先向大家推荐著 名作者Richard Stevens的著名作品:《Advanced Programming in the UNIX Environment》,它的中文译本《UNIX环境高级编程》已有机械工业出版社出版,原文精彩,译文同样地道,如果你的确对在Linux下编程有浓 厚的兴趣,那么赶紧将这本书摆到你的书桌上或计算机旁边来。说这么多实在是难抑心中的景仰之情,言归正传,在这一节里,我们将介绍进程间通信最最初步和最 最简单的一些知识和概念。 
1,UNIX平台进程通信方式:
早期进程间通信方式
system V IPC 其通信进程主要局限在单个计算机内。
BSD跳过了限制,形成了基于套接字(socket)的进程间通信机制。

2,进程间通信机制分类:
传统的进程间通信机制:
无名管道 pipe
有名管道 fifo
信号 signal
System V IPC 对象
内存共享 share memory
消息队列 massage queue
信号灯 semaphore
BSD
套接字 socket

一、 无名管道 pipe
1,无名管道的概念:
管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
2,无名管道由pipe()函数创建:
管道是基于文件描述符的通信方式,当一个管道建立时,它会创建两个文件描述符fd[0]和fd[1],其中fd[0]固定用于读管道,fd[1]固定负责读管道,构成半双工通道:

函数头文件
#include <unistd.h> 
函数原型  
int pipe(int filedis[2]); 
   函数参数含义
参数filedis返回两个文件描述符:
filedes[0]为读而打开
filedes[1]为写而打开
filedes[1]的输出是filedes[0]的输入
3,无名管道的特点:
只能用于具有亲缘关系的进程之间的通信
半双工的通信模式,具有固定的读端和写端
管道可以看成是一个文件,对于它的读写可以使用文件IO如 readwrite函数。
总结:
如果没有写端,读端会先把缓冲区数据读完,然后退出 EOF
如果没有读端,只有写端,写不进去
如果有读写段,read时没有数据会阻塞,
当管道里没有数据时,读操作会阻塞
向管道中写入数据时,Linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道内写入数据,如果读进程不读走管道缓冲区中的数据,那么写操作一定会阻塞
只有在管道的读端存在时,向管道中写入数据才有意思,否则,向管道中写入数据的进程将会受到内核传来的SIGPIPE信号 (Broken pipe错误)
二、有名管道 fifo
1,有名管道的概念:
有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
2,fifo函数创建:
有名管道可由两种方式创建:
命令行方式mknod系统调用
mkfifo("myfifo","rw"); 
函数mkfifo创建:
函数头文件:
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
函数原型:
int mkfifo(const char *filename , mode_t mode);
函数参数含义:
filename 要创建的管道名
mode 指定创建的管道权限 0666
函数返回值:
成功 0
出错 -1   
3,有名管道的特点:
有名管道可以使互不相关的两个进程互相通信,有名管道可以通过路径名来指出并在文件系统中可见。
进程通过文件IO来操作有名管道
有名管道遵循先进先出规则
不支持如lseek()操作
命名管道是建立在实际的磁盘介质或文件系统(而不是只存在于内存中)上有自己名字的文件,任何进程可以在任何时间通过文件名或路径名与该文件建立联系。

为了实现命名管道,引入了一种新的文件类型——FIFO文件(遵循先进先出的原则)。 实现一个命名管道实际上就是实现一个FIFO文件。命名管道一旦建立,之后它的读、写以及关闭操作都与普通管道完全相同。虽然FIFO文件的inode节点在磁盘上,但是仅是一个节点而已,文件的数据还是存在于内存缓冲页面中,和普通管道相同。

4,生成了有名管道后,就可以使用一般的文件I/O函数如open、close、read、write等来对它进行操作。


三、信号通信 SIGNAL
1,信号通信概念:
信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式
信号可以直接进行用户空间进程和内核进程之间的交互
如果该进程当前并未处于执行状态,则该信号就由内核保存起来,直到该进程恢复执行再传递给它。
使用信号的场合:
后台进程要使用信号、如果两个进程没有亲缘关系,无法使用无名管道、如果两个进程之一只能使用标准输入和标准输出,则无法使用FIFO
2,信号“诞生”:
信号的诞生指的是触发信号的事件发生(如检测到硬件异常、终端中断、定时器超时以及调用信号发送函数kill()或sigqueue()等)。
1> 异常
2>其他进程
3>终端终端 ctrl+c ctrl+\
4>作业控制
5>分配额 cpu超时或者文件大小突破限制
6>通知 内核通知进程某事件发生,I/O就绪 SIGIO
7>报警 计时器到期
3,信号的生存周期:

1->信号在进程中注册指的就是信号值加入到进程的未决信号集中(sigpending结构的第二个成员sigset_t signal),并且信号所携带的信息被保留到未决信号信息链的某个sigqueue结构中。 只要信号在进程的未决信号集中,表明进程已经知道这些信号的存在,但还没来得及处理,或者该信号被进程阻塞。
2->信号在进程中的注销。在目标进程执行过程中,会检测是否有信号等待处理(每次从系统空间返回到用户空间时都做这样的检查)。 如果存在未决信号等待处理且该信号没有被进程阻塞,则在运行相应的信号处理函数前,进程会把信号在未决信号链中占有的结构卸掉。
3->进程注销信号后,立即执行相应的信号处理函数,执行完毕后,信号的本次发送对进程的影响彻底结束。
注:在信号被注销到相应的信号处理函数执行完毕这段时间内,如果进程又收到同一信号多次,则对实时(可靠)信号来说,每一次都会在进程中注册;而对于非实时信号来说,无论收到多少次信号,都会视为只收到一个信号,只在进程中注册一次。
4,用户进程对信号的响应方式
1->忽略信号 对信号不做任何处理,但是有两个信号不能被忽略 SIGKILL SIGSTOP
2->捕捉信号 定义信号处理函数 当信号发生时,执行响应的处理函数
3->执行缺省操作 即对信号规定的默认操作
5,信号的处理流程

6,信号的发送与捕捉:
使用kill raise alarm pasue signal 函数:
***************
头文件
#include<signal.h>
#include<sys/types.h>
函数原型
int kill(pid_t pid,int sig);
参数含义
pid 正数:要接收信号的进程的进程号
0:信号被发送到所有和pid进程在同一组的进程
-1:信号发给所有的进程表中的进程(除了进程号最大的进程)
sig 信号
返回值
成功:0
出错:-1
***************
头文件
#include<signal.h>
#include<sys/types.h>
函数原型
int raise(int sig);
参数含义
sig 信号
返回值
成功:0
出错:-1
***************
头文件
#include<unistd>
函数原型
int alarm(int seconds);
参数含义
second 制定秒数
返回值
成功:0
出错:-1
***************
头文件
#include<unistd.h>
函数原型
int pause(void);
参数含义
无参
返回值
成功:0
出错:-1

头文件
#include<signal.h>
函数原型
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
参数含义
signal信号量
handler SIG_IGN 忽略信号
SIG_DFL 采用系统默认方式处理信号
自定义处理信号函数
返回值
成功:0
出错:-1

函数说明:
kill函数与kill命令类似,发送信号给进程或进程组
kill -l 命令查看系统的全部信号列表
raise函数允许进程向自己发送信号
alarm函数 也成闹钟函数 它可以在进程中设置一个定时器,当定时器指定到时间时,内核就向进程发送SIGALSM信号
pause函数 是用于将调用进程挂起知道收到信号为止
signal函数指定需要处理的函数和处理函数


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值