1. Signal信号简介
信号是软件层次上模拟的中断,它是一种异步通信的处理机制。信号的异步性意味着,应用程序不用等待事件的发生,当信号发生时应用程序自动陷入到对应的信号处理函数中。产生信号的事件对进程而言是随机出现的。信号的响应方式有忽略、捕捉、执行默认动作三种。
2. 线程安全
线程安全函数:在C语言中局部变量是在栈中分配的,任何未使用静态数据或其他共享资源的函数都是线程安全的。使用全局变量的函数是非线程安全的。使用静态数据或其他共享资源的函数,必须通过加锁的方式来使函数实现线程安全。
线程安全的(Thread-Safe):如果一个函数在同一时刻可以被多个线程安全地调用,就称该函数是线程安全的。线程安全函数解决多个线程调用函数时访问共享资源的冲突问题。
3. 可重入
可重入(Reentrant)函数可以由多于一个线程并发使用,而不必担心数据错误。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据。可重入性解决函数运行结果的确定性和可重复性。
1) 一个函数对于多个线程是可重入的,则这个函数是线程安全的;
2) 一个函数是线程安全的,但并不一定是可重入的,比如使用互斥锁实现的线程安全;
3) 可重入性要强于线程安全性。
4. Signal信号处理
信号处理函数中只能调用可重入函数,而不能调用不可重入函数。进程捕捉到信号并对其进行处理时,正在执行的正常指令序列就被信号处理程序临时中断,它首先执行该信号处理函数中的指令。如果从信号处理程序返回,则继续执行在捕捉到信号时正在执行的正常指令序列(这类似于发生硬件中断时所做的)。但在信号处理函数中,不能判断捕捉到信号时线程执行到何处。
信号处理函数默认情况下是在进程的主线程调用的,这种情况下使用不可重入函数,有可能会造成不可预知的错误。比如调用了malloc函数,为了保证malloc是线程安全的,所以内部使用了锁,根据malloc中锁的不同处理方式,分别可能会导致以下情况的发生:
1) 如果是普通锁,在主线程中malloc函数获取锁之后被signal中断,在signal处理函数中继续调用malloc,因为主线程中的malloc已经获取到了锁,signal处理函数只能等待锁释放,而主线程中的malloc函数正在等待signal处理函数返回后继续执行,这样就造成了锁死;
2) 如果是递归锁,那么signal处理函数中的malloc函数获取锁后进行内存分配,因为上次的malloc操作还没完,可能成会造成内存数据混乱。
就定时而言,可不直接使用singal alarm,而使用posix定时器,通过通知线程的方式,将定时处理函数放到单独的线程中来处理。
原文地址:http://blog.51cto.com/13578681/2145288