进程间通讯方式

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

二、进程间通讯方式:信号,管道,信号量,共享内存,消息队列,socket

0、信号是系统提前规定好的一些特定的事件,信号可以被产生,也可以被接收,产生和接收信号的主体都是进程。

接收信号的三种响应方式:忽略(SIG_IGN),默认(SIG_DFL),自定义(自定义的函数)

进程修改信号响应方式的函数:

typedef  void  (*Fun_Handle_t )(int);

Fun_Handle_t(int sig,Fun_Handle_t   fun);//将信号和自定义的处理函数绑定

int   kill(pid_t  pid,int  sig);//向指定的进程发送指定的信号,进程接收到信号,触发相应的响应函数

1、管道(管道容量:64k):半双工通讯

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

有名无名区别:

 (1)有名管道:在文件目录树中有文件标识,无名管道没有

 (2)使用限制:

有名管道:任意一个有权限访问管道文件的进程,可以让同一台计算机上的任何两个没有关系的进程通信;

无名管道:无名管道要想完成进程通讯,必须借助于父子进程共享fork之前打开的文件描述符;即需要通信的进程之间必须存在关系。

操作过程

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

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

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

注意

如果一个进程以只写的方式打开一个管道文件,open函数不会立即返回,会阻塞运行,知道另一个进程以只读的方式打开文件。

2、信号量

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

  2)只允许对它进行两个操作:

P操作:等待信号量
当信号量值为0时,程序等待;当信号量值大于0时,信号量减1,程序继续运行。
V操作:发送信号量
如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,将就信号量值加1。

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

原子操作:不会被线程调度机制打断的操作

  4)进程如何获得共享资源

(1)测试控制该资源的信号量

(2)信号量的值为正,进程获得该资源的使用权,进程将信号量减1,表示它使用了一个资源单位

(3)若此时信号量的值为0,则进程进入挂起状态(进程状态改变),直到信号量的值大于0,若进程被唤醒则返回至第一步。

注:信号量通过同步与互斥保证访问资源的一致性。

3、共享内存:

这是最快的一种IPC(IPC通讯:信号量,共享内存,消息队列)

    (1) 允许两个或多个进程共享一定的存储区。就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改。因为数据不需要在客户机和服务器端之间复制,数据直接写到内存,不用若干次数据拷贝,所以这是最快的一种IPC。

   (2)  共享内存中的数据并不会像管道或者信号量等被一端读取之后就不存在。

   (3)优点:使用共享内存进行进程间的通信真的是非常方便,而且函数的接口也简单,数据的共享还使进程间的数据不用传送,而是直接访问内存,也加快了程序的效率。同时,它也不像无名管道那样要求通信的进程有一定的父子关系。
  缺点:共享内存没有提供互斥同步的机制,这使得我们在使用共享内存进行进程间通信时,往往要借助其他的手段比如信号量等来进行进程间的同步工作。 

4、消息队列

消息:数据+类型         队列:先进先出的一种数据结构

传递的数据是带有type的,不同的进程可以根据不同的需要获取不同类型的数据;如果队列中同一类型的数据有很多条,则采用队列先进先出的原则获取数据。

  (1) 消息队列是消息的链接表,存放在内核中并由消息队列标识符标识(key)。 

标识符是IPC对象的内部名, 而它的外部名则是key(键), 它的基本类型是key_t, 在头文件<sys/types.h>中定义为长整型.。键由内核变换成标识符。

  (2)用户可以从消息队列中读取数据和添加消息,其中发送进程添加消息到队列的末尾,接收进程在队列的头部接收消息;消息一旦被接收,就会从队列中删除。和FIFO有点类似,但是它可以实现消息的随机查询,比FIFO具有更大的优势(比如按消息的类型字段取消息)。

  (3)与FIFO不同的是:消息队列可以制定从消息队列中取走某一条消息

猜你喜欢

转载自blog.csdn.net/YMY_mine/article/details/81537412