任務:實現一個類bash的管道符功能程序,能夠經過特殊符號例如‘@’將第一個程序的輸出做爲第二個程序的輸入。html
大致思路:linux
1. 主進程建立一個管道,獲得一對讀寫fd[2],其中fd[0]用於讀,fd[1]用於寫。centos
2. fork子進程1,經過dup2將子進程的標準輸出改成fd[1],而後經過execve執行第一個程序;bash
3. fork子進程2,經過dup2將子進程的標準輸入改成fd[0],而後經過execve執行第二個程序;centos7
4. 主進程等待子進程執行結束後退出。spa
參考文檔:code
http://man7.org/linux/man-pages/man2/pipe.2.htmlhtm
http://man7.org/linux/man-pages/man2/wait.2.htmlblog
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> ...\n",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\n"); exit(EXIT_FAILURE); } cpid[0] = fork(); if(cpid[0] == -1){ perror("fork fail.\n"); exit(EXIT_FAILURE); } if (cpid[0] == 0){ close(pipefd[0]); res = dup2(pipefd[1],STDOUT_FILENO); if(res == -1){ perror("dup2 error\n"); _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