Unix/Linux编程:fcntl函数总结

目录

  • 前言
  • [一、fcntl 函数基础篇](#一、fcntl 函数基础篇)
    • [1.1 fcntl 函数原型](#1.1 fcntl 函数原型)
    • [1.2 常见的用途](#1.2 常见的用途)
      • [1.2.1 获取和设置文件状态标志](#1.2.1 获取和设置文件状态标志)
      • [1.2.2 文件锁定](#1.2.2 文件锁定)
      • [1.2.3 更改文件描述符的属性](#1.2.3 更改文件描述符的属性)
    • [1.3 错误处理](#1.3 错误处理)
    • [1.4 示例代码](#1.4 示例代码)
  • [二、fcntl 函数深度篇](#二、fcntl 函数深度篇)
    • [2.1 复制文件描述符](#2.1 复制文件描述符)
      • [2.1.1 `F_DUPFD`](#2.1.1 F_DUPFD)
      • [2.1.2 `F_DUPFD_CLOEXEC`](#2.1.2 F_DUPFD_CLOEXEC)
      • [2.1.3 二者对比](#2.1.3 二者对比)
      • [2.1.4 `FD_CLOEXEC`标志的意义](#2.1.4 FD_CLOEXEC标志的意义)
    • [2.2 获取/设置文件描述符标志](#2.2 获取/设置文件描述符标志)
      • [2.2.1 `F_GETFD`](#2.2.1 F_GETFD)
      • [2.2.2 `F_SETFD`](#2.2.2 F_SETFD)
    • [2.3 获取/设置文件状态标志](#2.3 获取/设置文件状态标志)
      • [2.3.1 `F_GETFL`](#2.3.1 F_GETFL)
      • [2.3.2 `F_SETFL`](#2.3.2 F_SETFL)
    • [2.4 获取/设置记录锁](#2.4 获取/设置记录锁)
      • [2.4.1 `F_GETLK`](#2.4.1 F_GETLK)
      • [2.4.2 `F_SETLK`](#2.4.2 F_SETLK)
      • [2.4.3 `F_SETLKW`](#2.4.3 F_SETLKW)
      • [2.4.4 结构体 flock](#2.4.4 结构体 flock)
    • [2.5 获取/设置异步I/O所有权](#2.5 获取/设置异步I/O所有权)
      • [2.5.1 `F_SETOWN `](#2.5.1 F_SETOWN )
      • [2.5.2 `F_GETOWN`](#2.5.2 F_GETOWN)
    • [2.6 处理异步 I/O 操作时的信号通知](#2.6 处理异步 I/O 操作时的信号通知)
      • [2.6.1 `F_SETSIG`](#2.6.1 F_SETSIG)
      • [2.6.2 `F_GETSIG`](#2.6.2 F_GETSIG)
  • 三、参考链接

前言

fcntl 函数是一个在 UNIX 和类 UNIX 系统(如 Linux)上用来操作文件描述符的系统调用。它可以用于改变文件描述符的属性或状态,或者执行基本的控制操作。fcntl 函数非常强大且灵活,常用于实现各种文件和进程间通信的功能。

一、fcntl 函数基础篇

1.1 fcntl 函数原型

在 C 语言中,fcntl 的函数原型定义如下:

c 复制代码
#include <fcntl.h>  
#include <unistd.h>  

int fcntl(int fd, int cmd, ... /* arg */ );

参数说明:

  • fd: 文件描述符,指定要操作的文件或套接字的描述符。
  • cmd: 控制命令,指示要执行的操作类型。常见的命令包括:
  1. 复制一个现有的描述符:
    F_DUPFD :.复制文件描述符
    F_DUPFD_CLOEXEC:复制文件描述符,设置FD_CLOEXEC标志
  2. 获得/设置文件状态标记:
    F_GETFL: 获取文件描述符的当前状态标志。
    F_SETFL: 设置文件描述符的状态标志。
  3. 获得/设置文件描述符标记:
    F_GETFD: 获取文件描述符的内部标志。
    F_SETFD: 设置文件描述符的内部标志。
  4. 获得/设置异步I/O所有权:
    F_GETOWN:获得异步I/O所有权
    F_SETOWN:设置异步I/O所有权
  5. 获得/设置记录锁:
    F_GETLK: 获取文件锁定信息。
    F_SETLK: 设置文件锁定信息。
    F_SETLKW: 以阻塞方式设置文件锁定信息。
  • ... arg: 可选的参数,根据不同的 cmd 值提供额外的信息。例如,对于 F_SETFL 命令,可以传递新的状态标志。

  • 返回值

    成功时返回命令的结果,通常是状态标志或锁信息。

    失败时返回 -1,并设置 errno 以指示错误类型。


1.2 常见的用途

1.2.1 获取和设置文件状态标志

可以获取和修改文件描述符的标志,比如设置文件为非阻塞模式。

c 复制代码
int flags = fcntl(fd, F_GETFL);  
fcntl(fd, F_SETFL, flags | O_NONBLOCK);  // 将这个描述符设置为非阻塞模式

1.2.2 文件锁定

可用于实现文件锁定机制,防止多个进程同时写入同一文件。

c 复制代码
struct flock lock;  
lock.l_type = F_WRLCK;   // 请求写锁  
lock.l_whence = SEEK_SET; // 从文件开始处锁定  
lock.l_start = 0;        // 从文件开始位置  
lock.l_len = 0;          // 锁定整个文件  

fcntl(fd, F_SETLK, &lock); // 设置锁定

1.2.3 更改文件描述符的属性

可以动态更改文件描述符的功能,例如将其设置为异步I/O工作模式或实时信号。


1.3 错误处理

使用 fcntl 函数时,如果返回值为 -1,可以通过 errno 获取具体错误信息。常见的错误包括:

EBADF: 提供的文件描述符无效。

EINTR: 操作被信号中断。

EINVAL: 指定的命令无效或者参数不符合规范。


1.4 示例代码

以下是一个简单的使用 fcntl 函数的示例,演示如何将一个文件描述符设置为非阻塞模式:

c 复制代码
#include <stdio.h>  
#include <fcntl.h>  
#include <unistd.h>  

int main() {  
    int fd = open("example.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);  
    if (fd == -1) {  
        perror("open");  
        return 1;  
    }  

    // 获取当前的文件状态标志  
    int flags = fcntl(fd, F_GETFL);  
    if (flags == -1) {  
        perror("fcntl get");  
        return 1;  
    }  

    // 设置为非阻塞模式  
    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {  
        perror("fcntl set");  
        return 1;  
    }  

    // 关闭文件描述符  
    close(fd);  
    return 0;  
}

二、fcntl 函数深度篇

基础篇只是针对fcntl 函数做了一个简单的概括性描述,下面通过一些demo与讲解加深

对fcntl 函数功能的理解。

2.1 复制文件描述符

fcntl 函数中的 F_DUPFD 和 F_DUPFD_CLOEXEC 命令用于复制一个文件描述符(file descriptor),并为新描述符分配一个最小的非负整数值。这两个命令在处理文件描述符的管理时非常有用,尤其是在需要动态分配文件描述符的情况下。

2.1.1 F_DUPFD

  • 命令: F_DUPFD
  • 功能: 创建一个新的文件描述符,该描述符是现有文件描述符的副本。新的文件描述符将从指定的最小文件描述符值开始分配,使用大于或等于arg参数的编号最低的可用文件描述符。新描述符与旧 fd共享同一文件表项。但是,新描述符有它自己的一套文件描述符标志,其FD_CLOEXEC文件描述符标志被清除〈这表示该描述符在 exec 时仍保持打开状态)。
  • 用法:
c 复制代码
int fcntl(int fd, F_DUPFD, int n);

参数说明:

fd: 要复制的原始文件描述符。

n: 分配的新文件描述符的起始值。如果可用,新的文件描述符将返回一个大于或等于 n 的最小的文件描述符。

返回值:

如果成功,则返回新的文件描述符。

失败时返回 -1,并设置 errno。

2.1.2 F_DUPFD_CLOEXEC

  • 命令: F_DUPFD_CLOEXEC
  • 功能: 类似于 F_DUPFD,但在创建的新文件描述符上设置了 FD_CLOEXEC 标志。这意味着如果当前进程调用 exec 系列函数时,将自动关闭这个文件描述符。
  • 用法:
c 复制代码
int fcntl(int fd, F_DUPFD_CLOEXEC, int n);

参数说明:

fd: 要复制的原始文件描述符。

n: 分配的新文件描述符的起始值。

返回值:

如果成功,则返回新的文件描述符。

失败时返回 -1,并设置 errno。

2.1.3 二者对比

dupF_DUPFD 都不会保留 FD_CLOEXEC 标志;

使用 F_DUPFD_CLOEXEC 会将新描述符的 FD_CLOEXEC 标志设置为 1。

fcntl(fd, F_GETFD, 0) 获取的标志用于查询指定文件描述符的状态,包括 FD_CLOEXEC。如果该标志被设置,返回值为 1。如果没有设置,返回值为 0。

下面通过一个demo理解二者的区别。

c 复制代码
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main()
{
	//fd 设置标记 fcntlFd 不设置 fcntlCloFd 设置 dupFd 不设置
	int fd = open("./fcntl_F_DUPFD_CLOEXEC", O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0775);
	int fcntlFd = fcntl(fd, F_DUPFD, 0);
	int fcntlCloFd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
	int dupFd = dup(fd);
	
	//通过fcntl(fd, F_GETFD, 0);获取状态标记
	int fdFlag = fcntl(fd, F_GETFD, 0);
	int fcntlFdFlag = fcntl(fcntlFd, F_GETFD, 0);
	int fcntlCloFdFlag = fcntl(fcntlCloFd, F_GETFD, 0);
	int dupFdFlag = fcntl(dupFd, F_GETFD, 0);
	
	// 结果是:fdFlag=1, fcntlFdFlag=0, fcntlCloFdFlag=1, dupFdFlag=0
	printf("fdFlag=%d, fcntlFdFlag=%d, fcntlCloFdFlag=%d, dupFdFlag=%d\n",
		fdFlag,fcntlFdFlag,fcntlCloFdFlag,dupFdFlag);
	
	close(fd);
	close(fcntlFd);
	close(fcntlCloFd);
	close(dupFd);
	return 0;
}

2.1.4 FD_CLOEXEC标志的意义

文件描述符标志FD_CLOEXEC。用来表示该描述符在执行完fork+exec系列函数创建子进程时会自动关闭,以防止它们被传递给子进程。为什么要这样做呢?

因为当一个进程调用exec系列函数(比如execve)来创建子进程时,所有打开的文件描述符都会被传递给子进程。如果文件描述符没有设置FD_CLOEXEC标志,这些文件将保持打开状态并继续对子进程可见。这可能导致潜在的安全风险或者意外行为。


2.2 获取/设置文件描述符标志

fcntl 函数中的 F_GETFD 和 F_SETFD 命令用于获取和设置文件描述符的标志,这在操作文件描述符的行为时非常重要。

2.2.1 F_GETFD

  • 功能: 获取指定文件描述符的标志。
  • 用法:
c 复制代码
int fcntl(int fd, F_GETFD);
  • 参数说明:
    fd: 要查询状态的文件描述符。
  • 返回值:
    返回文件描述符的标志,如果失败则返回 -1,并设置 errno。主要的标志包括:
    FD_CLOEXEC: 文件描述符在 exec 系列调用时会被关闭。如果该标志被设置,返回值包含该标志。
  • 常见的标志值:
    如果返回值与 FD_CLOEXEC 持平,表示标志已设置;如果返回值包含 0,表示没有设置。

2.2.2 F_SETFD

功能: 设置指定文件描述符的标志。

用法:

c 复制代码
int fcntl(int fd, F_SETFD, int flags);
  • 参数说明:
    fd: 要设置状态的文件描述符。
    flags: 新的状态标志,可以是以下值之一,或者是它们的组合:
    FD_CLOEXEC: 设置该标志,表示在调用 exec 系列函数时关闭文件描述符。
  • 返回值:
    如果成功,返回 0。失败时返回 -1,并设置 errno。

文件描述符的FD_CLOEXEC标志可以通过三个方法得到:

1、调用open函数是,指定 O_CLOEXEC

2、通过fcntl函数使用F_DUPFD_CLOEXEC复制文件描述符,新的描述符就是FD_CLOEXEC

3、通过fcntl函数使用F_SETFD直接设置FD_CLOEXEC。


2.3 获取/设置文件状态标志

fcntl 函数中的 F_GETFLF_SETFL 命令用于获取和设置文件的状态标志,这些标志控制文件的行为和特性。

文件状态标志如下表:

文件状态标志 说明 十六进制值
O_RDONLY 只读打开 0x0
O_WRONLY 只写打开 0x1
O_RDWR 读、写打开 0x2
O_APPEND 追加写 0x400
O_NONBLOCK 非阻塞模式 0x800
O_SYNC 等待写完成(数据和属性)
O_DSYNC 等待写完成(仅数据)
O_RSYNC 同步读和写
O_FSYNC 等待写完成
O_ASYNC 异步IO 0x2000

2.3.1 F_GETFL

  • 功能: 获取指定文件描述符的状态标志。
  • 用法:
c 复制代码
#include <fcntl.h>  

int fcntl(int fd, F_GETFL);
  • 参数说明:
    fd: 要查询状态的文件描述符。
  • 返回值:
    返回文件描述符的状态标志。如果成功,则是一个标志位的位掩码,失败时返回 -1,并设置 errno。
    访问方式标志:O_RDONLY 、O_WRONLY、O_RDWR。这3个值是互斥的,因此首先必须用屏蔽O_ACCMODE取得访问方式位,然后将结果与这3个值中的每一个相比较。
  • 常见的状态标志:

O_RDONLY: 只读模式。

O_WRONLY: 只写模式。

O_RDWR: 读写模式。

O_APPEND: 写操作时将偏移量移到文件末尾。

O_NONBLOCK: 以非阻塞模式操作。

O_CLOEXEC: 文件描述符在执行 exec 系列函数时会关闭。

2.3.2 F_SETFL

  • 功能: 设置指定文件描述符的状态标志。
  • 用法:
c 复制代码
#include <fcntl.h>  

int fcntl(int fd, F_SETFL, int flags);
  • 参数说明:
    fd: 要设置状态的文件描述符。
    flags: 新的状态标志,可以是以下值之一,或者是它们的组合。常用的标志包括:
    O_APPEND
    O_NONBLOCK
    其他任何适用的标志(例如 O_RDONLY、O_WRONLY 等)。
  • 返回值:
    如果成功,返回 0。失败时返回 -1,并设置 errno。

在Linux上,只能设置这5个文件状态标志:O_APPEND、 O_ASYNC、 O_DIRECT、 O_NOATIME、O_NONBLOCK,其中最常用的是将文件描述符设置成非阻塞(O_NONBLOCK),特别是在网络编程中很常见。


2.4 获取/设置记录锁

在 Unix 和类 Unix 系统中,fcntl 函数提供了用于记录锁(record locks)的功能,通过命令 F_GETLKF_SETLKF_SETLKW 来实现。这些命令用于获取、设置和管理文件的记录锁,帮助实现进程间的同步。

Linux实现了POSIX标准化的传统("进程相关")UNIX记录锁。

记录锁(record locking)的功能是:当一个进程正在读或修改文件的某个部分时,它可以阻止其他进程修改同一文件区。对于UNIX系统而言,"记录"这个词是一种误用,因为UNIX系统内核根本没有使用文件记录这种概念。更适合的术语可能是字节范围锁(byte-rangelocking),因为它锁定的只是文件中的一个区域(也可能是整个文件)。

F_SETLK、F_SETLKW和F_GETLK用于获取、释放和测试记录锁(也称为字节范围、文件段或文件区域锁)的存在。使用记录锁时,第三个参数是指向struct flock结构的指针。

2.4.1 F_GETLK

  • 功能: 获取文件的锁的状态。
  • 用法:
c 复制代码
#include <fcntl.h>  
#include <unistd.h>  

struct flock lock;  
lock.l_type = F_RDLCK;  // 读取锁或写入锁的类型  
lock.l_whence = SEEK_SET; // 锁的起始位置  
lock.l_start = 0; // 从文件的开始位置锁定  
lock.l_len = 0; // 锁定整个文件  

int result = fcntl(fd, F_GETLK, &lock); // fd 是文件描述符
  • 参数说明:
    fd: 要获取锁状态的文件描述符。
    &lock: 指向 flock 结构的指针,该结构包含了锁的信息。
  • 返回值:
    返回 0 表示成功,若出现错误则返回 -1,并设置 errno。
    在成功时,可以通过检查 lock.l_type 来确定锁的状态。如果 l_type 被设置为 F_UNLCK,则表示没有其他进程持有该锁。如果是 F_RDLCK 或 F_WRLCK,则表示相应的锁已经被其他进程持有。

2.4.2 F_SETLK

  • 功能: 设置文件的锁。如果锁失败,不会阻塞。
  • 用法:
c 复制代码
struct flock lock;  
// 设置锁的信息  
lock.l_type = F_WRLCK; // 写入锁  
lock.l_whence = SEEK_SET;  
lock.l_start = 0;  
lock.l_len = 0; // 锁定整个文件  

int result = fcntl(fd, F_SETLK, &lock); // 尝试设置锁
  • 参数说明:
    &lock: 指向 flock 结构的指针,定义需要设置的锁的类型和范围。
  • 返回值:
    返回 0 表示成功,若无法锁定则返回 -1,并设置 errno。
    当返回 -1 时,常见的 errno 值为 EACCES 或 EAGAIN,表示锁已被其他进程持有。

2.4.3 F_SETLKW

功能: 设置文件的锁,和 F_SETLK 类似,但如果锁失败则阻塞直到成功。

用法:

c 复制代码
struct flock lock;  
// 设置锁的信息  
lock.l_type = F_WRLCK; // 写入锁  
lock.l_whence = SEEK_SET;  
lock.l_start = 0;  
lock.l_len = 0; // 锁定整个文件  

int result = fcntl(fd, F_SETLKW, &lock); // 阻塞直到成功
  • 参数说明:
    同样使用 &lock,配置结构。
  • 返回值:
    同样返回 0 表示成功且锁定成功。若发生错误返回 -1,并设置 errno。成功是阻塞等待获得锁。

2.4.4 结构体 flock

在以上命令中,使用的 flock 结构体定义如下:

c 复制代码
struct flock {  
    short l_type;   // 锁的类型:F_RDLCK, F_WRLCK 或 F_UNLCK  
    short l_whence; // 锁偏移基准(SEEK_SET,SEEK_CUR,SEEK_END)决定l_start位置*
    off_t l_start;  // 从文件的哪个位置开始  锁定区域的开头位置
    off_t l_len;    // 锁定的字节数, 0 表示锁定到文件的末尾  锁定区域的大小
    pid_t l_pid;    // 锁的拥有者的进程 ID  
};

l_whencel_startl_len这三个参数用于分段对文件加锁,若对整个文件加锁,则:l_whence= SEEK_SET,l_start= 0,l_len= 0;
l_type 有三种状态 :

  • F_RDLCK 建立一个供读取用的锁定,允许其他进程读该文件,但不允许其他进程写该文件;

  • F_WRLCK 建立一个供写入用的锁定,不允许其他进程读、写该文件;

  • F_UNLCK 删除之前建立的锁定
    l_whence 也有三种方式:

  • SEEK_SET 以文件开头为锁定的起始位置。

  • SEEK_CUR 以目前文件读写位置为锁定的起始位置

  • SEEK_END 以文件结尾为锁定的起始位置。

c 复制代码
#include "filelock.h"

/* 设置一把读锁 */
int readLock(int fd, short start, short whence, short len)
{
    struct flock lock;
    lock.l_type = F_RDLCK;
    lock.l_start = start;
    lock.l_whence = whence;//SEEK_CUR,SEEK_SET,SEEK_END
    lock.l_len = len;
    lock.l_pid = getpid();
//  阻塞方式加锁
    if(fcntl(fd, F_SETLKW, &lock) == 0)
        return 1;

    return 0;
}

/* 设置一把读锁 , 不等待 */
int readLocknw(int fd, short start, short whence, short len)
{
    struct flock lock;
    lock.l_type = F_RDLCK;
    lock.l_start = start;
    lock.l_whence = whence;//SEEK_CUR,SEEK_SET,SEEK_END
    lock.l_len = len;
    lock.l_pid = getpid();
//  非阻塞方式加锁
    if(fcntl(fd, F_SETLK, &lock) == 0)
        return 1;

    return 0;
}
/* 设置一把写锁 */
int writeLock(int fd, short start, short whence, short len)
{
    struct flock lock;
    lock.l_type = F_WRLCK;
    lock.l_start = start;
    lock.l_whence = whence;
    lock.l_len = len;
    lock.l_pid = getpid();

    //阻塞方式加锁
    if(fcntl(fd, F_SETLKW, &lock) == 0)
        return 1;

    return 0;
}

/* 设置一把写锁 */
int writeLocknw(int fd, short start, short whence, short len)
{
    struct flock lock;
    lock.l_type = F_WRLCK;
    lock.l_start = start;
    lock.l_whence = whence;
    lock.l_len = len;
    lock.l_pid = getpid();

    //非阻塞方式加锁
    if(fcntl(fd, F_SETLK, &lock) == 0)
        return 1;

    return 0;
}

/* 解锁 */
int unlock(int fd, short start, short whence, short len)
{
    struct flock lock;
    lock.l_type = F_UNLCK;
    lock.l_start = start;
    lock.l_whence = whence;
    lock.l_len = len;
    lock.l_pid = getpid();

    if(fcntl(fd, F_SETLKW, &lock) == 0)
        return 1;

    return 0;
}

2.5 获取/设置异步I/O所有权

F_GETOWNF_SETOWN是与文件描述符相关的控制命令,它们用于获取和设置与文件描述符关联的异步 I/O 所属的进程或进程组。这两个命令主要在 POSIX 标准中使用,尤其是在 Unix 或 Linux 系统中。

这两个命令主要用于异步 I/O 功能,特别是在信号处理和进程间通信中。常见的使用情况包括:

  • 信号通知: 当异步 I/O 操作完成,内核会向设置的进程或进程组发送信号。这允许应用程序实现更灵活的 I/O 处理机制。
  • 进程管理: 当需要通过文件描述符进行进程间通信时,F_SETOWN 可以指定接收事件的进程,F_GETOWN 获取当前设置的所有者。

2.5.1 F_SETOWN

  • 定义: F_SETOWN 是一个用于设置文件描述符的拥有者的命令。您可以指定一个进程 ID 或进程组 ID,使其成为文件描述符事件的接收者。(设定 SIGIO和 SIGURG 信号的宿主进程的 PID或进程组的组ID。)

  • 用法: 同样与 fcntl 函数配合使用,例如:

c 复制代码
fcntl(fd, F_SETOWN, owner);

其中 owner 是要设置为新的 PID 或 PGID 的值。

  • 参数:
    参数 owner 普通进程的 PID 时,设置为该进程作为文件描述符的信号接收者。
    参数为 0 时,将信号发送给与该文件描述符关联的进程组。
    如果 owner 是负数(如 -group_id),则它会成为该组的所有进程的接收者。

2.5.2 F_GETOWN

  • 定义: F_GETOWN 是一个用于获取文件描述符的拥有者的命令。它返回与文件描述符关联的信号接收者的 PID(进程 ID)或 PGID(进程组 ID)。 (获得 SIGIO和 SIGURG 信号的宿主进程的 PID或进程组的组ID。)
  • 用法: 通常与 fcntl 函数一起使用,例如:
c 复制代码
int owner = fcntl(fd, F_GETOWN);

其中 fd 是文件描述符。

  • 返回值:
    如果返回值大于 0,表示它是一个 PID,意味着普通进程在等待该文件描述符的事件。
    如果返回值为 0,表示它是一个进程组 ID,表示该进程组的任何一个进程可以接收信号。
    如果返回 -1,表示调用失败,您可以通过 errno 获取错误信息。

SIGIOSIGURG这两个信号与其他Linux信号不同,它们必须和某个文件描述符相关联方可使用:

当被关联的文件描述符可读或者可写时,系统将触发SIGIO信号

当被关联的文件描述符(必须是一个socket)上有带外数据可读时,系统将触发SIGURG信号

将信号和文件描述符关联的方法,就是使用fcntl函数为目标文件描述符指定宿主进程或者进程组,那么被指定的宿主进程或者进程组将会捕获这两个信号

使用SIGIO时,还需要利用fcntl设置其O_ASYNC标志(异步IO标志)


2.6 处理异步 I/O 操作时的信号通知

F_SETSIGF_GETSIG 是在 Unix 和 Linux 系统中与文件描述符相关的一组控制命令,通常用于处理异步 I/O 操作时的信号通知。这些命令也是通过 fcntl 系统调用实现的,主要用于管理进程和文件描述符之间的信号机制。

这两个命令主要用于管理异步 I/O 操作,特别是在需要在 I/O 操作完成时通知进程进行处理时。常见的使用情况包括:

  • 文件描述符的信号通知: 可以为某个非阻塞的文件描述符设置信号,以便在该文件描述符可以进行读写操作时,进程能够接收到相应的信号处理逻辑。

  • 提高事件响应能力: 使用这些命令,应用程序可以异步地响应文件描述符的状态变化,而不需要使用轮询来检查可读性或可写性。

2.6.1 F_SETSIG

  • 定义: F_SETSIG 命令用于设置与文件描述符关联的信号。当文件描述符准备好 I/O 操作(如可以读取或写入)时,内核将发送指定的信号给拥有该文件描述符的进程。

  • 用法: 与 fcntl 函数一起使用,例如:

c 复制代码
fcntl(fd, F_SETSIG, SIGUSR1);
  • 参数:
    提供给 F_SETSIG 的参数是一个信号值,可以是任何有效信号(例如 SIGIO、SIGUSR1 等)。
    当文件描述符状态变化时,内核将发送此信号给拥有该文件描述符的进程。

2.6.2 F_GETSIG

  • 定义: F_GETSIG 命令用于获取与文件描述符关联的当前信号值。
  • 用法: 也通过 fcntl 函数使用,例如:
c 复制代码
int sig = fcntl(fd, F_GETSIG);

这将返回与文件描述符 fd 相关联的当前信号值。

返回值: 返回的信号值表示当前为文件描述符设置的信号。如果没有为该文件描述符设置信号,可能返回无效信号(如 0)。如果调用失败,将返回 -1,并可以通过 errno 获取错误信息。


fcntl函数支持的常用操作以其参数如表所示:

fd对应的文件状态标志:


三、参考链接

Unix/Linux编程:fcntl函数总结
Linux fcntl函数详解

相关推荐
FoldWinCard6 小时前
D5 Linux 网络及端口命令
linux·运维·服务器
零涂毕业设计7 小时前
毕业设计模块开发-OLED显示屏(IIC协议0.96寸)STM32 ESP32 FPGA Linux驱动免费分享
linux·stm32·单片机·嵌入式·esp32·fpga·oled
tedcloud1237 小时前
OmniRoute怎么部署?开源AI模型路由平台Linux部署教程
linux·服务器·人工智能·开源·音视频
霸道流氓气质7 小时前
KMS 密钥管理服务(Key Management Service)原理与实践
linux·服务器·数据库
SakitamaX8 小时前
LVS(Linux Virtual Server)概念详解
linux·运维·lvs
小张同学a.8 小时前
Linux系统管理
linux·运维
阿龙的工作记录8 小时前
深入理解Linux设备驱动模型
linux·嵌入式硬件·工作记录
代码村新手9 小时前
Linux的基本指令
linux·运维·服务器
hkj88089 小时前
Ubuntu 切换java版本
java·linux·ubuntu
撩得Android一次心动11 小时前
Linux编程笔记3【个人用】
linux·笔记