zoukankan      html  css  js  c++  java
  • Linux进程间通信(IPC)之一——管道

    1 管道(Pipe)

         管道是UNIX系统IPC的最古老的形式,并且所有的Unix系统都提供这种通信机制,当然也包括Linux。这样利用管道进行IPC管道具有如下限制:

    1、历史原因造成管道是半双工的,数据只能单向流动。如果想双向通信,必须要创建两个管道。

    2、管道通信双方必须有亲缘关系的进程之间(父子进程或者兄弟进程之间)。

    2 管道的创建

    #include <unistd.h>
    
    int pipe(int pipefd[2]);

         经由pipefd参数返回两个文件描述符,pipefd[0]描述符用来读取管道中的数据,可以简称为管道的读端;pipefd[1]文件描述符用来向管道写入数据,简称为管道的写端。

         返回的pipefd描述符都位于同一个进程中,没有任何意义。通常调用pipe的进程紧接着调用fork,这样就可以创建从父进程到子进程的管道(父进程 关闭pipefd[0],子进程关闭pipefd[1])或者从子进程到父进程的通信(父进程关闭pipefd[1],子进程关闭pipefd[0]), 用管道进行进程间通信了。

    3 管道的读写

         管道的读写是通过系统调用read和write完成的。pipefd[0]和pipefd[1]分别对应管道的读端和写端,pipefd[0]描述符用来 读取管道中的数据,pipefd[1]文件描述符用来向管道写入数据。如果向pipefd[0]写数据,或者向pipefd[1]读数据都将会得到错误。

         当管道一端关闭之后,遵循如下规则:

    1、当所有的写端都关闭时,当管道中所有的数据都被读取后,read将会返回0,以指示达到了文件末尾。理论上如果还有进程没有关闭管道的写端的话,读端将不会到达文件末尾。

    2、如果管道的读端已经关闭,再向管道写数据的话,将会产生SIGPIPE信号。默认SIGPIPE信号处理是结束当前进程,如果当前进程忽略SIGPIPE信号,则write函数返回-1,errno置为EPIPE。

         系统常量PIPE_BUF定义了管道的大小。该系统常量定义在limits.h中,运行期可以通过pathconf或者fpathconf系统调用查询 PIPE_BUF的值。Linux中PIPE_BUF的值为4096,假如你在编写可移植的程序,请用PIPE_BUF这个宏,而不要用4096这个数值 (不同Unix系统上面PIPE_BUF值的大小是不一样的)。

         对管道写入数据小于等于PIPE_BUF时,系统保证这个写入操作是原子操作,write将会一次性写入管道,并返回,当系统多个进程写管道时,将保证不 会穿插写入。如果写入数据量大于PIPE_BUF,则系统将不再保证写入操作为原子操作,当管道有空间,write就将会写入一部分数据,当所有的数据都 写入管道之后,write返回,当有多个进程同时写管道时,将会出现穿插写入的情况。

    4 管道应用实例

    #include <stdio.h>
    #include <unistd.h>
    #include <errno.h>
    #include <stdlib.h>
    
    int main(void)
    {
    	int n;
    	int fd[2];
    	pid_t pid;
    	char line[1024];
    
    	if(pipe(fd) < 0)
    	{
    		fprintf(stderr, "pipe error: %s\n", strerror(errno));
    		exit(-1);
    	}
    
    	if((pid = fork()) < 0)
    	{
    		fprintf(stderr, "fork error: %s\n", strerror(errno));
    		exit(-1);
    	}
    	else if(pid > 0) /* Parent */
    	{
    		close(fd[1]);
    		n = read(fd[0], line, 1024);
    		write(STDOUT_FILENO, line, n);
    	}
    	else /* Child */
    	{
    		close(fd[0]);
    		write(fd[1], "Hello World\n", 12);
    	}
    }

    通过例子我们可以看到,管道数据流向是从子进程到父进程的。父进程关闭了管道的写端,保留管道的读端,而子进程则关闭了管道的读端,而保留管道的写端。

    5 管道的总结

    通过上面的描述,我们可以总结一下他的特点:

    1、数据单向流动。

    2、没有管道命名,所以只能在有亲缘关系的进程间传递数据。

    3、管道的大小为PIPE_BUF,写入数据不大于这个值则系统保证为原子操作,否则不保证为原子操作。

    4、管道所传递的为无格式字节流。所以需要管道两端的进程之间事先定义好传输协议。

    参考资料:

    UNIX环境高级编程(AUPE)

    Linux环境进程间通信(一)

    原文

  • 相关阅读:
    Saltstack module apache 详解
    Saltstack module ip 详解
    Saltstack module iosconfig 详解
    Saltstack module introspect 详解
    Saltstack module inspector 详解
    Saltstack module ini 详解
    Saltstack module incron 详解
    Modbus 指令 RS485指令规则
    停车系统对接第三方在线支付平台(二)
    停车系统对接第三方在线支付平台
  • 原文地址:https://www.cnblogs.com/xiaoxiaoboke/p/2349774.html
Copyright © 2011-2022 走看看