3.3Apue文件IO——fcntl函数及其使用示例

为什么要使用fcntl函数

假设我们已经打开了一个文件,那么当我想修改已打开文件的属性时,就可以利用fcntl函数直接改变已打开文件的属性,而不用关闭然后重新打开来设置

fcntl函数

原型:
在这里插入图片描述
当第二个参数取不同的值时,fcntl有不同的功能:
cmd=F_DUPFD或F_DUPFD_CLOEXEC复制一个已有的描述符,返回新的文件描述符
cmd=F_GETFD或F_SETFD:获取/设置文件描述符标志
cmd=F_GETFL或F_SETFL:获取文件状态标志(如O_RDONLY、O_WRONLY、O_RDWR等,这三个值互斥一个文件的访问方式只能取这几个值之一,因此需要用屏蔽字O_ACCMODE取得访问方式位,然后与这几个值比较)。设置文件状态时将文件状态标志设置为第三个参数的值(可更改的几个标志O_APPENDO_NONBLOCK等)
cmd=F_GETOWN或F_SETOWN:获取/设置异步IO所有权:即获取当前接收SIGIO和SIGURG信号的进程ID或进程组ID。设置接收SIGIO和SIGURG信号的进程ID或进程组ID
cmd=F_GETLCK或F_SETLK或F_SETLKW:获取/设置记录锁

fcntl使用示例

示例1:获取文件hello的状态标志
在这里插入图片描述

/// for read()
#include <unistd.h>

/// for open()
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

/// for exit()
#include <stdlib.h>

#define BUFFERSIZE 1024

int main(int argc, char *argv[]) {

    int ret;

    int fd = atoi(argv[1]);

    if ((ret = fcntl(fd, F_GETFL)) < 0) {
        perror("fcntl() error!");
        exit(1);
    }

    switch (ret & O_ACCMODE) {
        case O_RDONLY:
            puts("O_RDONLY");break;
        case O_WRONLY:
            puts("O_WRONLY");break;
        case O_RDWR:
            puts("O_RDWR");break;
        default:
            break;
    }

    if(ret & O_APPEND)
        puts("O_APPEND");
    if(ret & O_NONBLOCK)
        puts("O_NONBLOCK");
    if(ret & O_TRUNC)
        puts("O_TRUNC");

    return 0;
}

示例2:修改状态标志的正确方式
首先要获得现在的标志值,然后按照期望修改它,最后才是设置新的标志值
如果只是执行F_SETFD或F_SETFL,这样会关闭以前的标志位
示例中的ret |= flags用于设置flags标志
如果是ret &= ~flags则用于取消flags标志

void set_fl(int fd, int flgs) {
    int ret;
    if ((ret = fcntl(fd, F_GETFL)) < 0)
        perror("fcntl() error!");
    
    ret |= flags;   /// turn on flags
    
    if (fcntl(fd, F_SETFL, ret) < 0)
        perror("fcntl() error!");
}

猜你喜欢

转载自blog.csdn.net/CSDN_dzh/article/details/85060387