std::signal和std::raise线程是否安全? < C和C++标准支持信号的概念。但是,C11标准规定,在多线程环境中不能调用函数signal(),或者行为未定义。但我认为信号机制本质上是针对多线程环境的

std::signal和std::raise线程是否安全? < C和C++标准支持信号的概念。但是,C11标准规定,在多线程环境中不能调用函数signal(),或者行为未定义。但我认为信号机制本质上是针对多线程环境的,c++,c,multithreading,c++11,signals,C++,C,Multithreading,C++11,Signals,引用C11标准7.14.1.1.7 “在多线程程序中使用此函数会导致未定义的行为 实现应表现为没有库函数调用信号函数。” 对此有何解释 以下代码是不言而喻的 #include <thread> #include <csignal> using namespace std; void SignalHandler(int) { // Which thread context here? } void f() { // // Running in

引用C11标准7.14.1.1.7

“在多线程程序中使用此函数会导致未定义的行为 实现应表现为没有库函数调用信号函数。”

对此有何解释

以下代码是不言而喻的

#include <thread>
#include <csignal>

using namespace std;

void SignalHandler(int)
{
    // Which thread context here?
}

void f()
{
    //
    // Running in another thread context.
    //
    raise(SIGINT); // Is this call safe?
}

int main()
{
    //
    // Register the signal handler in main thread context.
    //
    signal(SIGINT, SignalHandler);

    thread(f).join();
}
#包括
#包括
使用名称空间std;
无效信号处理器(int)
{
//这里是哪个线程上下文?
}
void f()
{
//
//在另一个线程上下文中运行。
//
升起(信号);//这个呼叫安全吗?
}
int main()
{
//
//在主线程上下文中注册信号处理程序。
//
信号(SIGINT,信号处理器);
螺纹(f.join();
}
但我认为信号机制本质上是针对多线程环境的


我认为这句话是主要的误解<代码>信号()是进程间通信的方法,而不是线程间通信的方法。线程共享公共内存,因此可以通过互斥体和控制结构进行通信。进程没有公共内存,必须使用一些显式的通信结构,如
signal()
或文件系统。

我认为您混淆了特定于进程的信令与线程之间的通信。如果它是在您所关注的线程之间共享信息,那么您可能会在新的线程中找到您想要的内容。当然,这取决于你真正想做什么


根据我对代码的了解,您需要一个线程以某种方式“通知”事件,并且希望能够在该事件发出信号时运行一些代码。有鉴于此,我将仔细查看线程支持库中的Futures部分

C11标准声明“在多线程程序中使用此函数会导致未定义的行为”,具体指函数
signal()
。因此,问题是
signal()
的使用是否“在多线程程序中”完成

据我所知,“多线程程序”一词在C标准中没有定义,但我认为它是指一个已经创建了多个执行线程但尚未完成的程序。这意味着在示例程序中调用
signal()
时,程序不是多线程的,因此程序的行为在此要求下不是未定义的

(但是C++ 11要求“所有信号处理程序都应该具有C链接”(18.10其他运行时支持[Suff.RunTime] P9]。因为您的示例程序使用一个带有C++链接的处理程序,行为是未定义的)。

正如其他人所指出的,信号并不用于线程之间的通信。例如,C和C++标准甚至不指定它们运行的线程。相反,标准库为线程间通信提供了其他工具,如互斥、原子等。

我认为您只是误解了术语“未定义的行为”,不幸的是,这意味着“糟糕的事情会发生”。这里这个术语的真正含义是:C标准没有对在多线程上下文中使用
signal
的含义做出任何假设

一般来说,C标准中的
signal
/
raise
接口本身不是很有用,它只是在上面定义的平台/OS特定事物的占位符

所以对于
信号
和威胁之间的交互,并不能给你一个契约。否则,
信号
和线程的交互将留给平台
实现。

信令最初用于进程间通信(IPC)。在POSIX中,多线程应用程序中的信号支持大多是事后才想到的,而在异步信号存在的情况下,很多线程的东西变得非常糟糕。正如标准所说,这不是必须的。此外,为什么你真的需要它?在多线程应用程序中,除了给自己发信号外,还有更直接的通信方式。这是标准的,我喜欢标准提供的函数,如果比系统提供的函数更好的话。@a.Mikhaylov这不正是OP问题中的标准引用所说的吗?未定义的行为意味着,例如,您不知道信号处理程序是否会中断所有线程,或者它是否会在当前执行的线程上执行,或者在某个可预测的线程(如设置处理程序的线程)上执行。如果是后者,这是抢占其他线程还是等待轮到它?这只是一个冰山一角,当你考虑要扩展这些函数定义的多线程行为时。C++标准决定不尝试。如果一个进程注册了一个信号处理程序,另一个进程叫做加法;第一个进程的信号处理程序能接收到信号吗?@xmllmx:标准未定义。在Linux上,是的。但是,在Linux中,只需使用pthread就可以了。这些函数现在已经过时了吗?标准是否仅支持向后兼容?@xmllmx:
signal
已被
sigaction
取代,但功能本身完全正常。它们并不适用于多线程程序。@C中定义的xmllmx信号对任何事情都不是特别有用。它需要额外的实现定义的保证,例如某些库函数可以在处理程序中调用,以使它们有用。除了标准要求之外,Windows不支持太多(如果有的话)。相反,Windows有自己的特定于平台的进程间通信方法。对于线程间通信,支持C++11线程库