fcntl()系统调用

来源:互联网 发布:软件系统开发评估 编辑:程序博客网 时间:2024/04/28 00:48

五一3天小长假,在家里悠闲度过了。基本没学习,昨天下午回到深圳,研究了一下fcntl()系统调用。

1. 函数介绍

函数fcntl()用于修改某个文件描述符的属性,函数原型为:

#include <unistd.h>#include <fcntl.h>int fcntl(int fd, int cmd, ... /* arg */ );

第1个参数fd为待修改属性的文件描述符,第2个参数cmd为对应的操作命令,第3个参数为cmd的参数。
常见的cmd命令有:

F_DUPFD     //复制文件描述符,跟dup()函数功能一样F_GETFD     //获取文件描述符标志F_SETFD     //设置文件描述符标志F_GETFL     //获取文件状态F_SETFL     //设置文件状态

函数执行失败,将返回-1并设置errno全局变量来指明错误。
不同的cmd其返回值不同: 若是设置文件属性,成功返回0失败返回-1;
若是读取文件属性,成功返回该属性值,失败返回-1。

2. 函数使用

2.1 F_DUPFD赋值文件描述符

fcntl()函数中cmd若使用F_DUPFD命令则是复制文件描述符,返回的值是新的文件描述符,该文件描述符同样指向原文件,具有特点有:
1) 大于或者等于指定的最小可用的文件描述符。”指定”是在函数的第三个参数指定的。
2) 和原文件相同方式的打开文件(包括管道)
3) 两个文件描述符共享一个文件指针
4) 两个文件描述符共享同一文件状态标志
5) 新的文件描述符关联的close-on-exec标志在各execX()函数簇中还是保持打开状态

int main(void){    const char* ptr = "Hello, funtl()\n";    int fd, new_fd;    fd = open("tmp.file", O_WRONLY | O_CREAT, 0666);    if (fd < 0)    {        perror("open");        exit(EXIT_FAILURE);    }    //赋值文件描述符,参数3设置为0,那么new_fd为3    new_fd = fcntl(fd, F_DUPFD, 0);    printf("fd = %d, new_fd = %d\n", fd, new_fd);    printf("write %d bytes to fd\n", write(fd, ptr, strlen(ptr)));    printf("write %d bytes to new_fd\n", write(new_fd, ptr, strlen(ptr)));    close(fd);    close(new_fd);    system("cat tmp.file");    return 0;}

运行结果:
这里写图片描述

2.2 F_GETFD / F_SETFD操作close-on-exec

首先了解close-on-exec是什么?每个文件描述符都有一个close-on-exec标志,这个标志的具体作用是体现在其它进程调用execX()函数簇时,是否关闭在这之前的文件描述符。F_GETFD命令获取文件描述符关联的close-on-exec标志。如果close-on-exec低序位为0,文件将在execX()函数执行期间保持打开状态,否则文件在执行execX()函数期间是关闭的。默认情况下是打开的,则允许在execX()函数簇代码中访问原来打开的文件描述符。
F_SETFL命令用于设置与文件描述符相关的close-on-exec标志,设置的值为fcntl的第3个参数。
若设置为1,即FD_CLOEXEC,

/* for F_[GET|SET]FL */#define FD_CLOEXEC  1   /* actually anything with low bit set goes */

那么子进程的execX()函数簇中不可以使用该文件描述符,代码示例在http://blog.csdn.net/qq_29344757/article/details/70316536#t13讲过。

2.3 F_GETFL / F_SETFD设置文件描述符状态

F_GETFL命令用于获取文件状态标志,F_SETFL将文件状态标志设置为funtl()的第3个参数。也就是说,它不能设置读写属性(O_RDWR、O_WRONLY、O_RDONLY),设置文件状态属性,如阻塞/非阻塞、追加(O_APPEND)。

/*    实验证明:    F_SETFD是设置文件的close-on-exec标志    F_SETFD是设置文件状态属性,如阻塞/非阻塞、追加(O_APPEND)*/int pre_test(int flag){    int accmode;    accmode = flag & O_ACCMODE;     //获取文件的读写属性需要这么操作    if (accmode == O_RDONLY)        printf("read only");    else if (accmode == O_WRONLY)        printf("write only");    else if (accmode == O_RDWR)        printf("read write");    else        printf("unknown mode");    if (flag & O_APPEND)        printf(", append");    if (flag & O_NONBLOCK)        printf(", nonblocking");    printf("\n");    return 0;}int main(int argc, char** argv){    int flag;    int fd;    fd = open("./tmp.file", O_RDONLY);    flag = fcntl(fd, F_GETFL);    if (flag < 0)    {        perror("fcntl");        exit(EXIT_FAILURE);    }    pre_test(flag);    fcntl(fd, F_SETFL, flag | O_NONBLOCK | O_APPEND);    flag = fcntl(fd, F_GETFL);    pre_test(flag);    return 0;}

运行结果:
这里写图片描述

F_SETFD和F_SETFL存在区别:
F_SETFD仅更改该文件描述符的信息,而F_SETFL则是更改与该文件相关的所有描述符。比如复制了某个文件描述符后,若使用F_SETFD修改close-on-exec标志,那么只是修改该文件描述符信息,若使用F_SETFL修改将修改原文件和拷贝文件描述符的状态信息。

水平有限,上述结论可能还有误,先总结这么多吧,

0 0
原创粉丝点击