<430>函數
(1)管道的侷限性ui
1)歷史上,它們是半雙工的。咱們不該假定系統支持全雙工的管道。
this
2)管道只能在具備公共祖先的兩個進程之間使用。如父子進程。
spa
//經由管道從父進程向子進程傳送數據 #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); }
(2)建立管道函數code
int pipe(int pipefd[2]);htm
pipefd[0]用於讀管道,pipefd[1]用於寫管道。進程
POSIX.1容許實現支持全雙工管道。對於這些實現,pipefd[0],pipefd[1]以讀/寫方式打開。ip
(3)get
寫管道時,常量PIPE_BUF規定了內核的管道緩衝區大小。同步
用pathconf或fpathconf函數能夠肯定PIPE_BUF的值。
此例子中子進程執行分頁程序,其標準輸入是管道的讀端。父進程經過管道將文件內容複製到分頁程序。
#include "apue.h" #include <sys/wait.h> #define DEF_PAGER "/bin/more" /* default pager program */ int main(int argc, char *argv[]) { int n; int fd[2]; pid_t pid; char *pager, *argv0; char line[MAXLINE]; FILE *fp; if (argc != 2) err_quit("usage: a.out <pathname>"); if ((fp = fopen(argv[1], "r")) == NULL) err_sys("can't open %s", argv[1]); if (pipe(fd) < 0) err_sys("pipe error"); if ((pid = fork()) < 0) { err_sys("fork error"); } else if (pid > 0) { /* parent */ close(fd[0]); /* close read end */ /* parent copies argv[1] to pipe */ while (fgets(line, MAXLINE, fp) != NULL) { n = strlen(line); if (write(fd[1], line, n) != n) err_sys("write error to pipe"); } if (ferror(fp)) err_sys("fgets error"); close(fd[1]); /* close write end of pipe for reader */ if (waitpid(pid, NULL, 0) < 0) err_sys("waitpid error"); exit(0); } else { /* child */ close(fd[1]); /* close write end */ if (fd[0] != STDIN_FILENO) { if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) err_sys("dup2 error to stdin"); close(fd[0]); /* don't need this after dup2 */ } /* get arguments for execl() */ if ((pager = getenv("PAGER")) == NULL) pager = DEF_PAGER; if ((argv0 = strrchr(pager, '/')) != NULL) argv0++; /* step past rightmost slash */ else argv0 = pager; /* no slash in pager */ if (execl(pager, argv0, (char *)0) < 0) err_sys("execl error for %s", pager); } exit(0); }
(1)
int ferror(FILE *stream);
The function ferror() tests the error indicator for the stream pointed to by stream, returning nonzero if it is set. The error indicator can be reset only by the clearerr() function.
若流出錯返回非0。
(2)
if (fd[0] != STDIN_FILENO) { if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) err_sys("dup2 error to stdin"); close(fd[0]); /* don't need this after dup2 */ }
int dup2(int oldfd, int newfd);
複製一個現有的文件描述符,newfd指定新描述符的值。返回新的文件描述符。
調用dup2和close將一個描述符複製到另外一個上,都要先將兩個描述符進行比較。(若oldfd等於newfd則返回newfd,而不關閉它。最後close將關閉該描述符)
(3)
char *getenv(const char *name);此處使用環境變量PAGER得到用戶分頁程序名稱。這是環境變量的經常使用方法。
The getenv() function searches the environment list to find the environment variable name, and returns a pointer to the corresponding value string.
(4)
char *strrchr(const char *s, int c);
The strrchr() function returns a pointer to the last occurrence of the character c in the string s.
(1)
經過管道也能夠實現父進程與子進程間的同步。