睡眠过程不响应信号

时间:2012-09-17 14:08:39

标签: c linux signals fork

我有一个程序,其中主要过程分为4个孩子,彼此合作:

process0打开FIFO文件(O_WRONLY),使用读取功能从STDIN一次读取1个字节,使用写入和关闭FIFO文件写入FIFO

process1正在等待共享内存为空(我正在使用共享内存表的第一个字节if(tab [0] == 0)来检查它是否为空)打开FIFO文件(O_RDONLY),从中读取,将这一个字节转换为十六进制并将其保存到共享内存中。然后它关闭fifo并将tab [0](共享内存表)设置为1.

如果tab [0] == 1,

process2正在从共享内存中读取。读取后,它将数据写入管道

process3正在读取管道并写入STDIN

这一切都很完美。当我想添加信号时问题就开始了。我正在使用信号量同步p0和p1,信号同步p1和p2以及消息队列同步p2和p3。除了例如process1处于休眠模式的时间之外,它也可以正常工作。当它想要从fifo读取并且必须等待数据传输时它进入这种模式。我想。我一直在读它。

processes hierarchy

以下是我发现我认为可能是原因:

“当进程在用户模式(1)中进行系统调用时,它进入状态2,开始以内核模式运行。此时假设系统调用是在硬盘上读取文件因为没有立即执行读取,所以进程进入休眠状态,等待系统读取磁盘并且数据准备就绪的事件。它现在处于状态4.当数据准备就绪时,进程是唤醒。这并不意味着它会立即运行,而是再次准备好在主内存中运行(3)。“

我想我理解但是如何避免这种情况?我希望我的程序始终对信号做出反应。当我通过“kill”发送信号时,是否有某种方法可以将进程状态从睡眠状态更改为运行状态?我可以以某种方式告诉进程停止“等待系统已读取磁盘且数据准备就绪的事件”吗?

这是我的代码,如果有人想看看它:

Program's code

2 个答案:

答案 0 :(得分:1)

如果我理解你的问题,过程1会挂在第442行(来源)并且没有响应信号,因为它位于read

显而易见的答案就是不要阻止read()。检查描述符以查看是否有任何内容可供阅读,如果没有则继续前进。阅读fcntl / ioctl以及如何进行非阻塞读取。

答案 1 :(得分:1)

您的观察结果可能是(大多数)系统调用默认在信号发生时重新启动。简而言之,这意味着系统调用中的代码在传递信号时会唤醒用户空间,但在信号处理程序运行后会恢复系统调用。

如果使用sigaction()建立信号处理程序而不是signal()函数,系统调用将在捕获信号时不会重新启动,而是失败并将errno设置为EINTR。 这意味着你必须处理这样一个事实,即由于传递信号,系统调用可以“失败”。

(signal()默认会导致linux重启系统调用,在包含signal.h头之前可以通过某些功能宏控制.sigaction()是否导致系统调用重启由SA_RESTART标志控制建立信号处理程序)