O_CLOEXEC 和 TIOCEXCL 的区别

pbn*_*pbn 5 c linux

我在串行端口 /dev/ttyUSB0 上使用一个设备(使用 FTDI)并且我不想将任何文件描述符泄漏给其他生成的进程,因此我在描述符上设置了 close-on-exec 标志。你能告诉我在打开时设置 O_CLOEXEC 有什么区别:

#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
    int fd, rc;
    fd = open("/dev/ttyUSB1", O_RDWR | O_NOCTTY | O_CLOEXEC);
    if(fd < 0)
    {
        perror("error open:");
        exit(-1);
    }
    rc = close(fd);     
    if(rc != 0)
    {
        perror("error close:");
        exit(-1);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

并使用 ioctl(fd, TIOCEXCL) 设置 close-on-exec:

#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
    int fd, rc;

    fd = open("/dev/ttyUSB1", O_RDWR | O_NOCTTY);
    if(fd < 0)
    {
        perror("error open:");
        exit(-1);
    }

    rc = ioctl(fd, TIOCEXCL);
    if(rc != 0)
    {
        perror("error ioctl:");
        exit(-1);
    }

    rc = close(fd);     
    if(rc != 0)
    {
        perror("error close:");
        exit(-1);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Tob*_*ght 5

TIOCEXCL不会设置密on-exec标志(这将是FIOCLEX,或者等价地,fcntl(fd, F_SETFD, FD_CLOEXEC))。

回答你认为你在问的问题:

指定O_CLOEXEC当你open()的文件,将设置近on-exec标志返回之前,节省您的另一通话,且重要的是,确保没有竞争条件,其中另一个线程可能会调用exec()之后open(),但之前的后续fcntl()

如果您真的需要在任何其他时间设置或取消设置标志(我从来不需要),您可以分别使用fcntl F_SETFD、passingFD_CLOEXEC0

  • `open(..., O_CLOEXEC)` 不只是保存调用,它确保标志是原子设置的。否则,如果你有一个多线程程序,一个线程可能会在 `open()` 和随后的 `fcntl(..., FD_CLOEXEC)` 调用之间调用 `exec()`。 (2认同)