美文网首页Linux
APUE读书笔记-17高级进程通信(13)

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

作者: QuietHeart | 来源:发表于2020-08-18 19:53 被阅读0次

    客户端

    open.h头文件

    首先我们定义头文件,包含一些标准头文件和函数的声明:

    #include "apue.h"
    #include <errno.h>
    #define CL_OPEN "open"        /* client's request for server */
    int     csopen(char *, int);
    

    客户进程的main函数(版本1)

    main函数就是一个循环,从标准输入读取路径,然后将文件拷贝到标准输出。这个函数调用csopen来连接打开文件的服务进程,并且返回一个打开的文件描述符号。

    #include    "open.h"
    #include    <fcntl.h>
    #define BUFFSIZE    8192
    int main(int argc, char *argv[])
    {
        int     n, fd;
        char    buf[BUFFSIZE], line[MAXLINE];
    
        /* read filename to cat from stdin */
        while (fgets(line, MAXLINE, stdin) != NULL) {
            if (line[strlen(line) - 1] == '\n')
                line[strlen(line) - 1] = 0; /* replace newline with null */
    
            /* open the file */
            if ((fd = csopen(line, O_RDONLY)) < 0)
                continue;   /* csopen() prints error from server */
    
            /* and cat to stdout */
            while ((n = read(fd, buf, BUFFSIZE)) > 0)
                if (write(STDOUT_FILENO, buf, n) != n)
                    err_sys("write error");
            if (n < 0)
                err_sys("read error");
            close(fd);
        }
    
        exit(0);
    }
    

    csopen函数(版本1)

    创建了s-pipe管道之后,函数csopen调用fork和exec服务进程。

    #include    "open.h"
    #include    <sys/uio.h>     /* struct iovec */
    /*
     * Open the file by sending the "name" and "oflag" to the
     * connection server and reading a file descriptor back.
     */
    int csopen(char *name, int oflag)
    {
        pid_t           pid;
        int             len;
        char            buf[10];
        struct iovec    iov[3];
        static int      fd[2] = { -1, -1 };
    
        if (fd[0] < 0) {    /* fork/exec our open server first time */
            if (s_pipe(fd) < 0)
                err_sys("s_pipe error");
            if ((pid = fork()) < 0) {
                err_sys("fork error");
            } else if (pid == 0) {      /* 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("./opend", "opend", (char *)0) < 0)
                    err_sys("execl error");
            }
            close(fd[1]);               /* parent */
        }
        sprintf(buf, " %d", oflag);     /* oflag to ascii */
        iov[0].iov_base = CL_OPEN " ";      /* string concatenation */
        iov[0].iov_len  = strlen(CL_OPEN) + 1;
        iov[1].iov_base = name;
        iov[1].iov_len  = strlen(name);
        iov[2].iov_base = buf;
        iov[2].iov_len  = strlen(buf) + 1;  /* +1 for null at end of buf */
        len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len;
        if (writev(fd[0], &iov[0], 3) != len)
            err_sys("writev error");
        /* read descriptor, returned errors handled by write() */
        return(recv_fd(fd[0], write));
    }
    

    子进程关闭管道的一端,父进程关闭另外一端。exec服务进程之前,子进程首先将管道的没有关闭的那端dup到其标准输入和标准输出中。(另外一个可以选择的就是将文件描述符号 fd[1] 的ASCII表示作为一个参数传递给服务进程)

    父进程给服务进程发送包含路径和open模式的请求。最后,父进程调用recv_fd来返回文件描述符号或者错误。如果错误被服务进程返回,那么向标准错误输出写相关的信息。

    相关文章

      网友评论

        本文标题:APUE读书笔记-17高级进程通信(13)

        本文链接:https://www.haomeiwen.com/subject/jbhwrktx.html