概念
- 进程是一个独立的资源分配单元,不同进程之间的资源是独立的
- 进程并非孤立的,不同进程需要进行信息的交互和状态的传递,因此需要进程之间的通信【IPC: Inter processes communication】
如qq聊天,qq在每个人的手机上是独立的,聊天室不是孤立的
进程间通信的目的:
- 数据传输:一个进程需要将它的数据发送给另一个进程
- 通知事件:一个进程需要向另一个或一组进程发送消息,通知他们发生了事件
- 资源共享:多个进程之间共享同样的资源,需要内核提供互斥和同步机制
同步和异步:
- 进程控制:有些进程希望完全控制另一进程的执行
管道:
什么是进程间通信
Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间。任何一个进程的全局变量在另一个进程中都看不到,所以进程和进程之间不能相互访问,要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)。
管道的特点:
- 其实是一个在内核内存中维护的缓冲区
- 管道拥有文件的特质:读操作,写操作。匿名管道,有名管道。按照操作文件的方式对管道进行操作
- 一个管道是一个字节流,bytes
- 管道的传递数据是顺序的,单向的。一端写,一端读,半双工的,同一时间只能向一个方向。如对讲机,读取是单向的,但是可以双向传输。
- 使用特性
为什么可以进行管道间的通信?
子进程被fork()出来后,子进程和父进程共享文件描述符
管道数据结构:
循环队列:利用资源
管道的使用:
管道创建步骤:(重点)
- 父进程调用pipe函数创建管道,得到两个文件描述符fd[0]和fd[1],分别指向管道的读端和写端。
父进程调用fork创建子进程,那么子进程也有两个文件描述符指向同一管
父进程关闭管道读端,子进程关闭管道写端。父进程可以向管道中写入数据,子进程将管道中的数据读出,这样就实现了父子进程间通信
参考:使用管道完成父子进程间通信_执迷C++ 的菜鸡的博客-CSDN博客_创建一个有名管道父进程负责将指定的文件内容通过管道发给子进程子进程负责将 很简洁很棒!!看图很容易理解
使用
/* man pipe #include <unistd.h> int pipe(int pipefds[2]); 创建一个匿名管道,用来进程间的通信 */ #include <unistd.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(){ //创建管道,在fork()之前 int pipefds[2]; //得到两个文件描述符fd[0]和fd[1],分别指向管道的读端和写端。 int ret = pipe(pipefds); if (ret == -1){ perror("pipe"); exit(0); } // 创建子进程 pid_t pid = fork(); if (pid > 0){ printf("i am parent process,pid: %d\n",getpid()); char buf[1024] = {0}; //父进程 while (1) { /* code */ int len = read(pipefds[0],buf,sizeof(buf)); // 读端 printf("parent receive : %s ,pid:%d\n",buf,getpid()); } } else if(pid == 0) { /* 子进程*/ printf("i am child process,pid: %d\n",getpid()); while (1) { //向管道中写入数据 char * str = "i am child"; write(pipefds[1],str,strlen(str)); //写端 sleep(1); } } return 0; }
父子进程通信:
关系通信:互相发送
/*
man pipe
#include <unistd.h>
int pipe(int pipefds[2]);
创建一个匿名管道,用来进程间的通信
*/
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
//创建管道,在fork()之前
int pipefds[2]; //得到两个文件描述符fd[0]和fd[1],分别指向管道的读端和写端。
int ret = pipe(pipefds);
if (ret == -1){
perror("pipe");
exit(0);
}
// 创建子进程
pid_t pid = fork();
if (pid > 0){
printf("i am parent process,pid: %d\n",getpid());
char buf[1024] = {0};
//父进程
while (1)
{
/* code */
int len = read(pipefds[0],buf,sizeof(buf)); // 读端
printf("parent receive : %s ,pid:%d\n",buf,getpid());
sleep(1);
//向管道中写入数据
char * str = "i am child";
write(pipefds[1],str,strlen(str)); //写端
sleep(1);
}
}
else if(pid == 0)
{
/* 子进程*/
printf("i am child process,pid: %d\n",getpid());
char buf[1024] = {0};
while (1)
{
//向管道中写入数据
char * str = "i am child";
write(pipefds[1],str,strlen(str)); //写端
sleep(1);
int len = read(pipefds[0],buf,sizeof(buf)); // 读端
printf("child receive : %s ,pid:%d\n",buf,getpid());
}
}
return 0;
}
查看缓冲大小:ulimit -a
pipe size:8块,每块512字节·,也就是4kb.