24.4.6信号处理和不可重入功能
处理程序函数通常做得不多。最佳实践是编写一个处理程序,它只会设置一个外部变量程序定期检查,并将所有重要工作交给程序。这是最好的,因为处理程序可以在原始函数中间的不可预测时间段,或即使在C运算符的开头和结尾之间多条指令。被操作的数据结构可能因此,当处理程序函数为已调用。甚至复制一个整数
变量转换为另一个可以需要两个大多数机器上的说明。
这意味着你必须非常小心你在信号中所做的事情处理程序。
- 如果处理程序需要从程序中访问任何全局变量,声明这些变量
不稳定的
。这告诉编译器变量的值可能会异步更改,并禁止某些优化会因此类修改而失效。 - 如果在处理程序中调用函数,请确保它是可重入的或确保信号不能中断对相关函数的调用。
如果函数使用的内存不在堆栈。
- 如果函数使用静态变量或全局变量,或它为自己找到的动态分配对象,那么它就是不可重入和对函数的任何两个调用都可能会产生干扰。
例如,假设信号处理程序使用获取主机名
.此函数在静态对象中返回其值,重复使用相同的对象。如果在呼叫期间信号碰巧到达按主机名
,甚至在一个之后(当程序仍在运行时使用值),它将破坏程序要求的值。
但是,如果程序不使用按主机名
或任何其他函数返回同一对象中的信息,或者每次使用都会屏蔽信号,这样你就安全了。
在固定对象,总是以这种方式重用同一对象它们导致了同样的问题。本手册中的功能说明总是提到这种行为。
- 如果函数使用并修改了您提供的对象,则它是潜在不可重入;如果两个调用使用同一个调用,则会产生干扰对象。
当您使用流进行I/O时,就会出现这种情况。假设信号处理程序打印消息格式化输出
。假设程序正在进行格式化输出
使用相同的调用发送信号时的流。信号处理程序的消息程序的数据可能会被破坏,因为这两个调用都在相同的数据结构-流本身。
然而,如果您知道处理程序使用的流不能可能在信号到达时被程序使用,然后你很安全。如果程序使用其他流,则没有问题。
- 在大多数系统上,
malloc公司
和自由的
不可重入,因为它们使用静态数据结构来记录内存积木是免费的。因此,没有库函数分配或空闲内存是可重入的。这包括分配空间的函数存储结果。避免在处理程序中分配内存的最佳方法是预先分配信号处理程序使用的空间。
避免释放处理程序中内存的最佳方法是标记或记录要释放的对象,并不时检查程序是否有任何东西等待释放。但这必须完成注意,因为将对象放在链上不是原子的,如果是原子的被另一个做同样事情的信号处理程序打断,您可能会“丢失”其中一个对象。
- 任何修改
错误编号
是不可重入的,但您可以更正如下:在处理程序中,保存错误编号
恢复后再正常返回。这样可以防止信号处理程序中发生的错误程序中断运行时的系统调用错误处理程序。该技术通常适用;如果您想调用处理程序修改内存中特定对象的函数,可以通过保存和恢复该对象来确保安全。
- 只要你能处理,仅仅从内存对象读取是安全的在以下情况下可能出现在对象中的任何值可以发送信号。记住对某些数据的赋值类型需要多条指令,这意味着处理程序如果变量的类型为不是原子的。请参见原子数据访问和信号处理.
- 只要突然改变,只向内存对象中写入数据是安全的在值中,在处理程序可能运行的任何时候,都不会干扰什么都可以。