dup2函数用于复制一个现存的文件描述符,函数原型如下:
#include <unistd.h>
int dup2(int filedes, int filedes2);
返回值:若复制成功则返回新文件描述符,若出错则返回-1。
参数:
1、filedes现存的文件描述符。
2、filedes2指定的要生成的新文件描述符。
说明:
1、若filedes2是一个已存在的文件描述符,filedes2会先被关闭再根据filedes复制一个新文件描述符;
2、若filedes与filedes2相等,filedes不会被关闭,而是直接返回。
3、与dup函数一样,dup2函数复制出来的新文件描述符filedes2与原文件描述符filedes共享一个文件表项。
4、dup2函数与dup函数的不同是:dup根据当前可用文件描述符中的最小值复制新文件描述符,dup2则可以任意指定一个文件描述符。
实例 x.3.12.2.c
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#define BUFFSIZE 256
int main(void)
{
char filepath[] = "/tmp/myfile"; /*待操作文件路径*/
int f_id1, f_id2; /*文件描述符*/
ssize_t nwrite; /*实际写入字节书*/
size_t nbytes; /*要写入的字节书*/
off_t offset; /*文件指针偏移量*/
char buf[BUFFSIZE] = "0123456789"; /*待写入数据*/
/*打开文件,获取文件描述符*/
f_id1 = open(filepath, O_RDWR | O_CREAT);
if (f_id1 == -1) {
printf("open error for %s\n", filepath);
return 1;
}
f_id2 = dup2(f_id1, 8); /*复制文件描述符,指定的文件描述符为8*/
if (f_id2 == -1) {
printf("dup error for f_id2\n");
return 2;
}
printf("f_id1:%d\n", f_id1);
printf("f_id2:%d\n", f_id2);
/*把文件指针移动到文件开始处*/
offset = lseek(f_id1, 0, SEEK_SET);
if (offset == -1) {
printf("lseek error for %s\n", filepath);
return 3;
}
/*通过文件描述符f_id1写入3字节数据[0-2]*/
nbytes = 3;
nwrite = write(f_id1, buf, nbytes);
if (nwrite == -1) {
printf("write error for f_id1(%d)\n", f_id1);
return 4;
}
/*通过文件描述符f_id2写入7字节数据[3-9]*/
nbytes = 7;
nwrite = write(f_id2, (buf + 3), nbytes);
if (nwrite == -1) {
printf("write error for f_id2(%d)\n", f_id2);
return 5;
}
close(f_id1);
close(f_id2);
}
编译与执行:
[root@localhost unixc]# rm -f /tmp/myfile
[root@localhost unixc]# cc x.3.12.2.c
[root@localhost unixc]# ./a.out
f_id1:3
f_id2:8
[root@localhost unixc]# cat /tmp/myfile
0123456789[root@localhost unixc]#
分析:
1、复制出来的新文件描述符f_id2为指定值8;
2、新复制出来的文件描述符f_id2与被复制的文件描述符f_id1共享一个文件表项:代码中第二次写操作是通过文件描述符f_id2来执行,并且没有调用lseek重新定位,但第二次写入并不覆盖第一次写入。