linux进程通信1:进程通信概述,管道通信原理(无名管道,有名管道),管道编程实战 - 日理万妓 2022-12-14 12:22 240阅读 0赞 ## 进程通信概述,管道通信原理(无名管道,有名管道),管道编程实战 ## **1.进程间通信概述:** 举例1: 你手机微信和别人手机微信通信 举例2: 如:父子进程wait 和 exit之间的通信 **进程间通信(IPC)**:指在不同进程之间传播或交换信息 **进程间通信(IPC)的通信方式:** IPC的方式通常有管道(包括无名管道和命名管道), 消息队列, 信号量, 共享存储, socket,streams等, 其中socket和streams支持不同主机上的两个进程IPC **2. 管道通信原理:** **管道**:通常指无名管道,是UNIX系统IPC最古老的形式 特点: > 半双工(数据只能在一个方向上流动),具有固定的读端和写端只能用于具有亲缘关系进程间通信(父子兄弟) > 它可以看作文件,对于它的读写可用read,write等函数, > 但是它不是普通的文件,并不属于其它任何文件系统,并且只存在于内存中 注意:管道中的数据读走后就没了。 pipe函数原型: #include<unistd.h> int pipe(int fd(2));//返回值:成功:0,失败:-1 当一个管道建立时,它会创建两个文件描述符:fd\[0\]为读而打开,fd\[1\]为写而打开。如下图: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDczNDUxNA_size_16_color_FFFFFF_t_70_pic_center] 要关闭管道只需将这两个文件描述符关闭即可。 **例子:** 单个进程中的管道几乎没有任何用处。所以,通常调用 pipe 的进程接着调用 fork,这样就创建了父进程与子进程之间的 IPC 通道。如下图所示: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDczNDUxNA_size_16_color_FFFFFF_t_70_pic_center 1] 若要数据流从父进程流向子进程,则关闭父进程的读端(fd\[0\])与子进程的写端(fd\[1\]);反之,则可以使数据流从子进程流向父进程。 参考代码: #include<stdio.h> #include<unistd.h> int main() { int fd[2]; // 两个文件描述符 pid_t pid; char buff[20]; if(pipe(fd) < 0) // 创建管道 printf("Create Pipe Error!\n"); if((pid = fork()) < 0) // 创建子进程 printf("Fork Error!\n"); else if(pid > 0) // 父进程 { close(fd[0]); // 关闭读端 write(fd[1], "hello world\n", 12); } else { close(fd[1]); // 关闭写端 read(fd[0], buff, 20); printf("%s", buff); } return 0; } 运行结果: ![在这里插入图片描述][20201013165609973.png_pic_center] 其中包含的读写函数原型: #include <unistd.h> int pipe(int pipef d[2]); #include <unistd.h> ssize_t write(int fd, const void *buf, size_t count); ssize_t read(int fd, void *buf, size_t count); 3.管道编程实战: 参考代码: #include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> //管道的原型:int pipe(int pipe fd[2]); int main() { int fd[2]; int pid;//fork的返回值 char buf[128]; if(pipe(fd)==-1) { printf("创建管道失败\n"); } pid=fork();//父进程会拷贝一个空间给子进程 if(pid<0) { printf("创建子进程失败\n"); }else if(pid>0) { sleep(3);//父进程睡3秒,保证子进程先运行,,子进程会阻塞 printf("进入了父进程id:%d\n",getpid()); close(fd[0]);//关掉父进程的管道读操作 write(fd[1],"hello from father",strlen("hello from father")); wait(NULL);//不让父进程直接结束,子进程成孤儿 }else { printf("进入了子进程id:%d\n",getpid()); close(fd[1]);//关掉父进程的管道写操作 read(fd[0],buf,128);//读到buf里面,读wei字节 printf("read:%s\n",buf); exit(0); } return 0; } 代码:实现子进程与父进程之间的通信。 运行结果: ![在这里插入图片描述][20201013171452910.png_pic_center] **4.命名管道:** **FIFO**:也称为命名管道,它是一种文件类型 **特点:** > FIFO可以在无关的进程之间交换数据,与无名管道不同。 > FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中 fifo函数原型: #include <sys/types.h> #include <sys/stat.h> int mkfifo(const char *pathname, mode_t mode);//创建 // 返回值:成功返回0,出错返回-1 //其中的 mode 参数与open函数中的 mode 相同。一旦创建了一个 FIFO,就可以用一般的文件I/O函数操作它。 //如果命名管道文件已经存在,则会创建失败 演示代码: #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <errno.h> //int mkfifo(const char *pathname, mode_t mode); int main() { int ret=mkfifo("./file",0600);//创建命名管道(文件),0600:可读可写的方式 if(ret==0) { printf("创建成功\n"); } if(ret==-1) { printf("创建失败\n"); perror("why");//打印失败原因 } } 运行结果: ![在这里插入图片描述][20201013172720286.png_pic_center] 注意: 此种创建如果文件存在,创建也失败,说明不完善 修改演示代码如下: #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <errno.h> //int mkfifo(const char *pathname, mode_t mode); int main() { if((mkfifo("./file",0600)==-1)&&errno!=EEXIST)//同时满足错误吗:文件已存在 { printf("创建失败\n"); perror("why"); }else { if(errno==EEXIST) { printf("文件有啦\n"); }else { printf("创建成功\n"); } } return 0; } 运行结果: ![在这里插入图片描述][20201013172920389.png_pic_center] **5.命名管道编程通信编程实现:** open函数原型: #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *pathname, int flags); //当 open 一个FIFO时,是否设置非阻塞标志(O_NONBLOCK)的区别: //默认没有设置, //只读 open :要阻塞---到某个其他进程为写而打开此 FIFO文件。 //类似的,只写 open 要阻塞---到某个其他进程为读而打开它。 演示代码: 打开并只读: #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <errno.h> #include <fcntl.h> //int mkfifo(const char *pathname, mode_t mode); int main() { char buf[30]={ 0}; if((mkfifo("./file",0600)==-1)&&errno!=EEXIST)//同时满足错误吗:文件已存在 { printf("创建失败\n"); perror("why"); } int fd=open("./file",O_RDONLY);//仅只读这个管道文件 printf("打开成功\n"); int nread=read(fd,buf,30);//一次读20个字节...返回字节数 printf("read %d byte from fifo\ncontext:%s\n",nread,buf); close(fd); return 0; } 打开并只写: #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <errno.h> #include <fcntl.h> #include <string.h> //int mkfifo(const char *pathname, mode_t mode); int main() { char *str="vnfvjdknvdrij"; int fd=open("./file",O_WRONLY);//仅只写这个管道文件 printf("写入打开成功\n"); write(fd,str,strlen(str)); close(fd); return 0; } 注意:读写同时打开才能进行操作 运行结果: ![在这里插入图片描述][20201013173913787.png_pic_center] 说明: 若指定了O\_NONBLOCK(非阻塞)无意义,则只读 open 立即返回。而只写 open 将出错返回 -1 如果没有进程已经为读而打开该 FIFO,其errno置ENXIO。 一般使用FIFO的时候,都是以非阻塞方法打开 上述例子可以扩展成 客户进程—服务器进程 通信的实例,write\_fifo的作用类似于客户端,可以打开多个客户端向一个服务器发送请求信息,read\_fifo类似于服务器,它适时监控着FIFO的读端,当有数据时,读出并进行处理,但是有一个关键的问题是,每一个客户端必须预先知道服务器提供的FIFO接口,下图显示了这种安排: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDczNDUxNA_size_16_color_FFFFFF_t_70_pic_center 2] [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDczNDUxNA_size_16_color_FFFFFF_t_70_pic_center]: /images/20221123/ce7e6bbd1d604f14b362efc298084e81.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDczNDUxNA_size_16_color_FFFFFF_t_70_pic_center 1]: /images/20221123/3270c83949d945cdac75031f5ce0caba.png [20201013165609973.png_pic_center]: /images/20221123/bff131813c314643be986d488a678d80.png [20201013171452910.png_pic_center]: /images/20221123/98578c58aa87434bbb6ae4c7b7e8438e.png [20201013172720286.png_pic_center]: /images/20221123/6ee1768cbf77409f8310a6ec669e85b4.png [20201013172920389.png_pic_center]: /images/20221123/c5324e55e7a6424b8ac29dd7b9fdccb9.png [20201013173913787.png_pic_center]: /images/20221123/a28c1c32e5b147e2abb1480218f0d900.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDczNDUxNA_size_16_color_FFFFFF_t_70_pic_center 2]: /images/20221123/f2523fbc56d24cd3848fb65512655356.png
还没有评论,来说两句吧...