LinuxLinux学习之路

APUE读书笔记-17高级进程通信(2)

2020-08-06  本文已影响0人  QuietHeart

举例:stream pipe使用

这里对前面的协作处理程序使用单个的streams pipe做了一个重新的实现。下面的代码给出了新的main函数,而add2协作处理程序和前面的一样。我们调用了一个新的函数s_pipe来创建一个单一的streams pipe(我们马上会给出这个函数的stream pipes和unix domain sockets两种实现)。

通过streams pipe来调用add2程序的例子

#include "apue.h"
static void sig_pipe(int);      /* our signal handler */

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

    if (signal(SIGPIPE, sig_pipe) == SIG_ERR)
        err_sys("signal error");

    if (s_pipe(fd) < 0)         /* need only a single stream pipe */
        err_sys("pipe error");
    if ((pid = fork()) < 0) {
        err_sys("fork error");
    } else if (pid > 0) {                           /* parent */
        close(fd[1]);
        while (fgets(line, MAXLINE, stdin) != NULL) {
            n = strlen(line);
            if (write(fd[0], line, n) != n)
                err_sys("write error to pipe");
            if ((n = read(fd[0], line, MAXLINE)) < 0)
                err_sys("read error from pipe");
            if (n == 0) {
                err_msg("child closed pipe");
                break;
            }
            line[n] = 0; /* null terminate */
            if (fputs(line, stdout) == EOF)
                err_sys("fputs error");
        }
        if (ferror(stdin))
            err_sys("fgets error on stdin");
        exit(0);
    } else {                                    /* child */
        close(fd[0]);
        if (fd[1] != STDIN_FILENO &&
          dup2(fd[1], STDIN_FILENO) != STDIN_FILENO)
            err_sys("dup2 error to stdin");
        if (fd[1] != STDOUT_FILENO &&
          dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)
               err_sys("dup2 error to stdout");
        if (execl("./add2", "add2", (char *)0) < 0)
            err_sys("execl error");
    }
    exit(0);
}
static void sig_pipe(int signo)
{
    printf("SIGPIPE caught\n");
    exit(1);
}

父进程只使用 fd[0] 进行读写(向 fd[0] 写的内容反应到 fd[1] 的读取中,从 fd[0] 读取的内容来自 fd[1] 的写入),子进程只使用 fd[1] 进行读写。因为streams pipe的每个末端都是全双工的,所以父进程只是读取和写入 fd[0] ;子进程将标准输入输出复制到 fd[1] ,达到对 fd[1] 进行读写的目的(之前是使用了两个半双工管道对应两对文件描述符号,这里只使用一个管道对应一对文件描述符号)。下面的图就展示了结果文件描述符号的情况。注意这里的例子也可以使用不基于流的全双关工的pipes来实现,因为这个例子没有使用任何关于流的特性。

前面说过FreeBSD支持全双工pipes,但是这样的pipes不是基于流机制的。

        协作处理程序中的文件描述符号布局
   Parent                            Child(coprocess)
+----------+                         +--------------+
|          |        /--------------->|  stdin       |
|    fd[0] <-------|---------------->|  fd[1]       |
|          |        \--------------->|  stdout      |
+----------+                         +--------------+

我们定义的s_pipe和标准的pipe函数类似。两个函数使用接收同样的参数,但是s_pipe返回的文件描述符号以读和写的方式打开。

上一篇 下一篇

猜你喜欢

热点阅读