关于在写linux driver时的ERESTARTSYS的作用

来源:互联网 发布:李炎恢javascript下载 编辑:程序博客网 时间:2024/06/04 18:31
作用:
-ERESTARTSYS的与“可重新执行的系统调用”的概念相关联,一个可重新执行的系统调用是一个当有一些中断发生后能透明的被kernel重新执行的系统调用。
比如用户空间进程在执行一个系统调用时产生休眠,此时捕获到一个信号,执行信号处理函数,然后当从信号处理函数返回,表现为重新执行之前的那个系统调用进入睡眠状态。
使用sigaction 系统API,进程能够安排与信号相关的重新执行行为。这些都是POSIX所规定的。可以看看APUE中的sigaction函数说明。
在linux kernel中,当一个驱动或其它模块阻塞在一个系统调用的上下文中,探测到一个task己经被一个信号唤醒,它会返回-EINTR。但-EINTR将向上冒泡般传递到用户空间,并导致这个系统调用返回-1,errno被设置为EINTR。
如果你返回-ERESTARTSYS代替-EINTR,那么它意味着你的系统调用是可以重新启动的。ERESTARTSYS将不是必须在用户空间被感觉到,有两种表现形式,一种是在用户空间这个返回被翻译为一个-1的返回值,并且errno被设为EINTR(这时,很显然是被用户空间感觉到),另一种是被kernel透明的重新执行,使用之前执行这个系统调用时的参数,(没有在用户空间处理的部分:kernel隐藏所有信息)。

这里大家也许己经有疑问了,相同的参数,这不会出问题吗?的确,在某些系统调用中,这的确是会出问题的,比如:你执行系统调用nanosleep, 睡眠5.3秒,结果睡了5秒后,被 一个信号中断了,当信号处理结束返回时,就不能简单的继续执行nanosleep睡5.3秒,这时应该睡0.3秒,也就是说,这个参数需要改变。有一个方法做这个:你修改一个不同的参数在task的restart block上,然后用ERESTART_RESTARTBLOCK做返回值。


Consider the following:

Global variable :

wait_queue_head_t my_wait_q_head;
int read_avail = 0;

device_init() :

init_waitqueue_head(&my_wait_q_head);


device_read():

printk("I'm inside driver read!\n");
wait_event_interruptible(&my_wait_q_head, read_avail != 0);
printk("I'm awaken!\n");

device_write():

read_avail = 1;
wake_up_interruptible(&my_wait_q_head);

When I call the read() from user space, the command prompt hang until I call the write() as expected. The printk messages appear accordingly as well in dmesg. However, I'm seeing some of the drivers written like this :

Another version of device_read():

printk("I'm inside driver read!\n");
if(wait_event_interruptible(&my_wait_q_head, read_avail != 0))    
{return -ERESTARTSYS;}
printk("I'm awaken!\n");
I tested the second version of device_read() using the same method in user space, and the result is exactly the same, so, what's the use of ERESTARTSYS?

回答:
what's the difference? Why not just write the read routine without checking the return value and returning -ERESTARTSYS? Well, because that is incorrect in the case that the wakeup is due to a signal! Do you want a read to return 0 bytes read whenever a signal arrives? That could be misinterpreted by user space as end of data. This kind of problem won't show up in test cases that don't use signals.