基本概念(具体参见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)。