重定向(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)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章