可信赖的网站建设公司,网站建设的专业性对搜索引擎营销的影响,wordpress媒体库子目录,网络推广文案策划文章目录管道匿名管道 pipe命名管道 FIFO共享内存共享内存的使用流程#xff1a;消息队列信号量套接字在之前的博客中讲过#xff0c;虚拟空间出现的其中一个目的就是解决 进程没有独立性#xff0c;可能访问同一块物理内存 的问题。因为这种独立性#xff0c;进程之间无法…
文章目录管道匿名管道 pipe命名管道 FIFO共享内存共享内存的使用流程消息队列信号量套接字在之前的博客中讲过虚拟空间出现的其中一个目的就是解决 进程没有独立性可能访问同一块物理内存 的问题。因为这种独立性进程之间无法直接进行通信操作系统为了解决这种问题提出了多种适用于不同情境下的通信方式
数据传输管道、消息队列数据共享共享内存进程控制信号量 管道
管道的本质其实就是内核中的一块缓冲区多个进程通过访问同一个缓冲区就可以实现进程间的通信。自 Linux 2.6.11 内核起管道容量的大小默认是 65536 字节但可以通过 fcntl函数 来修改管道容量。 管道分为两种匿名管道、命名管道 匿名管道 pipe
因为没有具体的文件描述符所以只能用于具有亲缘父子关系的进程之间的通信。
原理 父进程在创建管道的时候操作系统会返回管道的文件描述符然后生成子进程时子进程会通过拷贝父进程的 pcb 来获取到这个管道的描述符所以他们可以通过这个文件描述符来访问同一个管道来实现进程间的通信。而不具备亲缘关系的进程则无法通过这个文件描述符来访问同一个管道。 返回值成功返回 0失败返回 -1 。 也就是说读/写操作的流程是
关闭 读/写 端进行 写/读 操作写/读 完关闭 写/读 端
图解父子进程通过管道通信的流程 一开始父进程创建管道 父进程fork创建子进程 关闭多余描述符 代码示例示例一 示例二
如果没有特意规定那么父子进程究竟是谁先执行是不确定的假设如果子进程还没写入父进程却已经开始读了这时候应该是会读不到东西的会在屏幕上输出空行但是这种情况并没有发生这里就牵扯到了管道的读写特性
如果管道中没有数据则调用 read 读取数据会阻塞。如果管道中数据满了则调用 write 写入数据会阻塞。如果管道的所有 读端 被关闭继续调用 write 时会因为无法读出而产生异常导致进程退出。如果管道的所有 写端 被关闭继续调用 read 时read 读完管道中的所有数据后不再阻塞返回 0 退出。 命名管道 FIFO
命名管道也是内核中的一块缓冲区但是它 具有标识符 。这个标识符是一个可见于文件系统的管道文件能够被其他进程找到并打开管道文件来获取管道的操作句柄多个进程可以通过打开这个管道文件来访问同一块缓冲区来实现通信。
可以在没有亲缘关系非父子的进程之间进行通信这是与无名管道最大的区别。他是以一个特性的文件存储在文件系统中, 所以对他的操作与其路径名有关联。
接口
int mkfifo(const char *filename,mode_t mode);filename——管道的标识符通过这个标识符来访问管道创建之前这个标识符必须不存在。 mode——权限掩码。 返回值——若成功则返回 0否则返回 -1 。 代码示例 命名管道实现进程的信息传递【mkfifo函数、open函数】
open 打开命名管道的特性
若文件以只读打开则会阻塞直到文件被以写的方式打开。若文件以只写打开则会阻塞直到文件被以读的方式打开。
管道的特性
管道是半双工通信可以选择方向的单向传输这个可以从上面的示意图看出来。管道的读写特性无论命名匿名都一样。管道声明周期随进程打开管道的所有进程退出后管道就会被释放。管道提供字节流传输服务。命名管道额外有一个打开特性只读打开会阻塞直到被以写打开只写打开会阻塞直到被以读打开。管道自带同步和互斥。 共享内存
共享内存即在 物理内存 上开辟一块空间然后 多个进程 通过 页表 将这 同一个物理内存 映射到自己的 虚拟地址空间 中通过自己的 虚拟地址空间 来访问这块 物理内存 达到了数据共享的目的。 也正是因为这种特性使得 共享内存成为了最快的进程间通信的方式 因为它 直接通过虚拟地址来访问物理内存比前面的管道和后面的消息队列 少了内核态和用户态的几次数据拷贝和交互 。
特点
生命周期随内核。由于多个进程可以同时操作因此需要进行同步。但不自带同步与互斥而是借助信号量来实现同步与互斥。 共享内存的使用流程
1. 创建共享内存
头文件
#include sys/ipc.h
#include sys/shm.h
定义函数
int shmget(key_t key, size_t size, int shmflg)
参数
key:这个共享内存段名字
size:共享内存大小
shmflg:由九个权限标志构成它们的用法和创建文件时使用的mode模式标志是一样的。返回值成功返回共享内存标识符失败返回-1。2. 将共享内存映射到虚拟地址空间
头文件
#include sys/types.h
#include sys/shm.h
定义函数
void *shmat(int shmid, const void *shmaddr, int shmflg)
参数
shmid: 共享内存标识
shmaddr:指定连接的地址
shmflg:权限标志返回值成功返回指向共享内存映射在虚拟地址空间的指针即首地址失败返回-1。3. 共享内存管理
头文件
#include sys/types.h
#include sys/shm.h
定义函数
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
参数
shmid:由shmget返回的共享内存标识码
cmd:将要采取的动作
buf:指向一个保存着共享内存的模式状态和访问权限的数据结构返回值成功返回0失败返回-1
4. 解除映射关系
头文件
#include sys/types.h
#include sys/shm.h
定义函数
int shmdt(const void *shmaddr)
参数shmaddr: 由shmat所返回的指针
返回值成功返回0失败返回-1消息队列
概念
消息队列是内核中的一个优先级队列多个进程通过访问同一个队列进行添加节点或者获取节点来实现通信。消息队列是消息的连接表, 放在内核中, 一个消息队列由一个标识符表示。消息队列是面向记录的, 其中的消息具有特定的格式以及特定的优先级。消息队列独立于发送和接受进程中, 也就是当一个进程被销毁, 他在消息队列中的信息是不会被删除的。消息队列中的内容可以实现随机查询, 也就是消息不一定要以 FIFO 读取, 也可以按消息的类型读取。
特性
自带同步与互斥生命周期随内核
流程
1. 创建消息队列
头文件
#include sys/types.h
#include sys/ipc.h
#include sys/msg.h
定义函数
int msgget(key_t key, int msgflg)
参数
key:消息队列对象的关键字
msgflg:消息队列的建立标志和存取权限返回值成功执行时返回消息队列标识值。失败返回-12. 进程可以向队列中添加/获取节点
头文件
#include sys/types.h
#include sys/ipc.h
#include sys/msg.h
添加节点
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
获取节点
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
参数
msqid:消息队列对象的标识符
msgp:消息缓冲区指针
msgsz:消息数据的长度
msgtyp:决定从队列中返回哪条消息
msgflg:消息队列状态返回值成功执行时返回0。失败返回-13. 删除消息队列
头文件
#include sys/types.h
#include sys/ipc.h
#include sys/msg.h
定义函数
int msgctl(int msqid, int cmd, struct msqid_ds *buf)
参数
msqid:消息队列对象的标识符
cmd:函数要对消息队列进行的操作
buf:取出系统保存的消息队列的 msqid_ds 数据并将其存入参数 buf 指向的 msqid_ds 结构中返回值成功执行时返回0。失败返回-1信号量
概念
信号量与IPC结构不同它其实是 内核中的一个计数器和阻塞队列 通过信号量来对 临界资源的访问进行控制来 实现进程间的同步与互斥 而不是用于进程间消息的通信的。信号量用于进程间同步若要在进程间传递数据需要结合共享内存。信号量基于操作系统的 PV 操作程序对信号量的操作都是原子操作。每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1而且可以加减任意正整数。
例如有一个能容纳 n 人的餐厅用一个计数器表示 n如果有人进入则 n - 1如果有人出来则 n 1只有 n 0 时才能进入如果 n 0 时则说明没有位置需要将进程挂起并放入阻塞队列中直到有人出来使资源释放时才能将后续进程从阻塞队列中唤醒获取资源。
同步通过条件判断实现临界资源访问的合理性互斥通过同一时间的唯一访问来实现临界资源访问的安全性
POSIX信号量 POSIX 信号量和 SystemV 信号量作用相同都是用于同步操作达到无冲突的访问共享资源目的。 但 POSIX 可以用于线程间同步。
流程
#include semaphore.h//初始化信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
/*
参数
pshared:0表示线程间共享非零表示进程间共享
value:信号量初值
*///销毁信号量
int sem_destroy(sem_t *sem);//等待信号量
int sem_wait(sem_t *sem);
//功能等待信号量会将信号量的值减1//发布信号量
int sem_post(sem_t *sem);
//功能发布信号量表示资源使用完毕可以归还资源了。将信号量值加1。 套接字
使用套接字也可以实现进程间的通信与其他机制不同的是它可以实现不同机器之前的进程间的通信。