如何获得文件描述符的模式? [英] How to get the mode of a file descriptor?

查看:125
本文介绍了如何获得文件描述符的模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的意思是使用fdopen

FILE *fdopen(int fd, const char *mode);

手册页中,值"r","r +","w","w +","a","a +"之一必须与文件描述符的模式兼容." 因此,我必须首先知道fd的模式(我猜是int),才能为流选择合适的const char *mode.

In man pages, it is stated that "The mode of the stream (one of the values "r", "r+", "w", "w+", "a", "a+") must be compatible with the mode of the file descriptor." So I have to first know the mode of fd (which I guess is an int) to choose an appropriate const char *mode for the stream.

我知道我应该使用fcntl

int fcntl(int fd, int cmd);

操纵文件描述符"(在下面,我引自此官方消息). 它可以在以下平台上运行:

to "manipulate file descriptor" (in the following, I quote from this official source). It can operate on:

文件描述符标志

以下命令操纵与文件关联的标志 描述符.
...

The following commands manipulate the flags associated with a file descriptor.
...

文件状态标志

每个打开的文件描述都有某些关联的状态标志, 由open(2)初始化...

Each open file description has certain associated status flags, initialized by open(2)...

(我不知道两者之间的区别. 鉴于fcntl完全是指文件描述符,我想第二个标题应该是文件描述符状态标志",因此,我们将有标志"和状态标志"……让我感到困惑.我还没有看到任何规范).我在这里通过提及这一点,是针对此提出一个具体问题.

(I wouldn't know the difference between the two. Given that fcntl refers entirely to file descriptors, I guess the second title should be "File descriptor status flags", and thus we would have "flags" and "status flags"... confusing to me. I haven't seen any specification of this). I mention this in passing here, I am putting together a specific question on this.

从描述中,我想我应该选择后者. 在这种情况下,当cmd=F_GETFL时,返回值为文件访问模式和文件状态标志". 文件状态标志及其语义在 open(2)".

From the description, I guess I should go for the latter. In this case, when cmd=F_GETFL, the return value is "the file access mode and the file status flags". "The file status flags and their semantics are described in open(2)".

现在,在阅读引用的资料后,我无法理解

Now I couldn't make sense of, after reading the sources cited:

  1. fd的所有可能模式(int s)

因此,什么是兼容"的所有组合模式(fd)<->模式(流).

Consequently, what are all combinations mode(fd) <-> mode(stream) that are "compatible".

我想一个人应该可以将两个列表放在一起并用箭头连接.

I guess one should be able to put together two list and join with arrows.

相关:

可以获取`FILE *的访问模式吗? `?

文件描述符的规范(我问了这个问题)

如何捕获文件模式?

我想知道内部struct FILE的成员,最新的成员

如何理解O_RDONLY = 0? (我问了这个问题)

How to make sense of O_RDONLY = 0? (I asked this)

https://www.gnu.org/software/libc/manual/html_node/Access-Modes.html

https://www.gnu.org/software/libc/manual/html_node/File-Status-Flags.html#File-Status-Flags

推荐答案

从答案和评论中学到之后,请在此处和 words "的以下信息(我不想使用术语" flags ",请参见下面的注释,摘自此评论)并打开 mode s.

After learning from answers and comments, here and in How to make sense of O_RDONLY = 0?, I put together code below. From there, I obtained the following info about file descriptor status "words" (I wouldn't like to use the term "flags", see Note below, taken from this comment) and file opening modes.

*** Flag                       O_RDONLY =     0 =            0 = x0000
*** Flag                       O_WRONLY =     1 =            1 = x0001
*** Flag                         O_RDWR =     2 =           10 = x0002
*** Flag                        O_CREAT =    64 =      1000000 = x0040
*** Flag                        O_TRUNC =   512 =   1000000000 = x0200
*** Flag                       O_APPEND =  1024 =  10000000000 = x0400
*** Flag   O_WRONLY | O_CREAT | O_TRUNC =   577 =   1001000001 = x0241
*** Flag  O_WRONLY | O_CREAT | O_APPEND =  1089 =  10001000001 = x0441
*** Flag     O_RDWR | O_CREAT | O_TRUNC =   578 =   1001000010 = x0242
*** Flag    O_RDWR | O_CREAT | O_APPEND =  1090 =  10001000010 = x0442
*** Mode  r  F_GETFL -> 32768 = 1000000000000000 = x8000
*** Mode  w  F_GETFL -> 32769 = 1000000000000001 = x8001
*** Mode  a  F_GETFL -> 33793 = 1000010000000001 = x8401
*** Mode r+  F_GETFL -> 32770 = 1000000000000010 = x8002
*** Mode w+  F_GETFL -> 32770 = 1000000000000010 = x8002
*** Mode a+  F_GETFL -> 33794 = 1000010000000010 = x8402

三列中的数字为十进制,二进制和十六进制. 寻找奇怪"的x8000,我在fcntl-linux.h

Numbers in the three columns are in decimal, binary and hex. Looking for the "strange" x8000, I found in fcntl-linux.h

# ifdef __USE_GNU
...
#  define AT_RECURSIVE      0x8000  /* Apply to the entire subtree.  */
...
# endif

因此,除了在所有模式中都存在的 flag 之外,关联将是

So, except for that flag, present in all modes, the association would be

r   <->  O_RDONLY
w   <->  O_WRONLY
a   <->  O_WRONLY | O_APPEND
r+  <->  O_RDWR
w+  <->  O_RDWR
a+  <->  O_RDWR | O_APPEND

现在,这为我提供了两个有趣的发现:

Now this provides a couple of intriguing findings to me:

  1. 此列表与 Tony Tannous给出的表不一致.

r+单词w+相同. 这给编码人员带来了挑战,即当单词为O_RDWR时(r+w+都可以)与fdopen一起使用哪种模式. 根据,我希望w+也具有O_CREAT(如上表所示). 我也希望w有它.

The word for r+ is the same as for w+. This provides a challenge for the coder, as to which mode to use with fdopen when the word is O_RDWR (both r+ and w+ would be ok). As per this, I expected w+ to have also O_CREAT (as in the table mentioned above). I also expected w to have it.

要编写完全可移植的代码,似乎每当使用fdopen时,都必须像我写的那样编写代码以自动找到连接 mode <-> word . (实际上,我所做的部分工作是手动识别,还需要进一步的代码).

To write completely portable code, it seems that whenever using fdopen one has to write code as I wrote to automatically find the connection mode <-> word. (actually, part of the work I did was a manual identification, and further code is needed).

编辑: 根据注释对点1和2的解释是,该表显示了fopen模式和open标志之间的匹配,即在创建过程中. 但是我用fcntl获得的是创建 之后持久保留的标志,而不是创建 期间使用的标志. 也如此处所述,O_CREATO_TRUNC属于文件创建标志,因此不是持久的. 另一方面,O_APPEND属于类别文件状态标志,并且是持久性的. 这两组标志之间的区别是文件创建标志影响打开操作本身的语义,而文件状态标志影响随后的I/哦,行动." [参考]

EDIT: The explanation for points 1 and 2 as per comments is that the table shows the match between fopen modes and open flags, i.e., during creation. But what I obtained with fcntl is the flags persistent after creation, not those used during creation. As also explained here, O_CREAT and O_TRUNC belong to the category of File creation flags and thus are not persistent. On the other hand, O_APPEND belongs to the category File status flags and is persistent. "The distinction between these two groups of flags is that the file creation flags affect the semantics of the open operation itself, while the file status flags affect the semantics of subsequent I/O operations." [ref]

注意: open(2)的手册页首先描述了该文件访问模式,然后添加此外,可以按位或在标志中添加零个或多个文件创建标志和文件状态标志...."但是(正确地)没有提到可以按位操作文件访问模式在.对我而言,标志"一词绝对是错误的称呼,并且具有误导性.

Note: The man page for open(2) first describes the file access modes, and then adds "In addition, zero or more file creation flags and file status flags can be bitwise-or'd in flags...." But it (correctly) does not mention that file access mode can be bitwise operated on. For me, the word "flag" is an absolute misnomer, and misleading.


代码(可以使用任何获取二进制格式的函数to_binary):


Code (any function to_binary to get the binary form can be used):

int main() {
    const char fname[100] = "test.txt";
    const char modes[][4] = { "r", "w", "a", "r+", "w+", "a+" };
    const size_t nmodes = sizeof(modes) / sizeof(modes[0]);
    const int flags[] = { O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_TRUNC, O_APPEND,
            O_WRONLY | O_CREAT | O_TRUNC,
            O_WRONLY | O_CREAT | O_APPEND,
            O_RDWR | O_CREAT | O_TRUNC,
            O_RDWR | O_CREAT | O_APPEND
    };
    const char flags_str[][100] = { "O_RDONLY", "O_WRONLY", "O_RDWR", "O_CREAT", "O_TRUNC", "O_APPEND",
            "O_WRONLY | O_CREAT | O_TRUNC",
            "O_WRONLY | O_CREAT | O_APPEND",
            "O_RDWR | O_CREAT | O_TRUNC",
            "O_RDWR | O_CREAT | O_APPEND"
    };
    const size_t nflags = sizeof(flags) / sizeof(flags[0]);
    for (size_t iflag = 0 ; iflag < nflags ; iflag++) {
        const int flag = flags[iflag];
        const char * flag_str = flags_str[iflag];
        char nbin[33];
        to_binary(flag, nbin);
        printf( "*** Flag %30s = %5d = %12s = x%04x\n", flag_str, flag, nbin, flag);
    }
    for (size_t imode = 0 ; imode < nmodes ; imode++) {
        const char * mode = modes[imode];
        FILE * fp1 = fopen(fname, mode);
        int fd1 = fileno(fp1);
        int retval = fcntl(fd1, F_GETFL);
        char nbin[33];
        to_binary(retval, nbin);
        printf( "*** Mode %2s  F_GETFL -> %5d = %12s = x%04x", mode, retval, nbin, retval);
        fclose(fp1);
    }
    return 0;
}

这篇关于如何获得文件描述符的模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆