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大小即管道容量。

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    送股分红是怎么回事?
    基金申购费用计算
    msn 爬楼梯
    沪市证券交易费用
    OS X
    见到郎咸平:)
    Long long time_Blog更新了
    生~气:)
    突然想起去年的今天
    久久沉思以后
  • 原文地址:https://www.cnblogs.com/y4247464/p/12080201.html
Copyright © 2011-2022 走看看