O_CLOEXEC和TIOCEXCL之间的区别

5

我在串口/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;
}

使用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;
}

2
TIOCEXCL 不是“exec关闭”。它将终端设置为“独占”模式。它与防止泄漏文件描述符无关。您可能在考虑使用 fcntl(fd, F_SETFD, old_flags | FD_CLOEXEC) 代替。 - user824425
1个回答

5
TIOCEXCL不会设置关闭执行标志(应该是FIOCLEX或等效地fcntl(fd, F_SETFD, FD_CLOEXEC))。
回答你原以为的问题:
在使用open()打开文件时指定O_CLOEXEC将在返回之前设置关闭执行标志,这样可以节省另一个调用,并确保没有竞争条件,即在open()之后但在后续的fcntl()之前,另一个线程可能会调用exec()
如果您真的需要在任何其他时间设置或取消标志(我从未需要过),则可以使用fcntl F_SETFD进行操作,分别传递FD_CLOEXEC0

2
open(..., O_CLOEXEC) 不仅可以节省一次调用,还可以确保标志原子地设置。否则,如果您有一个多线程程序,一个线程可能会在 open() 和随后的 fcntl(..., FD_CLOEXEC) 调用之间立即调用 exec() - G. Sliepen
感谢@G.Sliepen - 我认为情况是这样的,但想要确认它是否在系统调用中而不是C库中实现。我会将这些信息添加到我的答案中。 - Toby Speight

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接