在Linux中设置FD标志

时间:2016-06-18 07:29:38

标签: c linux unix posix

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

根据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。 (奇怪的是:所有的设置调用都返回成功)。

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

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

这里发生了什么?我错过了什么吗?

1 个答案:

答案 0 :(得分:3)

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