【问题标题】:Can fnctl(F_SETOWN, <pid>) direct a signal to a pthread ID instead of a process ID?fnctl(F_SETOWN, <pid>) 可以将信号定向到 pthread ID 而不是进程 ID?
【发布时间】:2018-09-28 14:06:54
【问题描述】:

我正在开发一个应用程序,它将在 Linux 上从串行/UART 读取数据。当 UART 从外部源异步获取数据时,我正在尝试唤醒/解除阻止 pthread 开始读取数据。我正在考虑使用信号(SIGIO)“软中断”而不是 select() 或 pselect(),但我不确定是否可以从信号中获得我想要的多线程应用程序的行为。

当我配置设备文件描述符时,我想设置 F_SETOWN(int) 以让内核向我设置为阻塞 SIGIO 的 pthread 发送信号。

            // Configure the signal to send
            fcntl(m_fileId, F_SETSIG, m_sigNum);

            // Set to non-blocking read mode
            fcntl(m_fileId, F_SETFL, FNDELAY);

            // Bind the PID of the task which is getting the signal
            fcntl(m_fileId, F_SETOWN, m_pid);

            // Enable sending a signal when data ready
            fcntl(m_fileId, F_SETFL, O_ASYNC);

我意识到,当我编写代码时,m_pid 被设置为进程 ID,而不是 pthread ID,当我检查手册页时......

根据 fnctl(2) 手册页:

F_SETOWN (int)

将接收文件描述符 fd 上事件的 SIGIO 和 SIGURG 信号的进程 ID 或进程组 ID 设置为 arg 中给出的 ID。进程 ID 指定为正值;进程组 ID 指定为负值。最常见的是,调用进程将自己指定为所有者(即,arg 被指定为 getpid(2))。

您可以在调用 pthread_self() 时传入一个 pthread ID,而不是使用 getpid() 作为进程 ID,这样只有特定的线程才能获得信号吗?

【问题讨论】:

    标签: c linux signals posix


    【解决方案1】:

    在 Linux 上,您可以使用 F_SETOWN_EX 来定位特定线程。

    来自手册页:

    以下情况在 2.6.x 内核(包括内核)中是正确的 2.6.11:

    如果在多线程进程中给 F_SETSIG 一个非零值 使用支持的线程库运行 端口线程组(例如,NPTL),则赋予 F_SETOWN 的正值具有不同的含义:而不是 作为标识整个进程的进程ID,它是标识一个特定线程的线程ID 过程。因此,可能需要将 gettid(2) 的结果而不是 getpid(2) 的结果传递给 F_SETOWN 使用 F_SETSIG 时获得合理的结果。 (在当前的 Linux 线程实现中,主线程的 线程 ID 与其进程 ID 相同。这意味着单线程程序同样可以使用 gettid(2) 或 getpid(2) 在这种情况下。)但是请注意,本段中的陈述不适用于 为套接字上的带外数据生成的 SIGURG 信号:此信号始终发送到进程或 进程组,取决于赋予 F_SETOWN 的值。

    上述行为在 Linux 2.6.12 中被意外删除,并且不会 得到恢复。从 Linux 2.6.32 开始,使用 F_SETOWN_EX 在特定线程中针对 SIGIO 和 SIGURG 信号。

    Linux 将期望 pid/tid(从内核的角度来看线程 ID;Linux 经常将它们称为 pid,即使它们标识线程而不是进程),而不是 pthread_t

    Pthread 实现通常会在内部以特定于实现的方式将 pthread_t's 映射到 pids,您可以破解您的特定实现来获取它。

    或者,您可以包装 pthread_create 以在创建线程时插入 pthread_t-to-pid 映射哈希表条目,以便您以后可以将 pthread_ts 映射到 pids 而不依赖于您的 pthread 实现。

    (可以通过syscall(SYS_gettid)获取当前线程的pid)。

    【讨论】:

    • 感谢您的指点!当我阅读手册页(DOH!)时,我错过了它。我会试一试,让你知道它是否适合我。
    猜你喜欢
    • 1970-01-01
    • 2014-12-05
    • 2013-07-28
    • 1970-01-01
    • 2015-05-11
    • 2019-10-31
    • 2017-11-17
    • 2011-03-03
    相关资源
    最近更新 更多