Linux应用编程之fcntl函数

fcntl() 函数可以对一个已经打开的文件描述符执行一系列控制操作,譬如复制一个文件描述符(与 dup 、 dup2 作用相同)、获取 / 设置文件描述符标志、获取 / 设置文件状态标志等,类似于一个多功能文件描述符管理工具箱。
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ )
fd 文件描述符。
cmd 操作命令。此参数表示我们将要对 fd 进行什么操作,cmd 操作命令大致可以分为以下 5 种功能:
复制文件描述符( cmd=F_DUPFD cmd=F_DUPFD_CLOEXEC );
获取 / 设置文件描述符标志( cmd=F_GETFD cmd=F_SETFD );
获取 / 设置文件状态标志( cmd=F_GETFL cmd=F_SETFL );
获取 / 设置异步 IO 所有权( cmd=F_GETOWN cmd=F_SETOWN );
获取 / 设置记录锁( cmd=F_GETLK cmd=F_SETLK);
fcntl 函数是一个可变参函数,第三个参数需要根据不同的 cmd 来传入对应的实参,配合 cmd 来使 用。
返回值: 执行失败情况下,返回 -1 ,并且会设置 errno ;执行成功的情况下,其返回值与 cmd (操作命 令)有关,譬如 cmd=F_DUPFD (复制文件描述符)将返回一个新的文件描述符、 cmd=F_GETFD (获取文 件描述符标志)将返回文件描述符标志、cmd=F_GETFL (获取文件状态标志)将返回文件状态标志等。
fcntl 使用示例

(1)复制文件描述符
cmd=F_DUPFD 时,它的作用会根据 fd 复制出一个新的文件描述符,此时需要传入第三个参数,第 三个参数用于指出新复制出的文件描述符是一个大于或等于该参数的可用文件描述符(没有使用的文件描 述符);如果第三个参数等于一个已经存在的文件描述符,则取一个大于该参数的可用文件描述符。

示例代码:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    int fd1, fd2;
    int ret;

    /* 打开文件 test_file */
    fd1 = open("./test_file", O_RDONLY);
    if (-1 == fd1)
    {
        perror("open error");
        exit(-1);
    }

    /* 使用 fcntl 函数复制一个文件描述符 */
    fd2 = fcntl(fd1, F_DUPFD, 100);
    if (-1 == fd2)
    {
        perror("fcntl error");
        ret = -1;
        goto err;
    }

    printf("fd1: %d\nfd2: %d\n", fd1, fd2);

    ret = 0;
    close(fd2);
err:
    /* 关闭文件 */
    close(fd1);
    exit(ret);
}
在当前目录下存在 test_file 文件,上述代码会打开此文件,得到文件描述符 fd1 ,之后再使用 fcntl 函数 复制 fd1 得到新的文件描述符 fd2 ,并将 fd1 fd2 打印出来。
编译测试:
可知复制得到的文件描述符是 7 ,因为在执行 fcntl 函数时,传入的第三个参数是 0,也就时指定复制得到的新文件描述符必须要大于或等于 100,那么 fd2 就会等于 100。

(2) 获取 /设置文件状态标志
 
cmd=F_GETFL 可用于获取文件状态标志, cmd=F_SETFL 可用于设置文件状态标志。 cmd=F_GETFL 时 不需要传入第三个参数,返回值成功表示获取到的文件状态标志;cmd=F_SETFL 时,需要传入第三个参数, 此参数表示需要设置的文件状态标志。
这些标志指的就是我们在调用 open 函数时传入的 flags 标志,可以指定一个或多个(通过位或 | 运算符组合),但是文件权限标志(O_RDONLY O_WRONLY O_RDWR )以及文件创建标志( O_CREAT 、 O_EXCL、 O_NOCTTY O_TRUNC )不能被设置、会被忽略;在 Linux 系统中,只有 O_APPEND O_ASYNC、O_DIRECT O_NOATIME 以及 O_NONBLOCK 这些标志可以被修改。
对于一个已经打开的文件描述符,可以通过这种方式添加或移除标志。
 
示例代码:fcntl 读取/设置文件状态标志
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    int fd;
    int ret;
    int flag;

    /* 打开文件 test_file */
    fd = open("./test_file", O_RDWR);
    if (-1 == fd)
    {
        perror("open error");
        exit(-1);
    }

    /* 获取文件状态标志 */
    flag = fcntl(fd, F_GETFL);
    if (-1 == flag)
    {
        perror("fcntl F_GETFL error");
        ret = -1;
        goto err;
    }

    printf("flags: 0x%x\n", flag);

    /* 设置文件状态标志,添加 O_APPEND 标志 */
    ret = fcntl(fd, F_SETFL, flag | O_APPEND);
    if (-1 == ret)
    {
        perror("fcntl F_SETFL error");
        goto err;
    }
    ret = 0;

err:
    /* 关闭文件 */
    close(fd);
    exit(ret);
}
上述代码会打开 test_file 文件,得到文件描述符 fd ,之后调用 fcntl(fd, F_GETFL) 来获取到当前文件状态标志 flag ,并将其打印来;接着调用 fcntl(fd, F_SETFL, flag | O_APPEND) 设置文件状态标志,在原标志的基础上添加 O_APPEND 标志。
编译测试:

 

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值