I'm*_*gon 29 c linux-device-driver linux-kernel
我正在学习用于编写linux设备驱动程序的阻塞I/O函数,我想知道它的用法是什么ERESTARTSYS.考虑以下:
全局变量:
wait_queue_head_t my_wait_q_head;
int read_avail = 0;
Run Code Online (Sandbox Code Playgroud)
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");
Run Code Online (Sandbox Code Playgroud)
device_write():
read_avail = 1;
wake_up_interruptible(&my_wait_q_head);
Run Code Online (Sandbox Code Playgroud)
当我调用read()from用户空间时,命令提示符会挂起,直到我write()按预期调用.的printk消息相应地出现,以及在dmesg.但是,我看到一些像这样编写的驱动程序:
另一个版本的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");
Run Code Online (Sandbox Code Playgroud)
我测试了device_read()在用户空间中使用相同方法的第二个版本,结果完全相同,那么,ERESTARTSYS的用途是什么?
p/s:我已经阅读了这本书上的Linux设备驱动程序,但是我没有得到它,有人可以举例来说明吗?:
一旦我们通过那个电话,有些东西唤醒了我们,但我们不知道是什么.一种可能性是该过程接收到信号.包含wait_event_interruptible调用的if语句将检查此情况.这个陈述确保了对信号的适当和预期的反应,这可能是唤醒过程的原因(因为我们处于可中断的睡眠状态).如果信号已到达并且尚未被进程阻止,则正确的行为是让内核的上层处理事件.为此,驱动程序将-ERESTARTSYS返回给调用者; 此值由虚拟文件系统(VFS)层在内部使用,该层可重新启动系统调用或将-EINTR返回到用户空间.我们使用相同类型的检查来处理每个读写实现的信号处理.
Kaz*_*Kaz 51
-ERESTARTSYS与可重启系统调用的概念相关联.可重新启动的系统调用是在内存中断时内核可以透明地重新执行的调用.
例如,在系统调用中休眠的用户空间进程可以获得信号,执行处理程序,然后当处理程序返回时,它似乎返回到内核并在原始系统调用上保持休眠状态.
使用POSIX sigactionAPI的SA_RESTART标志,进程可以安排与信号关联的重新启动行为.
在Linux内核中,当在系统调用的上下文中阻塞的驱动程序或其他模块检测到某个任务因信号而被唤醒时,它可以返回-EINTR.但是-EINTR将冒泡到用户空间并导致系统调用返回-1,并将errno设置为EINTR.
如果您返回-ERESTARTSYS,则表示您的系统调用可以重新启动.ERESTARTSYS代码不一定会出现在用户空间中.它要么被转换为-1返回而errno被设置为EINTR(显然,在用户空间中可见),或者它被转换为系统调用重启行为,这意味着使用相同的参数再次调用您的系统调用(通过对部分用户空间进程没有任何操作:内核通过在特殊的重启块中存储信息来完成此操作.
请注意前一段中"相同参数"的明显问题:某些系统调用无法使用相同的参数重新启动,因为它们不是幂等的!例如,假设有一个像nanosleep一样的睡眠呼叫,持续5.3秒.它会在5秒后中断.如果天真地重新开始,它将再睡5.3秒.它必须将新参数传递给重新启动的调用才能休眠0.3秒; 即改变重启块的内容.有一种方法可以做到这一点:将不同的参数填充到任务的重启块中,并使用-ERESTART_RESTARTBLOCK返回值.
解决第二个问题:有什么区别?为什么不在不检查返回值的情况下编写读取例程并返回-ERESTARTSYS?好吧,因为在唤醒是由信号引起的情况下这是不正确的!您是否希望读取在信号到达时返回0字节读取?这可能被用户空间误解为数据末尾.在不使用信号的测试用例中,这种问题不会出现.