Unix环境高级编程 读书笔记 第十五章 进程间通信

概述

进程间通信,即InterProcess Communication,IPC。
在这里插入图片描述

管道

管道是UNIX系统最古老的IPC形式,但是管道具有以下两个局限性:

  1. 在历史上,管道是半双工的方式,即数据只能在一个方向上流动,当前一些操作系统的实现提供了全双工方式的管道;
  2. 管道只能在具有公共祖先的两个进程之间使用。

管道通过调用函数pipe创建的:

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

经由参数fd返回2个文件描述符,fd[0]为读而打开,fd[1]为写而打开,fd[1]的输出是fd[0]的输入

对于在单个进程中设置管道是没有用处的,通过管道在不同进程之间传输数据。对于父进程与子进程,父进程先调用pipe,接着调用fork,从而创建父进程与子进程之间的IPC通道。
在这里插入图片描述
如果创建从父进程到子进程的管道,则父进程关闭管道的读端(fd[0]),子进程关闭管道的写端(fd[1])。如下图:
在这里插入图片描述
当一个管道的一端被关闭后:

  1. 当读(read)一个写端被关闭的管道时,在所有的数据被读取后,read返回0,表示文件结束(通常一个管道只有一个读进程和一个写进程)。
  2. 如果写(write)一个读端已经被关闭的管道时,会产生SIGPIPE信号,write返回-1,errno设置为EPIPE。

经过管道从父进程向子进程传送数据的范例为:

#include "apue.h"

int main(void)
{
	int     n;
	int     fd[2];
    pid_t   pid;
	char    line[MAXLINE];

	if(pipe(fd) < 0)
        err_sys("pipe error");
    if((pid = fork()) < 0)
    {
        err_sys("fork error");
    }
    else if(pid > 0)  /* parent */
    {
        close(fd[0]);
        write(fd[1], "hello world\n", 12);
    }
    else             /* child */
    {
        close(fd[1]);
        n = read(fd[0], line, MAXLINE);
        write(STDOUT_FILENO, line, n);
    }
    exit(0);
}

函数popen和pclose

标准提供了两个函数,实现创建一个连接到另一个进程的管道,然后读取其输出,或者向其输入发送数据。这两个函数的实现操作是:创建一个管道,fork一个子进程,关闭未使用的管道端,执行一个shell运行命令,然后等待命令终止。函数原型为:

#include <stdio.h>
FILE *popen(const char *cmdstring, const char *type);
/*若成功,返回文件指针,若出错,返回NULL*/

int pclose(FILE *fp);
/*若成功,返回cmdstring终止状态,若出错,返回-1*/

猜你喜欢

转载自blog.csdn.net/jiangzhangha/article/details/86569844