“我正在参加「掘金·启航计划」”
一、dup2
✔ 测试用例一:
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
//输出重定向
int main01()
{
int fd = open("log.txt", O_WRONLY|O_CREAT, 0644);
if(fd < 0)
{
perror("open");
return 1;
}
dup2(fd, 1);//此时再写入就不是标准输出,而是fd
const char* msg = "hello dup2->output\n";
int i = 0;
while(i < 5)
{
write(1, msg, strlen(msg));
i++;
}
close(fd);
return 0;
}
//输入重定向
int main02()
{
int fd = open("log.txt", O_RDONLY);
if(fd < 0)
{
perror("open");
return 1;
}
dup2(fd, 0);//此时再读就不是从标准输入读,而是fd
char buffer[1024];
ssize_t sz = read(0, buffer, sizeof(buffer) - 1);
if(sz > 0)
{
buffer[sz] = 0;
printf("%s", buffer);
}
close(fd);
return 0;
}
//追加重定向
int main03()
{
int fd = open("log.txt", O_WRONLY|O_APPEND);
if(fd < 0)
{
perror("open");
return 1;
}
dup2(fd, 1);//此时再写入就不是标准输出,而是fd
const char* msg = "hello dup2->append\n";
int i = 0;
while(i < 5)
{
write(1, msg, strlen(msg));
i++;
}
close(fd);
return 0;
}
-
我们之前自己实现重定向时是先 close 被重定向的文件,再 open 想重定向的文件。有没有可以不 close 被重定向的文件,直接重定向,此时系统提供了类似的接口 dup2 来解决 close 多此一举的行为。
-
使用 dup2,需要包含 unistd 头文件,
要输出的文件描述符是 1,而要重定向的目标文件描述符是 fd(echo "hello" > log.txt),dup2 应该怎么传参 —— dup2(1, fd) || dup2(fd, 1) ❓
很明显,依靠函数原型,我们就能认为 dup2(1, fd),因为 1 是先打开的,而 fd 是后打开的,可实际上并不是这样的。文档中说 newfd 是 oldfd 的一份拷贝,这里拷贝的是文件描述符对应数组下标的内容,所以数组内容,最终应该和 oldfd 一致。换言之,这里就是想把 1,不要指向显示器了,而指向 log.txt,fd 也指向 log.txt。所以这里的 oldfd 对应 fd,newfd 对应 1,所以应该是 dup2(fd, 1)。
-
运行结果
==输出重定向==
==输入重定向==
==追加重定向==
-
所以现在我们就明白了:
echo "hello world" > log.txt—— echo 是一个进程;"hello world" 默认是调用 printf 或 write 往显示器上输出;log.txt 是调用 open 使用 O_WRONLY|O_CREAT 打开;> 是调用 dup2,将默认标准输出 1 的内容改为 log.txt;<就是 dup2(fd, 0),且 open 文件的方式是 O_RDONLY;>>同 >,都是 dup2(fd, 1),只不过它打开文件的方式是 O_WRONLY|O_APPEND; -
进程替换时,是否会干扰重定向对应的数据结构 ❓
换言之,将来 fork,创建子进程,子进程会以父进程的大部分数据为模板,子进程进行程序替换时,并不会影响曾经打开的文件,也就不会影响重定向对应的数据结构。