初级文件IO——利用dup、dup2实现文件重定位
API参考:初级文件IO——概述、API
dup复制文件描述符

使用dup、dup2复制方式实现文件共享时,不管复制出多少个文件描述符,它们永远只有一个文件表,所以使用所有描述符去操作文件时,最后使用的都是通过同一个文件位移量,不管谁操作后文件位移量都会被更新,因此不会出现覆盖。
什么是重定位
某文件描述符原来指向了A文件,输出数据是输出到A文件,但是重定位后,文件描述符指向了B文件,输出时数据输出到了B文件,这就是重定位。所谓重定位,说白了就是,文件描述符所指向的文件该变了,使得数据输出的目标文件也随之变。
回顾printf与write的关系

printf输出时,原本通过1,将数据输出到标准输出文件(显示器)的,但是现在,我想让printf输出到file.txt文件,而不是输出到屏幕,应该怎么办?
最简单的办法是就是,把printf函数调用的write函数里面的1,改成指向file.txt文件的新描述符即可,但是不幸的是write中的1写死了,1这个数字改不了,怎么办?
1这个数改不了,但是可以对1进行重定位,让1不再指向标准输出文件,而是指向file.txt,printf的数据,就输出到了file.txt文件中。
实现步骤
①open file.txt文件,返回一个文件描述符,比如3
3 ——> file.txt
②close(1),不要再让1指向标准输出文件(/dev/stdout)
③ 使用dup、dup2把3复制到1上,让1也指向file.txt文件

1这个文件描述符就被重定位了,凡是通过1输出的数据,都被写到了file.txt中,printf底层调用的是write(1, ...),用的也是1,printf的数据就被输出到了file.txt中。相当于printf函数的输出目的地,被重定位为了新的文件,这就是重定位。
代码演示
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <stdlib.h> 6 #include <unistd.h> 7 8 #define FILE_NAME "./file.txt" 9 10 void print_error(char * str) 11 { 12 perror(str); 13 exit(-1); 14 } 15 16 int main(void) 17 { 18 int fd1 = 0; 19 int fd2 = 0; 20 21 fd1 = open(FILE_NAME, O_RDWR|O_TRUNC); 22 if(-1 == fd1) print_error("1 open fail"); 23 //close(1); 24 //dup(fd1); 25 26 dup2(fd1, 1); 27 28 //printf("fd2 = %d\n", fd2); 29 printf("hello world\n"); 30 31 return 0; 32 }
什么时候会使用dup、dup2,来实现从定位
函数中的文件描述符值写死了,无法修改为新的描述符,但是你又希望该函数,把数据输出到其它文件中,此时就可以使用dup、dup2对该函数中的文件描述符,进行重定位,指向新的文件,函数就会将数据输出到这个新文件。
Shell下面的重定位
Shell下面重定位 命令(>)是dup、dup2的典型应用,这个命令在重定位时,就是调用dup、dup2函数来实现的。
>使用的例子
ls > file.txt
ls的结果原本是输出到显示器的,但是>从定位后,就输出到了file.txt文件。
具体从定位的过程
①>命令(程序)会open打开file.txt文件,假设返回的文件描述符是3
3——>file.txt
②ls命令(程序)原本会调用write(1, ...),将结果输出到标准输出文件(显示器),但是 >会调用dup2,把3复制到1上,实现重定位,让1也指向file.txt文件,ls的结果自然就输出到file.txt文件了。


浙公网安备 33010602011771号