1. 为什么需要进程通信?
由于进程是工作在独立的内存空间中,不同的进程间不能直接访问到对方的内存空间,因而需要某种方式来通信.而同一进程内的线程共享内存空间,很容易实现数据共享,但需要严格控制多线程对同一内存地址的访问,因而需要采用某种方式来同步.
2. 进程间通信分类
(1) 间接或直接通信
这是按两个进程通信时是否需要借助临时中转点进行分类。
直接通信:两个进程直接建立一个链路通信。如下面讲到的共享内存。
间接通信:一个进程发数据到一个临时中转点,该中转点再把数据发给另一个进程。如下面讲到的管道、消息队列、套接字。
(2) 阻塞或非阻塞:同步或异步
这是按照发送或接受数据时,是否立即返回还是等操作成功了才返回。
(3) 按照发送或接受操作是否支持缓存分类
0缓存:发送方必须等接收方接受完数据才能返回
有限容量:发送方等缓存满了才等待,接收方等缓存空了等待。类比:socket。
无限缓存:发送方不需要等待,现实中不存在,用于理论。
3. linux下多进程下的通信方式
(1)信号(Signal):
信号是进程间的软件中断通知和处理机制,是在软件层次上对中断机制的一种模拟,用于通知进程有某事件发生。(硬件中断是cpu在执行指令的时候的一种异常处理机制。这种机制借鉴到进程当中来就是信号。)进程在执行过程当中有正常的执行流程,如果这时有意外的事件,并且每个进程有不同处理的时候,就可以用信号实现。比如ctrl-c造成程序退出,这就是由内核的SIGINT信号默认处理函数实现的。除了用于进程间通信外,进程还可以发送信号给进程本身,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一样的.linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix标准的信号函数sigaction。
不足:传送的信息量下,只有一个信号类型,仅起到通知的作用。不能传输要交换的任何数据。
优点:可以作为一种快速的响应机制,比别的通信机制快
信号的实现:
(1)首先用户进程调用系统调用,将信号类型及其相应的信号处理函数传给内核
(2)当有信号产生时,内核负责将该信号分发给进程的信号处理函数
(3)执行进程的信号处理函数
(2)管道(Pipe)及有名管道(named pipe):
管道是基于内存文件的通信机制。两个进程要进行通信,在内存中建立了一个临时文件,通信时数据放到该文件进行通信。只用于具有亲缘关系进程间的通信。比如父进程创建了管道后,子进程可以从父进程继承文件描述符。当两个进程需要进行通信,可以对管道文件描述符的读和写进行。
例如:ls | more,两个进程的通信就是用管道实现的。 该管道的输出端(ls写端)为stdout,输入端(more写端)为stdin。
有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信.
管道只能传输字节流,且buffer有限,当进程结束后管道资源也会释放。
(3)消息队列(Messge Queue):
消息队列是消息的链接表,由操作系统进行维护,两进程通信时消息队列就作为两个进程通信的临时中转站。它与管道的区别是:可用于多个不相关的进程传输数据;可以传输结构化数据,而不仅仅是字节流;buffer比管道更大;消息队列是独立于进程的,如果一个进程创建了消息队列,当进程结束后,该进程创建的消息队列不会释放会继续存在下去,从而后序创建的进程可以读取消息队列的内容,实现两个生命周期不同的进程间的通信。可以使用msgctl可以实现消息队列的创建和删除。消息队列使用标识来区分消息,相同标识的消息组成按先进先出顺序组成一个消息队列,按标识可以分为若干个子队列。
(4)共享内存(Shared memory):
可以说这是最有效的进程间通信方式,是针对其他通信机制运行效率较低而设计的.它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新.相比管道和消息队列,速度最快,没有多余的拷贝,没有系统调用的开销。缺点是这种通信方式需要依靠某种同步机制,如互斥锁和信号量等.
原理:把同一个物理内存区域同时映射到多个进程的内存地址空间。
(5)套接字(Socket):
这是一种更为一般的进程间通信机制,它可用于网络中不同机器之间的进程间通信,应用非常广泛.
4. 参考:
顶你学堂 操作系统
《Linux下多任务间通信和同步-概述》
Linux下多任务间通信和同步-概述
嵌入式开发交流群280352802,欢迎加入!
在前面,我们学习了两种多任务的实现手段:进程和线程.由于进程是工作在独立的内存空间中,不同的进程间不能直接访问到对方的内存空间,因而需要某种方式来通信.而同一进程内的线程共享内存空间,很容易实现数据共享,但需要严格控制多线程对同一内存地址的访问,因而需要采用某种方式来同步.
在linux中有一些多任务通信和同步的方式,有的方式既能实现通信又能实现同步,有的方式不但进程能用线程也能用,因此我们将这些东西放在一起来讲解,这些方式主要有:
(1)管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信.
(2)信号(Signal):信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知进程有某事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一样的.linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数).
(3)消息队列(Messge Queue):消息队列是消息的链接表,包括Posix消息队列SystemV消息队列.它克服了前两种通信方式中信息量有限的缺点,具有写权限的进程可以按照一定的规则向消息队列中添加新消息;对消息队列有读权限的进程则可以从消息队列中读取消息.消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点.
(4)共享内存(Shared memory):可以说这是最有效的进程间通信方式,是针对其他通信机制运行效率较低而设计的.它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新.这种通信方式需要依靠某种同步机制,如互斥锁和信号量等.
(5)套接字(Socket):这是一种更为一般的进程间通信机制,它可用于网络中不同机器之间的进程间通信,应用非常广泛.起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字.
(6)信号量(Semaphore):主要作为进程之间以及同一进程的不同线程之间的同步和互斥手段.
(7)互斥锁(Mutex):互斥锁主要用于线程同步,它可以对共享资源加锁,任何其他试图在此对互斥量加锁的线程将会阻塞直至当前线程释放该互斥锁,保证每次只有一个线程可以对共享资源访问.
在以上7中方式中,前5种主要用于多任务通信,后两种主要用于多任务间同步.
2016-11-22
Linux下进程间通信概述
评论
发表评论
姓 名: