多线程环境下的信号处理

函数有线程安全和异步信号安全的分别,线程安全指的是在多线程环境下(函数可能同时有几个线程正在调用)是安全的;异步信号安全指的是即使被信号处理函数打断执行,在处理函数里面再次调用此函数依然没有问题,不会产生不良影响。比如mutex是线程安全的,但不是异步信号安全的。malloc也不是异步信号安全的。

实现里面的station类有若干个实例,每一个实例都存在于一个单独的派生线程中,每一个进程都需要一个定时器,时长不一样。定时器处理函数里面都需要处理各自实例的数据。这里就碰到了几个问题:如何防止在定时器处理函数里面和类的主流程数据访问冲突;如何在处理函数里面得到实例的指针。

因为对多线程环境的信号处理不熟悉,所以编了一个测试的小程序。主线程设置SIGALRM的处理函数T,在T里面再次调用alarm(5);工作线程P有3个,都设置其超时处理函数为T。P里面是一个死循环,每次sleep(6)。然后打印出sleep前后的时间差。根据输出到文件的信息,可以知道其实把线程理解成为一个进程就OK了,只是 主线程的信号量设置(block等)可以被派生的线程继承,但是各自的信号处理和设置都可以是单独的。利用pthread_kill可以想指定的线程发送信号,与sigwait则可以实现信号的同步处理。注意的是在派生线程里面,printf的输出并不显示到STDOUT,可能是被重定向了,还不清楚。

一个方法是可以在各个派生线程里面自己处理SIGALRM信号,但是如何获取本线程的STATION实例呢?信号处理函数不能传入,只能依靠全局变量,但是当时却没有想到简单的方法区分出各自线程独有的数据,晚上却突然想到了类似与getpid,pthread肯定也提供API得到本线程的id,一查果然是有pthread_self。这种方法下处理数据访问冲突比较简单,主流程里面在访问数据前设置一个标记即可,类似于mutex,此时不能用pthread_mutex_t,因为他不是异步线程安全的。

另外一个方法是采用sigwait的同步处理方法,创建一个线程专用于处理信号量,各个线程向他注册信号处理的回调函数,由他负责在合适的时候调用。这时候,由于STATION线程的回调函数不是在信号中断上下文中执行,所以可以采用pthread_mutex_t。

当时遇到的一个问题是开始只是在信号处理线程中block了SIGALRM信号,主线程没有设置掩码,导致主线程过了几秒钟就会退出。一开始很是纳闷,后来用gdb调试才看到是因为有SIGALRM,才知道是怎么回事。不过为什么一定要在主线程中block呢?我的alarm也是在信号处理线程里面的啊?难道在派生线程中产生的信号,也会被递到主线程中?明天有时间还得仔细测试下。

前一种方法相对简单(可行的话),逻辑也比较清楚,但是会打断主流程;后一种方法看起来很美,并且在不同的线程执行,对主任务影响不大,缺点是如果管理的定时任务多的话,后续的定时会有明显的延迟,并且使用mutex(try lock)。打算先用着第二种方法,将来有必要再来改进。

gdb的几个thread调试命令:infor thread, thread [id], 还有一个设置是否所有线程同时挂起的命令给忘了。

还有很多任务要做:多实例化,改进目前的IO模型,有无必要使用splitter模式等等。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值