目录
一、回顾重定向命令
1.输出重定向 >
echo xxx > filename:将数据写入到文件中
文件不存在则创建文件再写入;文件存在则先清空再写入
2.追加重定向 >>
echo xxx >> filename:将数据写入到文件中
文件不存在则创建文件再写入;文件存在则在文件末尾追加写入数据
3.输入重定向 <
cat < filename:将文件中的数据读取到显示器中
二、重定向原理
Linux系统中被打开的文件都会有一个文件描述符,并且文件描述符的分配原则是:在文件描述符表files_struct的指针数组当中,找到当前没有被使用的 最小的一个下标,作为新的文件描述符。
进程会默认打开文件描述符分别为0、1、2的标准输入、标准输出和标准错误,所以如果我们关闭标准输出1,那么进程再打开另外一个文件,则该文件的文件描述符就为1。但是进程并不知道此时标准输出被关闭了,依然认为文件描述符为1的文件就是标准输出。根据这个原理,我们就可以实现输出重定向:将原本输出到显示器的数据,输出到文件中
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
const char* filename = "log.txt";
int main() {
close(1); // 关闭标准输出
int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
if (fd == -1) {
perror("open");
return 1;
}
// 输出到文件描述符为1的文件中,即输出到log.txt文件中
printf("111111111111\n");
fprintf(stdout, "2222222222222222\n");
fflush(stdout);//将数据刷新到语言级缓冲区
close(fd);
return 0;
}
同理,追加重定向就是在打开文件时O_TRUNC选项改为O_APPEND选项即可
输入重定向:关闭标准输入0
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
const char* filename="log.txt";
int main() {
close(0); // 关闭标准输入
int fd = open(filename, O_RDONLY);
if(fd == -1) {
perror("open");
return 1;
}
// 此时,新打开的文件log.txt的文件描述符为0
char buf[1024]; // 缓冲区
fgets(buf, sizeof(buf), stdin); // stdin指向文件描述符为0的文件,即指向log.txt,所以是从文件log.txt中读取数据
printf("%s\n", buf); // 输出数据
close(fd);
return 0;
}
三、dup2函数
dup2函数时C语言中的用于操作文件描述符的函数,它可以用来复制一个现有的文件描述符,使得新的文件描述符与现有的文件描述符共享相同的文件,使用该函数就可以重定向标准输入、标准输出和标准错误流。
int dup2(int oldfd, int newfd);
oldfd:现有的文件描述符
newfd:新的文件描述符
返回值:调用成功返回新的文件描述符,调用失败返回-1并设置全局变量 errno
以指示错误原因。
上述重定向原理中,利用文件描述符分配规则,将标准输出1关闭,新打开的文件其文件描述符就是1。而有了dup2函数后,直接将需要重定向的文件复制到标准输入/输出/错误中。
以输出重定向为例
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main() {
int fd = open("log.txt", O_CREAT | O_RDWR | O_TRUNC);
if (fd == -1) {
perror("open");
return 1;
}
if (dup2(fd, 1) == -1) {
perror("dup2");
return 1;
}
printf("hello linux file!\n");
fflush(stdout); // 确保将输出缓冲区的数据写入文件
close(fd);
return 0;
}