POSIX flags - 如何设置所有的/个别的

POSIX flags - how to set all of them / individual ones

我有这段代码应该从伪终端读取并打印到另一个伪终端 (stdin):

// Declare & define a file descriptor.
int fd;

int status;
char string[] = "XXXX";
char buffer[8];

// Establish connection between a file and the file descriptor.
fd = open("/dev/pts/4", O_RDWR);

// Check if connection was established.
if(fd == -1){
    printf("Assigning failed: %s\n", strerror(errno));
}
else{
    fputs("Assigning successful!\n", stdout);
    // Set some flags for the connection.
    fcntl(fd, F_SETFL, 0);
}
   
// Read from the connection.
status = read(fd, buffer, 8);
if (status == -1){
    printf("Read failed: %s\n", strerror(errno));
}
else{
    printf("I read this: %s\n", buffer);
}

return 0;

我不确切知道 fcntl(fd, F_SETFL, 0); 的作用,但在我使用它之前我无法读取 /dev/pts/4。第一次使用后,即使我注释掉这行代码,我也能正常阅读。

我试图通过阅读 POSIX...

向自己解释

F_SETFL 标志在 POSIX 中定义为:

Set the file status flags, defined in <fcntl.h>, for the file description associated with fildes from the corresponding bits in the third argument, arg, taken as type int. Bits corresponding to the file access mode and the file creation flags, as defined in <fcntl.h>, that are set in arg shall be ignored. If any bits in arg other than those mentioned here are changed by the application, the result is unspecified. If fildes does not support non-blocking operations, it is unspecified whether the O_NONBLOCK flag will be ignored.

所以它将与 fnctl() 的第一个参数(文件描述符)相关联的文件 status 标志设置为 0?我在 POSIX:

中找到了关于 status 标志的解释

The <fcntl.h> header shall define the following symbolic constants for use as file status flags for open(), openat(), and fcntl(). The values shall be suitable for use in #if preprocessing directives.

O_APPEND Set append mode. O_DSYNC Write according to synchronized I/O data integrity completion. O_NONBLOCK Non-blocking mode. O_RSYNC Synchronized read I/O operations. O_SYNC Write according to synchronized I/O file integrity completion.

那么 fcntl(fd, F_SETFL, 0); 是否将所有这些设置为 0?所有这些标志都是一个位吗?如何只将其中之一设置为 10?我怎么知道哪个位分配给了哪个标志?

这是一个位掩码。每个标志是您传递给 fcntl 的整数中的一位(或几位)。每个符号常量都扩展为一个数字,其中仅设置了相应的位,因此您可以通过将它们组合在一起来设置多个标志。例如,如果位 2 是附加标志,则 O_APPEND 将是 0b100 == 4;如果位 3 是非块标志,则 O_NONBLOCK 将是 0b1000 == 8,依此类推。但是通过使用符号常量,您不需要知道它们实际是哪些位,这很好,因为它们可能因操作系统而异。

fcntl(fd, F_SETFL, 0)中,数字0没有设置任何位,所以所有标志都被清除。要设置追加并清除其余部分,您可以执行 fcntl(fd, F_SETFL, O_APPEND);。要同时设置 append 和 nonblock,或者将它们的常量放在一起:fcntl(fd, F_SETFL, O_APPEND | O_NONBLOCK);

类似的位操作,可以对fl = fcntl(fd, F_GETFL)返回的flags进行操作:

int fl = fcntl(fd, F_GETFL);
if (fl & O_APPEND) { ... } // test if in append mode
fcntl(fd, F_SETFL, fl | O_NONBLOCK); // turn on nonblock and keep everything else the same
fcntl(fd, F_SETFL, fl & ~O_DSYNC); // turn off dsync and keep everything else the same

还有一些例子here