进程间通信IPC

     一个大型的应用系统,往往需要众多进程协作,进程间通信的重要性显而易见。

     首先,进程间通信至少可以通过传送打开文件来实现,不同的进程通过一个或多个文件来传递信息,事实上,在很多应用系统里,都使用了这种方法。但一般说来, 进程间通信(IPC:InterProcess Communication)不包括这种似乎比较低级的通信方法。Unix系统中实现进程间通信的方法很多,而且不幸的是,极少方法能在所有的Unix系统中进行移植(唯一一种是半双工的管道,这也是最原始的一种通信方式)。而Linux作为一种新兴的操作系统,几乎支持所有的Unix下常用的进程间通信方法:管道、信号、消息队列、共享内存、信号量、套接口等等。


管道
1. 管道通讯 是 单 向 的,有 固定 的 读端 和 写端 。
2. 数据 被 进 程从管道 读出后 , 在管道 中 该 数据 就 不 存 在 了 。
3. 当进程去读取空管道的 时 候,进 程 会阻塞 。
4. 当进程往满管道写入数据时,进 程 会阻塞 。
5. 管道 容量为 为64KB
管道常用于两个方面:(1)在shell中时常会用到管道(作为输入输入的重定向),在这种应用方式下,管道的创建对于用户来说是透明的;(2)用于具有亲缘关系的进程间通信,用户自己创建管道,并完成读写操作。
无名管道:
当一个管道建立时,会创建两个文件描述符fd[0]、fd[1]。其中fd[0]固定用于读管道,fd[1]固定用于写管道。把fd[0] fd[1]当做文件来操作,一般文件的I/O函数都可以用于管道,如close、read、write等等。它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。
只能用于有亲缘关系的进程之间的通信。半双工通信模式,具有固定的读端和写端。
读端固定:1、写端存在:如果无输入数据,阻塞,如果有输入数据输入多少输出多少
          2、写端不存在:如果管道里有数据有多少读多少,如果管道里没有数据立即返回0
写端固定:1、读端存在:如果管道空间足够大,可以一直向管道写内容。
                       如果管道空间不足,只能输入前面若干个满足管道空间大小的一些字符,剩下的丢失
写端固定:2、读端不存在:系统默认发送信号SIGPIPE结束当前进程。进程结束管道将不存在。
在向管道写入数据时,至少应该存在某一个进程,其中管道读端没有被关闭,否则就会出现管道断裂,进程收到了SIGPIPE信号,默认动作是进程终止)

有名管道
有名管道可以使互不相关的两个进程互相通信,可以通过路径名来指出,并在文件系统中可见。
有名管道遵循先进先出规则。进程通过文件IO操作有名管道。一般文件的I/O函数都可以用于FIFO,如close、read、write等等。
FIFO空间不足 写进程阻塞; FIFO内没有数据,读进程阻塞。  
单独运行读端或者写端都会阻塞,先运行哪个进程就在哪个进程中创建管道。
对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它们不支持诸如lseek()等文件定位操作。

共享内存:
共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝。
内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间
由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等。
读出共享内存后 读出的值还在共享内存中  再次写入后原值被覆盖,用fgets写入会在字符串后面自动加'\0'。
所以下次输出并不输出'\0'后面的字符。

消息队列

消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级

消息的发送者和接收者不需要同时与消息队列互交。消息会保存在队列中,直到接收者取回它。

消息队列可以单独的执行读或写操作,且读出后消息队列里的值被清除。

消息队列允许接收者在消息发送很长时间后再取回消息,但消息队列的这个特点,也造成了一个缺点,就是接收者必须轮询消息队列,才能收到最近的消息。

消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。但消息队列仍然有大小限制。

小结:消息队列与管道以及有名管道相比,具有更大的灵活性,首先,它提供有格式(char)字节流,有利于减少开发人员的工作量;其次,消息具有类型,在实际应用中,可作为优先级使用。这两点是管道以及有名管道所不能比的。同样,消息队列可以在几个进程间复用,而不管这几个进程是否具有亲缘关系,这一点与有名管道很相似;但消息队列是随内核持续的,与有名管道(随进程持续)相比,生命力更强,应用空间更大。


消息队列就是一个消息的链表。不同类型type把消息添加到已打开的消息队列末尾即链表末尾。
相同类型type会把消息以fifo机制存放在这个type下。
消息队列可以单独的执行读或写操作,且读出后消息队列里的值被清除。


信号:
信号是在软件层次上对中断机制的一种模拟,是一种异步(不确定事情发生时间)通信方式。
信号可以直接进行用户空间进程和内核进程之间的交互。如果一个信号被进程设置为阻塞,则该信号的传递被延迟
知道其阻塞被取消时才被传递给进程。
SIGKILL  SIGSTOP不能被忽略
2 SIGINT   ctry + c发送INT信号(SIGINT);默认情况下,这会导致进程终止。
3 SIGQUIT  ctry + \发送QUIT信号(SIGQUIT); 默认会导致进程终止并且将内存中的信息转储到硬盘(核心转储)。
9 SIGKILL   该信号用于立即结束程序的运行,不能被阻塞处理或忽略。           
10 SIGUSR1  自定义信号。通过signal()函数确定信号的作用
12 SIGUSR2  自定义信号。同上         
13 SIGPIPE  管道读端不存在时,向管道中写入数据的进程会收到内核传来的SIGPIPE信号。
14 SIGALRM  alarm对进程设置一个定时器,定时时间到内核就向该进程发送SIGALARM信号,默认终止这个进程
15 SIGTERM  使用kill的时候后面没有信号  默认是15(SIGTERM)终止一个进程    kill 进程号        
17 SIGCHLD  子进程改变状态时,父进程会收这个信号。
18 SIGCONT  使一个T(暂停)状态的进程继续运行(处于后台运行)。
19 SIGSTOP  该信号用于暂停一个进程,且不能被阻塞处理或忽略。           
20 SIGTSTP   ctry + z 发送SIGTSTP信号,默认会导致进程挂起。


信号灯:
也叫信号量,它是不同进程间或一个给定进程内部不同线程间同步和互斥的机制。
二值信号灯:值为0或1,资源可用时值为1,不可用时值为0.
计数信号灯:值在0到n之间,用来统计资源,其值代表可用资源数
等待操作是等待信号灯的值变为大于0,然后将其减1,而释放操作则相反,用来唤醒等待资源的进程或线程。


进程间通信方式比较:
pipe:具有亲缘关系的进程间,单工,数据在内存中。    (管道)
fifo:可用于任意进程间,双工,有文件名,数据在内存。(有名管道)
signal:唯一的异步通信方式。                        (信号)    
shm:效率最高,直接访问内存,需要同步,互斥机制。   (共享内存)
msg:常用于cs模式中,按消息类型访问,可有优先级。   (消息队列)
sem:配合共享内存使用,用以实现同步和互斥。         (信号灯)



管道一般用于数据传输,信号用于事件通知,信号灯用于资源共享

1.随进程持续:IPC一直存在到打开IPC对象的最后一个进程关闭该对象为止。如管道和有名管道;
2.随内核持续:IPC一直持续到内核重新自举或者显示删除该对象为止。如消息队列、信号灯以及共享内存等;
3.随文件系统持续:IPC一直持续到显示删除该对象为止。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值