2012-09-17 38 views
0

我已经有了一个应对方案,其中主要过程分叉成4点的孩子,互相配合:睡眠过程中不给信号

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

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

过程2是从共享存储器读出,如果标签[0] == 1看完之后将数据写入管道

process3被从管道读取并写入STDIN

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

processes hierarchy

这里是我发现,我认为可能的原因:

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

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

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

Program's code

回答

1

如果我正确理解你的问题,处理1可以取出线442(源)挂了电话,不回应的信号,因为它是在read

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

1

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

如果使用sigaction()建立信号处理程序而不是signal()函数。,当信号被捕获时系统调用不会重新启动,而是失败并将errno设置为EINTR。 这意味着你必须处理这样一个事实,即由于信号被传递,系统调用可能在任何地方“失败”。 (signal()默认会在linux重启时引起系统调用,在包含signal.h头文件之前可以通过某些特性宏来控制它)。sigaction()是否导致系统调用重启由flag SA_RESTART控制当建立信号处理器时)