进程间通信方式

1.进程间通信

每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,进程B再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信。

 

不同进程间的通信本质:进程之间可以看到一份公共资源;而提供这份资源的形式或者提供者不同,造成了通信方式不同。

2.程间通信方式

①管道(pipe),流管道(s_pipe)和命名管道(即FIFO文件)

②信号(signal)

信号量(semophore)

消息队列(message queue)

共享内存(shared memory)

⑥套接字(socket)

3.管道(pipe)

3.1 管道的创建

管道是由调用pipe函数来创建

#include <unistd.h>

int pipe (int fd[2]);        //返回:成功返回0,出错返回-1

fd参数返回两个文件描述符,fd[0]指向管道的读端,fd[1]指向管道的写端。fd[1]的输出是fd[0]的输入。

3.2 管道如何实现进程间的通信

(1)父进程创建管道,得到两个⽂件描述符指向管道的两端

(2)父进程fork出子进程,⼦进程也有两个⽂件描述符指向同⼀管道。

(3)父进程关闭fd[0],子进程关闭fd[1],即⽗进程关闭管道读端,⼦进程关闭管道写端(因为管道只支持单向通信)。⽗进程可以往管道⾥写,⼦进程可以从管道⾥读,管道是⽤环形队列实现的,数据从写端流⼊从读端流出,这样就实现了进程间通信。

3.3 管道特点

1.管道只允许具有血缘关系的进程间通信,如父子进程间的通信。

2.管道只允许单向通信。

3.管道内部保证同步机制,从而保证访问数据的一致性。

4.面向字节流

5.管道随进程,进程在管道在,进程消失管道对应的端口也关闭,两个进程都消失管道也消失。

管道这种通讯方式有两种限制,一是半双工的通信,数据只能单向流动,二是只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。

 

流管道(s_pipe): 去除了第一种限制,可以双向传输。

 

管道可用于具有亲缘关系进程间的通信,

命名管道(name_pipe):克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信; 通过命名管道可以在不相关的进程之间交换数据。

4.信号signal

信号 ( signal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

 

信号是Linux系统中用于进程之间通信或操作的一种机制,信号可以在任何时候发送给某一进程,而无须知道该进程的状态。如果该进程并未处于执行状态,则该信号就由内核保存起来,知道该进程恢复执行并传递给他为止。如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞被取消时才被传递给进程。

Linux提供了几十种信号,分别代表着不同的意义。信号之间依靠他们的值来区分,但是通常在程序中使用信号的名字来表示一个信号。在Linux系统中,这些信号和以他们的名称命名的常量被定义在/usr/includebitssignum.h文件中。通常程序中直接包含<signal.h>就好。

 

信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式,信号可以在用户空间进程和内核之间直接交互。内核也可以利用信号来通知用户空间的进程来通知用户空间发生了哪些系统事件。信号事件有两个来源:

1)硬件来源,例如按下了cltr+C,通常产生中断信号sigint

2)软件来源,例如使用系统调用或者命令发出信号。最常用的发送信号的系统函数是kill,raise,setitimer,sigation,sigqueue函数。软件来源还包括一些非法运算等操作。

 

一旦有信号产生,用户进程对信号产生的相应有三种方式:

1)执行默认操作,linux对每种信号都规定了默认操作。

2)捕捉信号,定义信号处理函数,当信号发生时,执行相应的处理函数。

3)忽略信号,当不希望接收到的信号对进程的执行产生影响,而让进程继续执行时,可以忽略该信号,即不对信号进程作任何处理。

  有两个信号是应用进程无法捕捉和忽略的,即SIGKILL和SEGSTOP,这是为了使系统管理员能在任何时候中断或结束某一特定的进程。

5.信号量(semophore)

信号量本质上是一个计数器信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

它和管道有所不同,它不以传送数据为主要目的,它主要是用来保护共享资源(信号量也属于临界资源),使得资源在一个时刻只有一个进程独享。

其中,信号量又分为两种:二进制信号量和计数信号量。 

在linux系统中,二进制信号量(binary semaphore)又称互斥锁(Mutex)。

5.1 信号量的工作原理

信号量又存在着两种操作,分别为V操作与P操作,V操作会增加信号量 S的数值,P操作会减少它。

在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。

信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv),他们的行为是这样的:

(1)P(sv):如果如果信号量sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行

(2)V(sv):如果有其他进程因等待该信号量sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1。

在信号量进行PV操作时都为原子操作(因为它需要保护临界资源)

注:原子操作:单指令的操作称为原子的,单条指令的执行是不会被打断的

 

具体的运作方式如下:

①初始化,给与它一个非负数的整数值。

②运行 P(wait()),信号量S的值将被减少。企图进入临界区块的进程,需要先运行 P(wait())。当信号量S减为负值时,进程会被挡住,不能继续;当信号量S不为负值时,进程可以获准进入临界区块。

③运行 V(又称signal()),信号量S的值会被增加。结束离开临界区块的进程,将会运行 V(又称signal())。当信号量S不为负值时,先前被挡住的其他进程,将可获准进入临界区块。

6.消息队列(message queue)

消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

7.共享内存(shared memory)

共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。

8.套接字(socket)

套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。

 

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值