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环境进程间通信(一)

    原文

  • 相关阅读:
    .netcore3.1添加swagger及JWT Authorize 验证
    Quartz.Net实现简单定时任务调度
    基于.Net Framework进行配置Swagger
    升级anaconda的python版本命令
    使用jmeter自带的html查看测试报告
    软件质量模型的6大特性和27个子特性
    PyQt5基础教程及官方文档
    使用jmeter进行下载并发测试
    selenium官方入门文档
    web driver 驱动配置位置
  • 原文地址:https://www.cnblogs.com/xiaoxiaoboke/p/2349774.html
Copyright © 2011-2022 走看看