zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    https单向证书
    单例模式再学习
    sql经常出现死锁解决办法
    sqlserver结束和监视耗时的sql
    如何保持进步
    es6-学习
    javascript修改div大小遮挡页面渲染问题
    报表功能设计思考-初步尝试-第一次
    导出统计数据-经验积累-深入1
    Java中数据类型转换&基本类型变量和对象型变量
  • 原文地址:https://www.cnblogs.com/zz1314/p/12890429.html
Copyright © 2011-2022 走看看