进程间通信

这里写图片描述
一、管道

管道的作用是在具有亲缘关系的进程之间传递消息,所以管道并不是只可以用于父子进程通信,也可以在兄弟进程之间还可以用在祖孙之间等,反正只要共同的祖先调用了pipe函数,打开的管道文件就会在fork之后,被各个后代所共享。不过由于管道是字节流通信,没有消息边界,多个进程同时发送的字节流混在一起,则无法分辨消息,所有管道一般用于2个进程之间通信,另外管道的内容读完后不会保存,管道是单向的,一边要么读,一边要么写,不可以又读又写,想要一边读一边写,那就创建2个管道。
这里写图片描述

管道的本质是内核维护了一块缓冲区与管道文件相关联,对管道文件的操作,被内核转换成对这块缓冲区内存的操作。

int fd[2]; fd[0] ==>read ———– fd[1]==>write
可以用dup函数将管道作为标准输入输出;
当写数据的管道没有关闭,而又没有数据可读时,read调用通常会阻塞,但是当写数据的管道关闭时,read调用将会返回0而不是阻塞。注意,这与读取一个无效的文件描述符不同,read一个无效的文件描述符返回-1。

二、有名管道

1.有名管道是创建一个真实的文件(存在于文件系统中),使用时打开文件open()/结束后关闭文件close();和普通文件不同的是open()时只能以读/写的方式打开,不能可读可写。
2.创建管道==》mkfifo filename
3.open()中可以设置管道是否为非阻塞的(默认是阻塞的),

注:open调用的阻塞:

》对于以只读方式(O_RDONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_RDONLY),除非有一个进程以写方式打开同一个FIFO,否则它不会返回;如果open调用是非阻塞的的(即第二个参数为O_RDONLY | O_NONBLOCK),则即使没有其他进程以写方式打开同一个FIFO文件,open调用将成功并立即返回。
》对于以只写方式(O_WRONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_WRONLY),open调用将被阻塞,直到有一个进程以只读方式打开同一个FIFO文件为止;如果open调用是非阻塞的(即第二个参数为O_WRONLY | O_NONBLOCK),open总会立即返回,但如果没有其他进程以只读方式打开同一个FIFO文件,open调用将返回-1,并且FIFO也不会被打开

有名管道的安全问题:
多个进程向一个fifo写时,会发生错乱,解决::在一个以O_WRONLY(即阻塞方式)打开的FIFO中, 如果写入的数据长度小于等待PIPE_BUF,那么或者写入全部字节,或者一个字节都不写入。如果所有的写请求都是发往一个阻塞的FIFO的,并且每个写记请求的数据长度小于等于PIPE_BUF字节,系统就可以确保数据决不会交错在一起。

三、消息队列

使用流程:
1、使用int msgget(key_t, key, int flg);创建/访问消息队列,key键值,flg是权限。
2、int msgsend(int id, const void *msg_ptr, size_t msg_sz, int msgflg);添加消息。
3、int msgrcv(int id, void *msg_ptr, size_t msg_st, long int type, int flg);获取消息。
4、int msgctl(int msgid, int command, struct msgid_ds *buf);控制。

@消息队列跟命名管道有不少的相同之处,通过与命名管道一样,消息队列进行通信的进程可以是不相关的进程,同时它们都是通过发送和接收的方式来传递数据的。在命名管道中,发送数据用write,接收数据用read,则在消息队列中,发送数据用msgsnd,接收数据用msgrcv。而且它们对每个数据都有一个最大长度的限制。
@与命名管道相比,消息队列的优势在于,1、消息队列也可以独立于发送和接收进程而存在,从而消除了在同步命名管道的打开和关闭时可能产生的困难。2、同时通过发送消息还可以避免命名管道的同步和阻塞问题,不需要由进程自己来提供同步方法。3、接收程序可以通过消息类型有选择地接收数据,而不是像命名管道中那样,只能默认地接收。

四、共享内存

1、进程通过调用shmget(Shared Memory GET,获取共享内存)来分配一个共享内存块
2、shmat()将这个内存区映射到本进程的虚拟地址空间
3、当一个进程不再须要共享内存时,须要把它从进程地址空间中分离shamdt();
4、shmctl控制对这块共享内存的使用

<1>共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝。
<2>为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间。进程就可以直接读写这一块内存而不需要进行数据的拷贝,从而大大提高效率。
<3>由于多个进程共享一段内存,因此也需要依靠某种同步机制。

几种IPC方式优缺点比较

1、如果用户传递的信息较少,或者只是为了出发某些行为。信号是一种简洁有效的通信方式。但若是进程间要求传递的信息量较大或者存在数据交换的要求,就需要考虑别的通信方式了。
2、无名管道与有名管道的区别在于单向通信以及有关联的进程。
3、消息队列允许任意进程通过共享队列来进行进程间通信。并由系统调用函数来实现消息发送和接收之间的同步。从而使得用户在使用消息缓冲进行通信时不再需要考虑同步问题,使用相对方便。
但是消息队列中信息的复制需要耗费CPU时间,不适宜信息量大或频繁操作的场合。
4、消息队列与管道方式的区别在于,消息队列可以实现多对多,并需要在内存中实现,而管道可以在内存或磁盘上实现。
5、共享内存无须复制,信息量大是其最大的优势。但是需要考虑同步问题。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值