open返回得到的文件描述符fd可以进行复制,复制成功之后可以得到一个新的文件 描述符,使用新的文件描述符和旧的文件描述符都可以对文件进行IO操作,复制得到的文件描述符和旧的文件描述符拥有相同的权限。
在Linux系统下,可以使用dup或dup2这两个系统调用对文件描述符进行复制。
1.dup
用于并可以多次复制文件描述符,复制得到的文件描述符与原文件描述符都指向同一个文件表,它们的文件偏移量是一样的,所以写入的内容不会被覆盖。
1)头文件
#include
2)函数原型
int dup(int oldfd);
3)参数
oldfd:表示需要被复制的文件描述符。
4)返回值
成功时将返回一个新的文件描述符,由操作系统分配,分配置原则遵循文件描述符分配原则;如果复制失败将返回-1,并且会设置errno值。
5)示例:(复制一个文件描述符,并循环写入特定内容)
#include
#include
#include
#include
#include
#include
int main()
{
char buf[20] = "duptest";
int fd1, fd2, i;
fd1 = open("test", O_RDWR | O_CREAT | O_TRUNC, 0666); //打开文件ftest
if (fd1 < 0) {
printf("error: ftest openn");
return -1;
}
fd2 = dup(fd1); //复制fd1
if (fd2 < 0) {
printf("error: dupn");
close(fd1);
return -1;
}
for (i = 0; i < 7; i++) { //循环7次,写入duptest
if ( write(fd1, &buf, 1) < 0 ) { //先向fd1写入
printf("error: fd1 write, i=%dn", i);
close(fd1);
close(fd2);
return -1;
}
if ( write(fd2, &buf, 1) < 0 ) { //再向fd2写入
printf("error: fd2 write, i=%dn", i);
close(fd1);
close(fd2);
return -1;
}
}
if (lseek(fd1, 0, SEEK_SET) < 0) { //将位置指针设置到文件开头
printf("error: fd1 lseekn");
close(fd1);
close(fd2);
return -1;
}
if (read(fd1, buf, 14) < 0) { //读取文件内容
printf("error: fd1 readn");
close(fd1);
close(fd2);
return -1;
}
printf("fd1=%d,fd2=%d,dup test:%sn", fd1, fd2, buf);
close(fd1);
close(fd2);
return 0;
}
6)编译运行并查看测试结果
fd1=3,fd2=4,dup test:dduupptteessttst //打印内容是连续写的,说明复制的文件描述符共用文件偏移量
2.dup2
相比于dup,dup2可以手动指定复制得到的文件描述符,而不需要遵循文件描述符分配原则。
1)头文件
#include
2)函数原型
int dup2(int oldfd, int newfd);
3)参数
oldfd:需要被复制的文件描述符。
newfd:指定一个新的文件描述符(当前进程没有使用到的文件描述符)。
4)返回值
成功时将返回一个手动指定的文件描述符newfd;如果复制失败将返回-1,并且会设置errno值。
5)示例:(复制一个文件描述符,指定新的文件描述符为10)
#include
#include
#include
#include
#include
#include
int main()
{
int fd1, fd2;
fd1 = open("test", O_RDWR | O_CREAT | O_TRUNC, 0666);
if (fd1 < 0) {
printf("error: test openn");
return -1;
}
fd2 = dup2(fd1, 10);
if (fd2 < 0) {
printf("error: dup2n");
close(fd1);
return -1;
}
printf("fd1=%d,fd2=%dn", fd1, fd2);
close(fd1);
close(fd2);
return 0;
}
6)编译运行并查看测试结果
fd1=3,fd2=10