zoukankan      html  css  js  c++  java
  • 进程间通信:管道

    任务:实现一个类bash的管道符功能程序,可以通过特殊符号例如‘@’将第一个程序的输出作为第二个程序的输入。

    大体思路:

    1. 主进程创建一个管道,得到一对读写fd[2],其中fd[0]用于读,fd[1]用于写。

    2. fork子进程1,通过dup2将子进程的标准输出改为fd[1],然后通过execve执行第一个程序;

    3. fork子进程2,通过dup2将子进程的标准输入改为fd[0],然后通过execve执行第二个程序;

    4. 主进程等待子进程执行结束后退出。

    参考文档:

    http://man7.org/linux/man-pages/man2/pipe.2.html

    http://man7.org/linux/man-pages/man2/wait.2.html

    http://man7.org/linux/man-pages/man2/fork.2.html

    http://man7.org/linux/man-pages/man2/execve.2.html

    http://man7.org/linux/man-pages/man2/dup2.2.html

    代码实现:

    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <string.h>
    #include <sys/wait.h>
    
    int main(int argc, char* argv[]){
        int pipefd[2];
        pid_t cpid[2];
        int i,pargindex,pipeindex,res,wstate1,wstate2;
        char* environ[] = {NULL};
    
        if(argc < 2){
            fprintf(stderr,"Usage: %s <string> @ <string> ...
    ",argv[0]);
            exit(EXIT_FAILURE);
        }
    
        pargindex = 1;
        for(i=1;i < argc;++i){
            if(**(argv+i) == '@'){
                pipeindex = i;
                argv[i] = NULL;
                break;
            }
        }
    
        if (pipeindex > 0) {
            if (pipe(pipefd) == -1){
                perror("pipe error
    ");
                exit(EXIT_FAILURE);
            }
            
            cpid[0] = fork();
            if(cpid[0] == -1){
                perror("fork fail.
    ");
                exit(EXIT_FAILURE);
            }
            
            if (cpid[0] == 0){
                close(pipefd[0]);
                res = dup2(pipefd[1],STDOUT_FILENO);
                if(res == -1){
                    perror("dup2 error
    ");
                    _exit(EXIT_FAILURE);
                }
                execve(argv[pargindex],argv + pargindex,environ);
                perror(argv[pargindex]);
                _exit(EXIT_FAILURE);
            }
    
            cpid[1] = fork();
            if (cpid[1] == -1){
                perror("fork 2 fail");
                exit(EXIT_FAILURE);
            }
            pargindex = pipeindex + 1;
            if (cpid[1] == 0){
                close(pipefd[1]);
                res = dup2(pipefd[0],STDIN_FILENO);
                if(res == -1){
                    perror("dup2 stdin");
                    _exit(EXIT_FAILURE);
                }
                execve(argv[pargindex],argv + pargindex,environ);
                perror(argv[pargindex]);
                _exit(EXIT_FAILURE);
            }
    
            close(pipefd[0]);
            close(pipefd[1]);
            
            if(waitpid(cpid[0],&wstate1,0) == -1){
                perror("waitpid 1");
            }
    
            write(pipefd[1],argv[0],strlen(argv[0]));
            if(waitpid(cpid[1],&wstate2,0) == -1){
                perror("waitpid 2");
            }
            
            exit(EXIT_SUCCESS);
        }
    
        execve(argv[pargindex],argv + pargindex,environ);
        perror(argv[pargindex]);
        exit(EXIT_FAILURE);
    }

    运行效果:

    [root@centos7 c]# ./prog /usr/bin/cat prog.c @ /usr/bin/wc -l
    90
  • 相关阅读:
    asp.net 正则表达式
    字符串分隔
    用定时器实现逐渐放大层的功能
    js获取剪贴板内容
    使用无线网卡共享上网
    使用事件探查器跟踪sqlserver进程
    document.all.WebBrowser.ExecWB
    (转)JAVA与.NET DES加密解密
    web打印的实现
    关于div的定位
  • 原文地址:https://www.cnblogs.com/ling-diary/p/10495882.html
Copyright © 2011-2022 走看看