目录
一、进程间通信
1.通信的技术背景
每个进程都有自己独立的内核数据结构,具有独立性的进程之间如果想要通信的话,成本一定是不低的。
2.进程间通信的目的
a.数据传输:一个进程需要将它的数据发送给另一个进程
b.资源共享:多个进程之间共享同样的资源。
c.通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
d.进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。比如在gdb调试时,用的就是gdb进程控制被调试的进程。
3.为什么要有通信
有时候单独进程的工作是无法满足需求的,所以我们是需要多进程协同完成某种业务内容的。
例如:cat file | grep ‘hello’
4.进程间通信的本质
是为了让不同进程看到同一份资源
5.进程间通信的方式
典型进程间通信方式:管道,共享内存,消息队列,信号量。 除此之外还有网络通信,以及文件等多种方式
二.管道
![](https://i-blog.csdnimg.cn/blog_migrate/3dbbb92d81fac4264f25a22996c53d7b.png)
管道是半双工通信,是可以选择方向的单向通信
管道本质是内核中的一块缓冲区,多个进程通过访问同一块缓冲区实现通信。
匿名管道
匿名管道只能用来进行父子进程之间的通信
匿名管道需要在创建子进程之前创建,因为只有这样才能复制到管道的操作句柄,与具有亲缘关系的进程实现访问同一个管道通信
#include <unistd.h>
功能:创建一无名管道
原型
int pipe(int fd[2]);
参数
fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端
返回值:成功返回0,失败返回错误代码
通过匿名管道写一个代码
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<string.h>
int main()
{
int fd[2];//定义文件描述符数组
int ret=pipe(fd);//创建管道
if(ret==-1)
{
perror("pipe");
exit(1);
}
pid_t pid=fork();//创建子进程
if(pid>0)//父进程 写
{
close(fd[0]);//关闭读端
const char *p= "hello\n";
write(fd[1],p,strlen(p)+1);//写数据
close(fd[1]);
wait(NULL);
}else if(pid==0)//子进程 读
{
close(fd[1]); 关闭写端
char buf[64]={0};
ret=read(fd[0],buf,sizeof(buf));
close(fd[0]);
write(STDOUT_FILENO,buf,ret);
}
return 0;
}
管道总结
管道读写规则
命名管道
创建命名管道
![](https://i-blog.csdnimg.cn/blog_migrate/ab0a3c3b3fc841421b15821321916c89.png)
匿名管道与命名管道的区别
3.共享内存
1.进程间通讯的方式中哪种的访问速度最快?
共享内存的题
共享内存的本质就是开辟一块物理内存,让多个进程映射同一块物理内存到自己的地址空间进行访问,实现数据共享的
共享内存的删除操作并非直接删除,而是拒绝后续映射,只有在当前映射链接数为0时,表示没有进程访问了,才会真正被删除
共享内存生命周期随内核,只要不删除,就一直存在于内核中,除非重启系统(当然这里指的是非手动操作,可以手动删除)
ipcrm 删除进程间通信资源
-m 针对共享内存的操作
-q 针对消息队列的操作
-s 针对信号量的操作
-a 针对所有资源的操作