Multithreading 使用sigprocmask实现锁
我在Linux内核2.4中实现用户线程,并使用ualarm调用线程之间的上下文切换 我们有一个要求,线程库的函数应该不受线程上下文切换机制的干扰,所以我研究了阻塞信号,了解到使用sigprocmask是实现这一点的标准方法 但是,要实现这一点,我似乎需要做很多工作:Multithreading 使用sigprocmask实现锁,multithreading,linux-kernel,signals,Multithreading,Linux Kernel,Signals,我在Linux内核2.4中实现用户线程,并使用ualarm调用线程之间的上下文切换 我们有一个要求,线程库的函数应该不受线程上下文切换机制的干扰,所以我研究了阻塞信号,了解到使用sigprocmask是实现这一点的标准方法 但是,要实现这一点,我似乎需要做很多工作: sigset_t new_set, old_set; sigemptyset(&new_set); sigaddset(&new_set, SIGALRM); sigprocmask(SIG_BLOCK, &
sigset_t new_set, old_set;
sigemptyset(&new_set);
sigaddset(&new_set, SIGALRM);
sigprocmask(SIG_BLOCK, &new_set, &old_set);
这会阻止SIGALARM,但它会通过3次函数调用实现这一点!在运行这些函数所需的时间内,可能会发生很多事情,包括发送的信号。
我缓解这种情况的最好办法是暂时禁用ualarm,如下所示:
sigset_t new_set, old_set;
time=ualarm(0,0);
sigemptyset(&new_set);
sigaddset(&new_set, SIGALRM);
sigprocmask(SIG_BLOCK, &new_set, &old_set);
ualarm(time, 0);
这很好,只是感觉很冗长。难道没有更好的办法吗 您会发现中的
sigeptyset()
和sigaddset()
只是宏或内联函数,因此它们在代码中内联执行。调用它们时只需使用堆栈变量
但是,为什么不在代码的单线程启动部分中执行此操作?我还怀疑对sigprocmask的函数调用将是原子的。阻止信号并不意味着您的代码将是不可中断的 顺便说一句,我不确定您是如何使用ualarm的,但是如果您在第一次调用它时没有捕获或忽略SIGALARM,您可能会终止您的进程。正如所指出的,信号集函数非常轻量级,甚至可以作为宏来实现;您也可以只保留一个只包含
SIGALRM
的信号集,然后重新使用它
不管怎样,信号是否发生在
sigaddset()
或sigeptyset()
调用期间实际上并不重要,new\u集
和old\u集
变量(可能)是线程本地的,并且在sigprocmask()
返回之后才进入关键部分。sigprocmask()是进入内核级别并实际更改信号屏蔽状态的唯一函数。其他函数只是在调用sigprocmask或将集合传递给另一个信号相关函数之前设置掩码的操纵函数。“阻止信号并不意味着您的代码将是不可中断的。”是的,我的意思是通过我正在实现的上下文切换机制不可中断(更新的问题)。ualarm在每个线程\u时间\u片上关闭,处理程序将执行切换到另一个线程。