Linux:信号处理程序执行可以被抢占吗?

Lun*_*oms 5 c linux signals interrupt-handling

我遇到了以下信号处理程序代码,它存储 errno 变量,以便它不会影响主线程的 errno 处理。

void myhandler(int signo)
{
    int esaved;
    esaved = errno;
    write(STDOUT_FILENO, "Got a signal\n", 13);
    errno = esaved;
}
Run Code Online (Sandbox Code Playgroud)

但这真的能达到目的吗?如果另一个线程在 write() 之后和恢复 errno 之前检查共享 errno 变量,会发生什么?该线程会由于竞争条件而获得错误的 errno 值吗?

或者信号处理程序相对于线程/进程以原子方式执行,因此一旦信号处理程序执行,内核就不会调度线程,直到信号处理程序完成为止?

换句话说 - 一旦启动,信号处理程序是否会执行而不会被以下情况中断:

 - 1) Scheduler (process/threads),  or  
 - 2) Other signals,  or
 - 3) Hardware interrupt handlers  ?
Run Code Online (Sandbox Code Playgroud)

Jon*_*ler 4

该变量errno是线程特定的 \xe2\x80\x94,或者更准确地说,在线程环境中,是线程本地或每个线程值 \xe2\x80\x94,因此errno在此线程中所做的操作不会影响errno在其他线程中。

\n\n

代码保存和恢复的目的errno是隐藏. 但是如果失败,它可能会设置为某个新值 \xe2\x80\x94 它不会为零,但这就是您可以说的所有内容 \xe2\x80\x94 但您询问的代码会恢复来自的值在调用to 之后,因此发生写入的事实是“不可见的”,因为它不会影响该线程。write()myhandler()write()errnowrite()write()errno

\n\n

信号处理函数本身可能会被未被其响应的信号的信号掩码阻止的信号中断。也可以重新安排。硬件中断也可能发生,但代码很难注意到这些影响。

\n\n
\n\n

在 Linux 上,您可能会发现/usr/include/bits/errno.h定义宏errno(包含在 more#ifdef代码比此处显示的更多):

\n\n
extern int *__errno_location (void) __THROW __attribute__ ((__const__));\n\n#  if !defined _LIBC || defined _LIBC_REENTRANT\n/* When using threads, errno is a per-thread value.  */\n#   define errno (*__errno_location ())\n#  endif\n
Run Code Online (Sandbox Code Playgroud)\n