Linux实时信号程序中锁的探索

发表于:2010-9-17 11:43

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:未知    来源:51Testing软件测试网采编

  修改后的程序在运行时,无论信号发生在任何时刻都不会导致程序的死锁,信号函数在请求锁时一旦失败立即返回,而并不是死等在锁的请求上。当主程序有机会继续运行时,将锁进行释放,从而避免了死锁。执行结果如下:

xxx@xxx-desktop:~$ ./test &

xxx@xxx-desktop:~$ kill -35 18748
enter signal handler. If there is no exit message, a dead lock happened.
exit signal handler. Lock failed
main thread, crit_value = 1.
xxx@xxx-desktop:~$ kill -35 18748

signal handled, crit_value = 0.

  前后两次发送信号发生在不同的阶段,第一个信号发生于主函数持有锁的过程中,信号函数由于未能获得锁而退出;第二个信号发生在主函数释放锁之后,信号函数成功获得锁。虽然这种方法避免了死锁,但却是以丢弃信号作为代价,因此这并不是一个好的解决办法,是否有更好的办法避免这个问题呢,下面引入第二节,来探讨这个问题。

  方案 2,使用双线程处理信号与锁

  参考 Linux 系统、NPTL 对实时信号的实现,当系统派发一个信号给一个进程时,会选择该进程的某个线程进行处理,前提是这个线程未屏蔽该信号。而被选中的线程将先中断自己的执行并跳转至信号函数执行,当信号函数执行完毕后,信号就被处理完毕,并进行释放,最后被中断的线程返回到中断处继续运行。但是,在被选中线程处理信号的过程中,其他线程并不会停止运行,而是和信号处理线程处于平行关系的执行顺序,与线程间的执行关系完全相同,即信号函数的执行空间是在线程内的。如图 2

图 2. 双线程时,信号的处理

  这就给我们以一个提示,如果我们用 MainThread线程作为主线程运行,并使其屏蔽该信号,Thread1线程作为信号处理线程执行,专门用于信号函数的处理,并对 MainThread和 SignalHandler之间临界区的访问进行加锁,这样既避免死锁的问题,又避免了临界区访问重入问题,同时也避免了信号丢失。其中,需要使用到线程信号处理函数:

int pthread_sigmask(int how, const sigset_t *newmask, sigset_t *oldmask);

  该函数的作用与 sigprocmask 函数颇为类似,但它处理的范围仅限于调用线程。how指定了处理 signalmask的方法,可以为 SIG_SETMASK,SIG_BLOCK或者 SIG_UNBLOCK,顾名思义,SIG_SETMASK使用 newmask参数替换原有 signal mask;SIG_BLOCK将 newmask里面的 signal mask标志位置为 block状态;SIG_UNBLOCK与前者功能相反。oldmask里面用来存放替换前的 signal mask状态,如果程序不需要恢复原来的 signal mask状态,可将这个参数置为 NULL。

  按照思路修改程序,其中关键程序片段如下:

  清单 3. 使用 pthread_sigmask 屏蔽主线程接收信号

int main()
{

if ( pthread_create( &Thread1_pt, NULL, &thread1_func, NULL ) != 0)
perror( "Creating Child thread failed\n" );
// Blocking RT_TEST_SIG in Main Thread, always using thread1.
sigset_t sigmask;
sigemptyset( &sigmask );
sigaddset( &sigmask, RT_TEST_SIG );
// Should not use sigprocmask, it will block signals over process instead thread.
pthread_sigmask( SIG_BLOCK, &sigmask, NULL );

}

43/4<1234>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号