Signal处理中的函数可重入问题

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

时间: 2024-11-05 18:47:11

Signal处理中的函数可重入问题的相关文章

Use Reentrant Functions for Safer Signal Handling(译:使用可重入函数进行更安全的信号处理)

Use Reentrant Functions for Safer Signal Handling 使用可重入函数进行更安全的信号处理 How and when to employ reentrancy to keep your code bug free 何时及如何利用可重入性避免代码缺陷 Dipak Jha (mailto:[email protected]?subject=Use reentrant functions for safer signal handling&[email pr

函数可重入问题reentrant functions(函数执行过程中可以被中断,允许多个副本)

最近经常听到这个名词,以前也听到过,不过接触更多的是“线程安全问题”,而且本人也一直理解的是两个名字的含义是一样的.今天仔细总结一下这个名词相关的概念. 引用博文:可重入函数和不可重入函数 (http://www.cppblog.com/franksunny/archive/2007/08/03/29269.html) 主要用于多任务环境中, 一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误

C语言之可重入函数 && 不可重入函数

可重入函数 在 实时系统的设计中,经常会出现多个任务调用同一个函数的情况.如果这个函数不幸被设计成为不可重入的函数的话,那么不同任务调用这个函数时可能修改其他任 务调用这个函数的数据,从而导致不可预料的后果.那么什么是可重入函数呢?所谓可重入是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会 出错.不可重入函数在实时系统设计中被视为不安全函数. 满足下列条件的函数多数是不可重入的: (1)函数体内使用了静态的数据结构: (2)函数体内调用了malloc()或者free()函数: (

函数可重入性及编写规范

一.可重入函数1)什么是可重入性?可重入(reentrant)函数可以由多于一个任务并发使用,而不必担心数据错误.相反, 不可重入(non-reentrant)函数不能由超过一个任务所共享,除非能确保函数的互斥(或者使用信号量,或者在代码的关键部分禁用中断).可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据.可重入函数要么使用本地变量,要么在使用全局变量时保护自己的数据. 2)可重入函数:不为连续的调用持有静态数据. 不返回指向静态数据的指针:所有数据都由函数的调用者提供. 使用本地

2信号处理之:信号产生原因,进程处理信号行为,信号集处理函数,PCB的信号集,sigprocmask()和sigpending(),信号捕捉设定,sigaction,C标准库信号处理函数,可重入函数,

 1信号产生原因 2.进程处理信号行为 manpage里信号3中处理方式: SIG_IGN SIG_DFL                                            默认Term动作 a signal handling function 进程处理信号 A默认处理动作 term   中断 core    core(调试的时候产生) gcc –g file.c ulimit –c 1024 gdb a.out core ign      忽略 stop     停止

关于C#中Timer定时器的重入问题解决方法

项目中用到了定时器随着服务启动作定时任务,按指定的准点时间定时执行相关操作,但是在指定准点时间内我只想让它执行一次,要避免重入问题的发生. 首先简单介绍一下timer,这里所说的timer是指的System.Timers.timer,顾名思义,就是可以在指定的间隔是引发事件.官方介绍在这里,摘抄如下: Timer 组件是基于服务器的计时器,它使您能够指定在应用程序中引发 Elapsed 事件的周期性间隔.然后可通过处理这个事件来提供常规处理. 例如,假设您有一台关键性服务器,必须每周 7 天.每

10.6 可重入函数

当一个信号捕获到并开始被进程处理的时候,进程正常执行的指令序列将被信号处理函数临时中断,进程立即转到信号处理函数中开始执行,如果信号处理函数返回(而不是调用exit或者是longjmp等),然后在进入信号处理函数之前进程正在执行的指令序列将会接着执行,但是在信号处理函数中,我们无法获知在信号被捕获的时候进程正在执行那一段代码,如果进程正在使用函数malloc在其堆上分配额外的内存的过程中会发生什么呢?或者是进程正在调用一个函数的过程中,比如说getpwnam将会发生什么呢?函数getpwnam会

函数的可重入性、线程安全函数、异步信号安全函数

重入即表示重复进入,首先它意味着这个函数可以被中断,其次意味着它除了使用自己栈上的变量以外不依赖于任何环境(包括static),这样的函数就是purecode(纯代码)可重入,可以允许有该函数的多个副本在运行,由于它们使用的是分离的栈,所以不会互相干扰.,常见的情况是,程序执行到某个函数foo()时,收到信号,于是暂停目前正在执行的函数,转到信号处理函数,而这个信号处理函数的执行过程中,又恰恰也会进入到刚刚执行的函数foo(),这样便发生了所谓的重入.此时如果foo()能够正确的运行,而且处理完

[学习笔记]信号处理函数遇上可重入和不可重入函数

可重入函数概念 q  为了增强程序的稳定性,在信号处理函数中应使用可重入函数. q  所谓可重入函数是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会出错.因为进程在收到信号后,就将跳转到信号处理函数去接着执行.如果信号处理函数中使用了不可重入函数,那么信号处理函数可能会修改原来进程中不应该被修改的数据,这样进程从信号处理函数中返回接着执行时,可能会出现不可预料的后果.不可再入函数在信号处理函数中被视为不安全函数. q  满足下列条件的函数多数是不可再入的:(1)使用静态的数据结构