zoukankan      html  css  js  c++  java
  • 进程间通信—无名管道通信

    进程间通信——Interprocess communication——IPC

      每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,进程B再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信。

       不同进程间的通信本质:进程之间可看到一份公共资源;而提供这份资源的形式或者提供者不同,造成了通信方式不同。

      Linux下进程通信方式主要有以下几种:

      1、管道---pipe

      无名管道:可用于具有亲缘关系进程间的通信(例,fork函数建立父子间通信);

      有名管道:除有与无名管道相同功能外,还允许无亲缘关系进程通信;

      2、信号---signal

      信号是在软件层上对中断机制的模拟,较为复杂,用于通知进程某事发生。

      3、消息队列---message queue

      消息队列是消息的链接表,包括Posix消息队列system V消息队列。有读/写权限的进程可以向队列中添加/读走消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。

      4、共享内存---shared memory

      使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。

      5、信号量---semaphore

      要作为进程间以及同一进程不同线程之间的同步和互斥的手段。

      6、套接口---Socket

      使用更为广泛的进程间通信机制,可用于网络中不同主机之间的进程通信。

    管道实现机制:
      管道是由内核管理的一个缓冲区,相当于我们放入内存中的一个纸条。管道的一端连接一个进程的输出。这个进程会向管道中放入信息。管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息。一个缓冲区不需要很大,它被设计成为环形的数据结构,以便管道可以被循环利用。当管道中没有信息的话,从管道中读取的进程会等待,直到另一端的进程放入信息。当管道被放满信息的时候,尝试放入信息的进程会等待,直到另一端的进程取出信息。当两个进程都终结的时候,管道也自动消失。

    一、无名管道

      管道通信会把一个程序的输出直接连接到另外一个程序的输入。

      特点:亲缘关系间通信,单工通信,有固定的读端与写端。

      1、无名管道的创建与关闭

    #include <unistd.h>
    int pipe (int pfd[2]); 
    
    //成功返回0,错误返回-1

      无名管道由调用pipe函数来创建,是基于文件描述符的通信方式。pfd包含两个元素的整形数组,存放文件描述符。pfd[0]用于读管道, pfd[1]用于写管道。

      管道关闭时只需要close()函数关闭两文件描述符即可。

      2、实现管道通信

      (1)父进程创建管道,得到两个文件描述符指向管道的两端

     

     

     

     

     

     

      (2)父进程fork出子进程,子进程也有两个文件描述符指向同一管道

      (3)父进程关闭fd[0],关闭管道读端,可往管道写;子进程关闭fd[1],关闭管道写端,可从管道读。管道是用环形队列实现的,数据从写端写入,从读端读出,进而实现进程间通信。

     1 #include <stdio.h>
     2 #include <unistd.h>
     3 #include <string.h>
     4 #include <errno.h>
     5 
     6 int main(void)
     7 {
     8     int pfd[2];
     9     pid_t pid;
    10     int ret;
    11 
    12     /*1.父进程创建管道,得到文件描述符指向管道两端*/
    13     ret = pipe(pfd); 
    14     if(ret == -1)
    15     {
    16         perror("pipe error
    ");
    17         return -1;
    18     }
    19 
    20     /* 2.父进程fork出子进程,子进程的描述符指向同一管道*/
    21     pid = fork();
    22     if(pid<0)
    23     {
    24         perror("fork error
    ");
    25         return -1;
    26     }else if(pid == 0) //子进程关闭pfd[0]写端,ta可以从管道读
    27     {
    28         close(pfd[0]);
    29         char buf[64] = "I am child process!
    ";
    30         while(1)
    31         {
    32             write(pfd[1],buf,strlen(buf));
    33             sleep(1);
    34         }
    35     }else  //父进程关闭pfd[1]读端,他可以写入管道
    36     {
    37         close(pfd[1]);
    38         char buf[64];
    39         while(1)
    40         {
    41             memset(buf,0,64); //初始化内存空间,防止打印乱码
    42             ret = read(pfd[0],buf,64);
    43             if(ret > 0)
    44             {
    45                 printf("msg from child %s
    ",buf);
    46             }else{
    47                 break;
    48             }
    49         }
    50     }
    51 }
    pipe_test.c

     

      3.管道读取数据的四种情况

    参考:https://blog.csdn.net/skyroben/article/details/71513385

     

      4、获取管道容量大小

      只要写端一直写,读端不读且不关闭fd[0]

     1 #include <stdio.h>
     2 #include <unistd.h>
     3 #include <string.h>
     4 #include <errno.h>
     5 
     6 int main(void)
     7 {
     8     //pfd[0]用于读管道,pfd[1]用于写管道
     9     int pfd[2];
    10     pid_t pid;
    11     int ret;
    12     int i;
    13 
    14     ret = pipe(pfd); //创建管道
    15     if(ret < 0)
    16     {
    17         perror("pipe error!
    ");
    18         return -1;
    19     }
    20     //一直写管道,知道堵塞
    21     for(i=0; i<1000000; i++) 
    22     {
    23         write(pfd[1],"a",1);
    24         printf("i = %d
    ",i);
    25     }
    26 
    27 }

           

       写到65535后就发生了管道阻塞,而65536为64K大小即管道容量。

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法提高 贪吃的大嘴
    Java实现 蓝桥杯VIP 算法提高 贪吃的大嘴
    Java实现 蓝桥杯VIP 算法提高 贪吃的大嘴
    Java实现 蓝桥杯VIP 算法提高 贪吃的大嘴
    Java实现 蓝桥杯VIP 算法提高 士兵排队问题
    Java实现 蓝桥杯VIP 算法提高 士兵排队问题
    Java实现 蓝桥杯VIP 算法提高 士兵排队问题
    Java实现 蓝桥杯VIP 算法提高 士兵排队问题
    Java实现 蓝桥杯VIP 算法提高 数字黑洞
    Minifilter微过滤框架:框架介绍以及驱动层和应用层的通讯
  • 原文地址:https://www.cnblogs.com/y4247464/p/12080201.html
Copyright © 2011-2022 走看看