dup和dup2
#include <unistd.h>
int dup(int oldfd);
dup
功能:复制某个已打开的文件描述符,得到一个新的文件描述符,这个新的描述符,也指向被复制描述符所指向的文件
比如 4指向了文件a.txt ,从4复制出5,5也指向a.txt
返回值:
成功:返回复制后的新文件描述符
失败:-1 并设置errno
参数:
oldfd:会被复制的已经存在的文件描述符
#include <fcntl.h> #include <string.h> #include <errno.h> #include <unistd.h> int main(int argc,char *argv[]){ int fd1=0; int fd2=0; fd1=open("./file.txt",O_RDWR); // fd2=dup(fd1); fd2=dup2(fd1,5); printf("fd1=%d,fd2=%d\n",fd1,fd2 ); write(fd1,"hello\n",6); write(fd2,"world\n",6); return 0; }
dup2
int dup2(int oldfd, int newfd);
功能:同dup,在dup2中可以指定新文件描述符
如果这个新文件描述符已经被打开,dup2会先把它关闭,再使用
如dup2(2,3)
从2复制出3,让3也指向2所指向的文件,如果3之前被打开过,dup2会关闭它,然后再使用
dup2与dup区别
dup:自己到文件描述符池中找到新文件描述符
dup2:可以自己指定新文件描述符
返回值
成功:返回复制后的新文件描述符
失败:返回-1,设置errno
参数:
oldfd:会被复制的已经存在的文件描述符
newfd:新的文件描述符
文件描述符表
没加O_APPEND为何没有出现覆盖
使用dup,dup2复制文件方式实现文件共享时,不管复制出多少个文件描述符,他们永远只有一个文件表,
所以使用任何一个文件描述符去操作文件时,最后使用的都是通过同一个文件位移量,不管谁操作后文件位移量都会被更新
因此不会出现覆盖
dup,dup2实现重定位
某文件描述符原来指向了A文件,输出数据到A文件,但是重定位后,文件描述符指向了B文件,
输出时数据输出到了B文件,就是改变文件描述符指向
printf的实现是write(1)的调用把文件输出到显示屏幕上,现在把printf的数据写入到file.txt,显然无法改write的底层实现
可以把1这个描述符重新定位到file.txt文件
步骤:
open file.txt 返回一个文件描述符,比如3
close(1)不要让1指向/dev/stdout
使用dup或者dup2把1复制到3 上,也让1指向file.txt
#include <fcntl.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <stdio.h> int main(int argc,char *argv[]){ int fd1=0; int fd2=0; fd1=open("./file.txt",O_RDWR); // close(1); // dup(fd1);//或者 fd2=dup(fd1) dup会找到描述符池中最小的那个 此处即为1 拿来复制返回给fd2即为1 dup2(fd1,1); printf("fd1=%d,fd2=%d\n",fd1,fd2 ); return 0; }
对0重定位实现scanf从file.txt读取数据
#include <fcntl.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <stdio.h> int main(int argc,char *argv[]){ int fd1=0; fd1=open("./file.txt",O_RDWR); //file.txt里是hello world dup2(fd1,STDIN_FILENO); char s[20] ={0}; scanf("%[^\n]",&s); printf("s=%s\n", s); return 0; }
重定位命令
ls>file.txt
ls会调用write(1 ,..)
使用>时会调用dup函数
文件共享操作
1.单进程多次open
2.多个进程多个open