fcntl函数可以改变已打开文件的性质。函数原型如下:
#include <fcntl.h>
int fcntl(int filedes, int cmd, ...);
当第二个参数 cmd=F_DUPFD时,它的作用是根据 filedes复制一个新文件描述符。此时, fcntl相当于 dup和 dup2函数。
第三个参数指出新复制的文件描述符是一个等于或大于该参数的可用文件描述符,且不能等于一个已有的文件描述符。如果第三个参数等于一个已有文件描述符,则取一个大于该参数的一个可用描述符。
DUPFD:duplicate(复制)File(文件)Description(描述)
实例 x.3.14.1.c
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#define BUFFSIZE 256
int main()
{
char filepath[] = "/tmp/myfile"; /*待操作文件路径*/
int f_id1, f_id2, f_id3; /*文件描述符*/
char rbuf[BUFFSIZE]; /*数据缓冲区*/
ssize_t nread; /*实际读到的字节数*/
size_t nbytes; /*要读取的字节数*/
/*打开文件,获取文件描述符*/
f_id1 = open(filepath, O_RDONLY);
if (f_id1 == -1) {
printf("open error for %s\n", filepath);
return 0;
}
/*利用fcntl复制一个最小可用描述符*/
f_id2 = fcntl(f_id1, F_DUPFD, 0);
if (f_id2 < 0) {
printf("fcntl error for f_id2\n");
return 1;
}
printf("f_id2 = %d\n", f_id2);
/*复制一个大于或等于8的可用描述符*/
f_id3 = fcntl(f_id1, F_DUPFD, 8);
if (f_id3 < 0) {
printf("fcntl error for f_id3\n");
return 1;
}
printf("f_id3 = %d\n", f_id3);
/*通过描述符f_id2读取5字节数据*/
nbytes = 5;
nread = read(f_id2, rbuf, nbytes);
if (nread == -1) {
printf("read error for f_id2\n");
return 1;
}
nread = nread == 0 ? nbytes : nread;
rbuf[nread] = '\0';
printf("read by f_id2:%s\n", rbuf);
/*通过描述符f_id3读取5字节数据*/
nbytes = 5;
nread = read(f_id3, rbuf, nbytes);
if (nread == -1) {
printf("read error for f_id3\n");
return 1;
}
nread = nread == 0 ? nbytes : nread;
rbuf[nread] = '\0';
printf("read by f_id3:%s\n", rbuf);
close(f_id1);
close(f_id2);
close(f_id3);
return 0;
}
编译与执行:
[root@localhost unixc]# echo "0123456789" > /tmp/myfile
[root@localhost unixc]# cc x.3.14.1.c
[root@localhost unixc]# a.out
f_id2 = 4
f_id3 = 8
read by f_id2:01234
read by f_id3:56789
[root@localhost unixc]#
分析:
本例中分别两次调用fcntl函数复制新文件描述符,第一次指定的描述符(参数3)为0,因为0描述符已作为标准输入,所以函数自动用一个最小的可用描述符4作为新描述符返回。第二次调用fcntl给定的描述符为8,是一个可用描述符,所以函数直接返回8作为新文件描述符。