重定向(redirect)與管道(pipe)

基本概念(具體參見APUE):
一個進程控制塊中有多個文件描述符(file descriptor),如:
fd0:標準輸入
fd1:標準輸出
fd2:標準輸錯
fd3:自定義
fd4:自定義
...
每個文件描述符對應一個指向file table的指針。


重定向使用dup()/dup2()系統調用,
dup()的原型爲:

int dup(int filedes)
函數返回當前可用的最小文件描述符,此描述符的file pointer與filedes的file pointer指向相同的file table。

dup2()的原型爲:

int dup(int filedes, int filedes2)
函數指定filedes2與filedes的file pointer指向相同的file table。

下面是一個使用dup()的實例代碼,功能爲使進程的文件描述符1(標準輸出)與文件"file1"的文件描述符的file pointer指向同一個file table,即將進程的標準輸出寫入到文件"file1"中也就是shell中常用的重定向'>'操作。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int main()
{
  int fd;
  if ((fd = open("file1", O_RDWR | O_CREAT | O_TRUNC, 00664)) < 0) {
    perror("open");
    exit(EXIT_FAILURE);
  }
  close(STDOUT_FILENO);
  dup2(fd, STDOUT_FILENO);
  char *buf = "I wrote this string to stdout.\n";
  if (write(STDOUT_FILENO, buf, strlen(buf)) != strlen(buf)) {
    perror("write");
    exit(EXIT_FAILURE);
  }
  exit(EXIT_SUCCESS);
}
總結:這兩個函數的功能是使兩個文件描述符的file pointer指向同一個file table,從而可以共享打開的文件。


管道使用pipe()系統調用,
原型爲:

int pipe(pipefd[2])
其中:
pipefd[0]爲管道的read端
pipefd[1]爲管道的write端
下面是man 2 pipe的一個實例代碼,功能爲父進程向管道的write端寫入argv[1],子進程從管道的read端逐個字符讀入buf,然後輸出到標準輸出。

#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char *argv[])
{
  int pipefd[2];
  pid_t cpid;
  char buf;

  if (argc != 2) {
    fprintf(stderr, "Usage: %s <string>\n", argv[0]);
    exit(EXIT_FAILURE);
  }

  if (pipe(pipefd) == -1) { /× create a pipe */
    perror("pipe");
    exit(EXIT_FAILURE);
  }

  if ((cpid = fork()) < 0) {
    perror("fork");
    exit(EXIT_FAILURE);
  }
  else if (cpid == 0) { /* child process */
    close(pipefd[1]); /* close write end of pipe */
    while (read(pipefd[0], &buf, 1) == 1) /* read from read end of pipe */
      write(STDOUT_FILENO, &buf, 1); /* write buf to STDOUT */
    write(STDOUT_FILENO, "\n", 1);
    close(pipefd[0]);
    _exit(EXIT_SUCCESS);
  }
  else { /* parent process */
    close(pipefd[0]); /* close read end of pipe */
    write(pipefd[1], argv[1], strlen(argv[1])); /* write argv[1] to write end of pipe */
    close(pipefd[1]);
    wait(NULL);
    exit(EXIT_SUCCESS);
  }
}

區別:重定向(redirect)主要是對同一個進程而言的,而管道(pipe)可用於進程間通信(IPC)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章