IPC通信概述

一、管道通信

 管道是一种半双工的通信方式,具有固定的读端和写端,而且只支持有血缘关系的进程之间通信。因为管道是只存在于内存中,并不属于任何的系统文件。

  头文件:#include <unistd.h>

  函数原型:int pipe(int pipefd[2]);

  函数参数:fd[0]代表读端,fd[1]代表写端

  函数详解:一旦建立一个管道,就会创建并打开两个文件描述符,当fork出子进程后,也会复制两份相同的文件描述符,这样就可以实现父子进程间的通信。

例子:用pipe实现ps aux |grep bash的命令,并输出到屏幕上。

  补充说明:grep是阻塞式的命令,会匹配到输入并输出到屏幕上。

 1 #include <iostream>
 2 #include <unistd.h>
 3 #include <sys/types.h>
 4 #include <sys/wait.h>
 5 
 6 using namespace std;
 7 int main(int argc, char *argv[])
 8 {
 9     int fd[2];
10     if(pipe(fd) < 0)  // 创建一个管道
11     {
12         cout << "open pipe error" << endl;
13         return -1;
14     }
15     pid_t pid = fork(); // 创建一个子进程
16     if(pid < 0)
17     {
18         cout << "create process failed" << endl;
19     }
20     if(pid == 0)
21     {
22         close(fd[0]);
23         dup2(fd[1], STDOUT_FILENO);  // 将标准输出 重定向到 写端
24         execlp("ps", "ps", "aux", NULL);
25     }
26     else
27     {
28         close(fd[1]);
29         dup2(fd[0], STDIN_FILENO);  // 将标准输入重定向到读端
30         execlp("grep", "grep", "bash", NULL); 
31         wait(NULL);
32     }
33     
34     return 0;
35 }

 二、FIFO实现通信

 FIFO,也称为命名管道,是一种文件类型。

 FIFO也是一种管道,和pipe不同的是,FIFO是以一种特殊设备文件形式存在于文件系统中,支持没有血缘关系的进程间进行通信。

  头文件:#include <sys/types.h>

      #include <sys/stat.h>

  函数原型:int mkfifo(const char *pathname, mode_t mode);

  函数参数:mode参数和open函数中的mode相同

三、mmap通信

  mmap是通过创建一个映射区来实现进程间通信,也就类似于操作同一块内存。

  函数原型:

  

1 #include <sys/mman.h>
2 
3        void *mmap(void *addr, size_t length, int prot, int flags,
4                   int fd, off_t offset);
5        int munmap(void *addr, size_t length);//释放映射区

  函数参数:

  addr:传null

  length:映射区的长度

  prot:PROT_READ 可读 | PROT_WRITE可写

  flag:MAP_SHARED 共享的,对内存的修改会影响到源文件

      MAP_PRIVATE 私有的

  fd:文件描述符,open打开一个文件,如果文件描述符先关闭,对mmap的映射区是没有影响的。

  offset:偏移量,必须为4096的整数倍

  返回值:成功返回可用的内存首地址,失败返回MAP_FAILED

利用mmap实现无血缘关系间的进程通信代码:

write:

 1 #include <iostream>
 2 #include <unistd.h>
 3 #include <sys/mman.h>
 4 #include <string>
 5 #include <stdio.h>
 6 #include <sys/types.h>
 7 #include <sys/stat.h>
 8 #include <fcntl.h>
 9 
10 using namespace std;
11 typedef struct _Student
12 {
13     int sid;
14     char name[20];
15 }Student;
16 int main(int argc, char* argv[])
17 {
18     if(argc != 2){
19         cout << "please take file name!" << endl;
20         return -1;
21     }
22     int fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
23     if(fd < 0){
24         cout << "open failed" << endl;
25     }
26     ftruncate(fd, sizeof(Student));
27     void* addr = mmap(NULL, sizeof(Student), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
28     if(addr == MAP_FAILED){
29         cout << "mmap failed" << endl;
30         return -1;
31     }
32     Student *stu = (Student*)addr;
33     int num = 1;
34     while(1)
35     {
36         stu->sid = num;
37         sprintf(stu->name, "xiaoming--%3d", num++); 
38         sleep(1);
39     }
40     if(munmap(addr, sizeof(Student)) < 0)
41     {
42         cout << "munmap error" << endl;
43         return -2;
44     }
45     return 0;
46 }

read:

 1 #include <iostream>
 2 #include <unistd.h>
 3 #include <sys/mman.h>
 4 #include <sys/types.h>
 5 #include <sys/stat.h>
 6 #include <fcntl.h>
 7 
 8 using namespace std;
 9 typedef struct _Student
10 {
11         int sid;
12         char name[20];
13 }Student;
14 
15 int main(int argc, char *argv[])
16 {
17     if(argc != 2){
18         cout << "please take file name!" << endl;
19         return -1;
20     }
21     int fd = open(argv[1], O_RDWR);
22     if(fd < 0){
23         cout << "open failed" << endl;
24     }
25 
26     void* addr = mmap(NULL, sizeof(Student), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
27     if(addr == MAP_FAILED){
28         cout << "mmap failed" << endl;
29         return -1;
30     }
31     Student *stu = (Student*)addr;
32     while(1){
33         cout << "sid = " << stu->sid << " name = " << stu->name << endl;
34         sleep(1);
35     }
36     return 0;
37 }

 

posted @ 2020-05-14 18:06  妇愁者  阅读(468)  评论(0编辑  收藏  举报