关键词:
进程间通信
一、 什么是进程间通信
1. 进程间通信的目的
- 数据传输:一个进程需要将它的数据发送给另一个进程
- 资源共享:多个进程之间共享同样的资源。
- 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
- 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。
2. 进程间通信的分类
管道
- 匿名管道
- 命名管道
System V IPC
- system V 消息队列
- system V 共享内存
- system V 信号量
POSIX IPC
- 消息队列
- 共享内存
- 信号量
- 互斥量
- 条件变量
- 读写锁
二、 管道
- 管道是Unix中最古老的进程间通信的形式。
- 从一个进程连接到另一个进程的一个数据流称为一个“管道"
1. 管道
01 管道的符号
ps aux | grep xxx
- ps 本质上都是可执行程序
- grep 可执行程序
02 管道的本质
管道在内核当中是一块缓冲区,供不同的进程读写的缓冲区
2. 匿名管道与命名管道
01 匿名管道
int pipe(int pipfd[2]);
- pipefd:数组,输出型参数。
- pipefd[0],pipefd[1]是pipefd函数填充的,参数当中保存的值是文件描述符,俩个文件描述符分贝对应管道读写俩端。
- pipefd[[0]:管道的读端。
- pipefd[1]:管道的写端。
- 返回值: 0: 匿名管道创建成功。 -1:匿名管道创建失败。
特性:
- 管道是半双工通信的,数据流只能从写端流向读端
- 匿名管道在内核创建出来的缓冲区是没有标识符的,导致了其他进程没有办法之间找到这个缓冲区。但是创建的进程可以通过读写俩端的文件描述符进行操作。
- 匿名管道值支持具有亲缘惯性系的进程进行进程间通信
- 当文件描述符保持基础属性(阻塞),调用read读空管道的时候,则read函数就会阻塞;
- 管道的大小为64k;
- 当文件描述符保持基础属性(阻塞),一直调用write将管道写满之后,则wirte函数就会阻塞。
- 管道的生命周期是跟随进程的
- 管道提供字节流服务
- 从fd[1]当中读取内容的时候,是直接将数据读走了,并不是拷贝
- 管道的大小:64K
- 当对管道进行读写的时候,如果读写的字节大小没超过pipe_size,则管道保证读写的原子性。
代码验证:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main()
int fd[2];
int ret = pipe(fd);
if(ret == -1)
perror("pipe:");
return 0;
printf("fd[0] : %d\\nfd[1] : %d\\n",fd[0],fd[1]);
pid_t pid = fork();
if(pid < 0)
perror("fork:");
return 0;
else if(pid == 0)
// 子进程
close(fd[1]);
char buff[1024]=0;
read(fd[0],buff,sizeof(buff)-1);
printf("child read : %s\\n",buff);
else
// 父进程
close(fd[0]);
char buf[1024]="I am father!";
write(fd[1],buf,strlen(buf));
while(1)
sleep(1);
return 0;
02 命名管道
区别于匿名管道,是由标识符标识的管道,其他进程可以通过管道标识栈找到该管道。
①创建命名管道
命令创建: mkfifo
函数创建: mkfifo函数
int mkfifo(const char *pathname, mode_t mode);
pathname : 要创建的命名管道文件的路径
mode_t : 命名管道的文件权限,八进制数字(0664)
②特性
支持不同进程进行进程间通信的
代码实现:
//read.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
int main()
int fd = open("./fifo",O_RDONLY);
if(fd < 0)
perror("open");
return 0;
char buf[1024]=0;
read(fd,buf,1024);
printf("%s",buf);
return 0;
//write.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main()
int fd = open("./fifo",O_WRONLY);
if(fd < 0)
perror("OPEN:");
return 0;
char buf[]="I am process A!";
write(fd,buf,sizeof(buf)-1);
return 0;
三、 消息队列
- 消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法
- 每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值特性方面
- IPC资源必须删除,否则不会自动清除,除非重启,所以system V IPC资源的生命周期随内核
四、 共享内存
1. 共享内存的原理
- 在物理内存当中开辟一段空间
- 不同的进程通过页表将该空间映射到自己的进程虚拟地址空间当中
- 不同的进程通过操作自己进程虚拟地址空间当中的虚拟地址,来操作共享内存。
2. 共享内存接口
01 shmget
int shmget(key_t key,size_t size,int shmflg);
- key : 共享内存标识符
- size : 共享内存大小
- shmflg : 共享内存的属性信息
IPC_CREAT : 共享内存不存在的话,则创建共享内存
IPC_EXCL | IPC_CREAT:如果共享内存存在,则报错。如果共享内存不存在,则创建。引申含义 : 一定要获取一个是自己创建的共享内存。
按位或上共享内存的权限,权限也是八进制数字 - 返回值:成功则返回共享内存的操作局柄
02 shmat
void *shmat(int shmid, const void *shmaddr, int shmflg);
- shmid : 共享内存操作句柄
- shmaddr :将共享内存附加到共享区当中的那一个地址,一般是传递NULL的值,让操作系统进行分配。
- shmflg : SHM_RDONLY : 只读方式。
- 返回值: 成功: 返回附加的虚拟地址, 失败返回NULL
03 shmdt
int shmdt(const void *shmaddr);
- shmaddr : shmat的返回值
04shmctl
int shmctl(int shmid,int cmd,struct shmid_ds *buf);
- shmid :共享内存操作局柄
- cmd : 告诉shmctl函数完成什么事情
IPC_SET :设置共享内存属性信息, 通过第三个参数获取(入参)
IPC_STAT :获取共享内存属性信息,通过第三个参数获取(出参)
IPC_RMID : 删除共享内存, 第三个参数传递NULL
- buf :共享内存数据结构buf
3. 共享内存的特性
以上就是这篇文章的所有内容啦,感谢老铁有耐心看完。有啥错误请多多指正哈!码字不易,希望大佬们点个赞
《linux从0到99》八进程控制(代码片段)
LINUX进程控制1.进程创建(fork)2.进程终止01_exit函数02exit函数03atexit函数04return退出3.进程等待01进程等待的必要性02进程等待的方法a)wait函数b)waitpid函数03获取子进程status5.进程替换01进程替换原理02进程替换函数6.利用所学... 查看详情
《linux从0到99》六进程概念下(代码片段)
进程概念下1.僵尸进程01僵尸进程的概念03解决僵死状态/僵尸进程04僵尸进程的模拟实现05僵尸进程的危害2.孤儿进程01孤儿进程的概念02孤儿进程的模拟实现03孤儿进程的危害3.进程优先级01PRIandNI02PRIvsNI查看进程优先级的命令4.环境... 查看详情
《linux从0到99》五进程概念上(代码片段)
进程概念上1.冯·诺依曼体系结构2.操作系统01概念02设计OS的目的03OS的定位04对OS所谓管理的理解3.进程01基本概念02描述进程PCB1)task_struct-PCB的一种2)task_struct内容分类03查看进程04通过系统调用获得进程标识符05通过系统... 查看详情
linux中进程间通信(代码片段)
一、整体大纲二、进程间通信概念及方法 Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间。任何一个进程的全局变量在另一个进程中都看不到,所以进程和进程之间不能相互访问,要... 查看详情
《linux从0到99》十一进程信号(代码片段)
进程信号一、信号的概念二、信号的种类1.非可靠信号(非实时信号)2.可靠信号(实时信号)三、信号的产生方式1.硬件产生2.软件产生四、信号的注册五、信号的注销六、信号的处理方式七、信号的捕捉流程1.内... 查看详情
《linux从0到99》十一进程信号(代码片段)
进程信号一、信号的概念二、信号的种类1.非可靠信号(非实时信号)2.可靠信号(实时信号)三、信号的产生方式1.硬件产生2.软件产生四、信号的注册五、信号的注销六、信号的处理方式七、信号的捕捉流程1.内... 查看详情
linux进程间通信总结(代码片段)
进程间通信的概念每个进程各自有不同的用户地址空间,任何一个进程的变量在另一个进程中都是看不到的,所以进程之间要交换数据必须通过内核,在内核中开辟出一块缓冲区。一个进程把自己的数据从用户空间拷... 查看详情
《linux从0到99》八进程控制(代码片段)
LINUX进程控制1.进程创建(fork)2.进程终止01_exit函数02exit函数03atexit函数04return退出3.进程等待01进程等待的必要性02进程等待的方法a)wait函数b)waitpid函数03获取子进程status5.进程替换01进程替换原理02进程替换函数6.利用所学... 查看详情
linux进程间通信消息队列实现两个进程间通信(代码片段)
例子:通过消息队列实现两个进程间通信,一个进程从终端输入数据,通过消息队列发送,另一个进程通过消息队列接收数据 文件1创建进程1终端输入通过消息队列发送数据#include<stdio.h>#include<stdlib.h>#include<errno.h&... 查看详情
linux进程间通信实例(pipesharedmemorysocket)(代码片段)
在Linux下的多个进程间的通信机制叫做IPC(Inter-ProcessCommunication),它是多个进程之间相互沟通的一种方法。Linux中提供有多种进程间通信的方法:管道(Pipes)FIFO(或称namedpipes)消息队列Unix-domainSocket共享内存(Sharedmemory)本文... 查看详情
domainsocket本地进程间通信(代码片段)
...就是UNIXDomainSocket。虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是UNIXDomainSocket用于IPC更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据... 查看详情
[os-linux]详解linux的进程间通信1------管道(代码片段)
本文详解了Linux中进程间通信,包括了进程间通信的介绍,匿名管道和命名管道。目录一、进程间通信的介绍1.进程间通信目的2.进程间通信分类二、管道1.管道是什么2.匿名管道 (1)pipe (2)实现 (3)用... 查看详情
[os-linux]详解linux的进程间通信1------管道(代码片段)
本文详解了Linux中进程间通信,包括了进程间通信的介绍,匿名管道和命名管道。目录一、进程间通信的介绍1.进程间通信目的2.进程间通信分类二、管道1.管道是什么2.匿名管道 (1)pipe (2)实现 (3)用... 查看详情
[linux]详解linux进程间通信(代码片段)
目录前言1.进程间通信的目的2.进程间通信的方式2.1管道2.1.1什么是管道2.1.2管道的本质2.2匿名管道2.2.1匿名管道的接口函数2.2.2从内核的角度理解管道2.2.3匿名管道的特性2.2.4如何将文件描述符设置为非阻塞2.2.5匿名管道的非阻塞特... 查看详情
[linux]详解linux进程间通信(代码片段)
目录前言1.进程间通信的目的2.进程间通信的方式2.1管道2.1.1什么是管道2.1.2管道的本质2.2匿名管道2.2.1匿名管道的接口函数2.2.2从内核的角度理解管道2.2.3匿名管道的特性2.2.4如何将文件描述符设置为非阻塞2.2.5匿名管道的非阻塞特... 查看详情
四十进程间通信——管道的分类与读写(代码片段)
...6.1管道介绍46.1.1管道通信管道是针对于本地计算机的两个进程之间的通信而设计的通信方法,建立管道后,实际获得两个文件描述符:一个用于读取而另一个用于写入最常见的IPC机制,通过pipe系统调用管道是单工的,数据只能... 查看详情
linux进程间通信总结(代码片段)
进程间通信的概念每个进程各自有不同的用户地址空间,任何一个进程的变量在另一个进程中都是看不到的,所以进程之间要交换数据必须通过内核,在内核中开辟出一块缓冲区。一个进程把自己的数据从用户空间拷... 查看详情
linux进程间通信共享内存(代码片段)
1.特点: 1)共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝。如管道当在内核空间创建以后,用户空间需要内存 拷贝,需要拷贝数据,所以效率低。 2)为了在多个进... 查看详情