在 Linux 中设置 FD 标志

Setting FD flags in Linux

我的印象是 fcntl(fd, F_SETFD, flg )flg = fcntl(fd, F_GETFD, flg ) 可用于设置和获取文件描述符标志。

根据https://community.spiceworks.com/linux/man/2/fcntl,linux应该只支持部分fd标志的设置。很公平。但 从输出判断:

#define _GNU_SOURCE
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>

#define XSZ(x) (int)(sizeof(x)*2)
int main(int argc, char** argv){
    int fd, flg;
    if ( (fd = open("/dev/stdout", O_RDWR )) < 0){ perror("open"); return -errno; }

    //get
    if ( (flg = fcntl(fd, F_GETFD)) < 0 ){ perror("setfd"); return -errno; }
    printf("flg=0x%0*x\n", XSZ(flg), flg);

#define ADD_FLAG(FLG) \
    flg |= FLG;\
    printf("setting flg=0x%0*x\n", XSZ(flg), flg);\
    if ( (flg = fcntl(fd, F_SETFD, flg )) ){ perror("setfd"); return -errno; }\
    if ( (flg = fcntl(fd, F_GETFD, flg )) < 0 ){ perror("getfd"); return -errno; }\
    printf("flg=0x%0*x\n\n", XSZ(flg), flg);

    ADD_FLAG(FD_CLOEXEC);
    ADD_FLAG(O_APPEND);
    ADD_FLAG(O_DIRECT);
    ADD_FLAG(O_ASYNC);
    ADD_FLAG(O_NOATIME);

    return 0;
}

flg=0x00000000
setting flg=0x00000001
flg=0x00000001

setting flg=0x00000401
flg=0x00000001

setting flg=0x00004001
flg=0x00000001

setting flg=0x00002001
flg=0x00000001

setting flg=0x00040001
flg=0x00000001

看起来唯一可设置的标志是FD_CLOEXEC。 (奇怪的是:所有集合调用 return 成功 )。

在我看来,内核几乎忽略了 F_SETFD:

的参数

https://github.com/torvalds/linux/blob/master/fs/fcntl.c#L259

这是怎么回事?我错过了什么吗?

F_SETFD的唯一有效标志是FD_CLOEXEC;您使用的所有其他内容都用于 F_SETFL。 Linux 和 POSIX 都没有在 F_SETFD 传递任何不存在的标志值时指定任何错误,因此预计这种情况不会导致错误。