什么是ERESTARTSYS而写的Linux驱动程序使用? [英] What does ERESTARTSYS used while writing linux driver?

查看:189
本文介绍了什么是ERESTARTSYS而写的Linux驱动程序使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我学习的阻塞I / O功能,用于编写Linux设备驱动程序,我想知道什么是 ERESTARTSYS 的使用。考虑以下几点:

全局变量:

  wait_queue_head_t my_wait_q_head;
INT read_avail = 0;

结果
完Device_Init():

init_waitqueue_head(安培; my_wait_q_head);

结果
device_read():

 的printk(!我在里面阅读驱动\\ n);
wait_event_interruptible(安培; my_wait_q_head,read_avail!= 0);
printk的(我醒来\\ n!);

结果
device_write():

  read_avail = 1;
wake_up_interruptible(安培; my_wait_q_head);

结果
当我称之为阅读()从用户空间,在命令提示符下挂起,直到我称之为的write()预期。在的printk 相应的消息以及出现在的dmesg 。但是,我看到了一些这样写的驱动程序:

device_read的另一个版本():

 的printk(!我在里面阅读驱动\\ n);
如果(wait_event_interruptible(安培;!my_wait_q_head,read_avail = 0))
{返回-ERESTARTSYS;}
printk的(我醒来\\ n!);

我测试的第二个版本使用用户空间同样的方法device_read(),结果是完全一样的,所以,有什么用ERESTARTSYS的<? / p>

P / S:我读过这一本书的Linux设备驱动程序,但我不明白这一点,可有人举个例子来eleborate:


  

一旦我们得到过去的电话,事情已经醒我们,但我们不这样做
  知道什么。一种可能性是,该过程接收的信号。该
  如果包含wait_event_interruptible调用检查声明
  用于这种情况。此语句确保正确的和预期的反应
  到信号,这本来是负责唤醒
  过程(因为我们是在中断睡眠)。如果一个信号有
  通过该方法到达和它没有被堵塞,适当的
  行为是让内核的上层处理该事件。至
  为此,驾驶员返回-ERESTARTSYS给该呼叫者;这个值是
  由虚拟文件系统(VFS)层,其在内部使用
  重新启动系统调用或返回-EINTR到用户空间。我们使用
  同一类型的检查处理的信号处理,每读
  写的实现。


来源: http://www.makelinux.net/ldd3/chp-6-sect-2


解决方案

-ERESTARTSYS连接到重新启动的系统调用的概念。可重新启动的系统调用是一个可以透明地通过内核的时候有一些中断,重新执行。

有关实例的用户空间的过程,是在一个系统调用睡眠可以得到一个信号,执行一个处理程序,然后当处理程序返回,看来回去到内核,并保持睡在原来的系统调用。

使用sigaction的API,进程可以安排与信号相关的重新启动行为。这是POSIX的一部分。查一查sigaction的。

在Linux内核,当驾驶员或其它模块中的系统调用的上下文阻塞检测,因为一个信号的一个任务已经唤醒,它可以返回-EINTR。但-EINTR会冒泡到用户空间,并导致系统调用返回-1,并将errno设置为EINTR。

如果您返回-ERESTARTSYS相反,它意味着你的系统调用重新启动。该ERESTARTSYS code不一定会在用户空间中可以看出。它要么被转换为-1回报,并设置errno为EINTR(那么,很显然,出现在用户空间),也被翻译成一个系统调用重新启动行为,这意味着你的系统调用是使用相同的参数再次调用(用在用户空间程序的任何操作:内核通过积攒在一个特殊的重启块信息)做到这一点。

请注意与在previous款同样的参数这一明显的问题:一些系统调用不能使用相同的参数重新启动,因为它们是不一样的!举例来说,假设有一个电话的睡眠一样了nanosleep,5.3秒。它得到5秒后中断。如果天真地重新启动,它会再睡5.3秒。它通过新的参数重新启动的通话睡了仅剩下0.3秒;即,改变再启动块中的内容。有一种方法可以做到这一点:你的东西不同的参数到任务的启动块,并使用-ERESTART_RESTARTBLOCK返回值

要解决的第二个问题:有什么区别?为什么不只是写读出程序不检查返回值和返回-ERESTARTSYS?好了,因为那是在不正确的情况下,该唤醒是由于信号!你想读返回0字节读每当信号到达?这可能是由用户空间的数据结束PTED misinter $ P $。这种问题不会在测试用例显示不使用的信号。

I'm learning about the blocking I/O functions for writing linux device driver and I'm wondering what is the usage of ERESTARTSYS. 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?

p/s: I've read the book Linux Device Driver on this but I don't get it, can someone give an example to eleborate?:

Once we get past that call, something has woken us up, but we do not know what. One possibility is that the process received a signal. The if statement that contains the wait_event_interruptible call checks for this case. This statement ensures the proper and expected reaction to signals, which could have been responsible for waking up the process (since we were in an interruptible sleep). If a signal has arrived and it has not been blocked by the process, the proper behavior is to let upper layers of the kernel handle the event. To this end, the driver returns -ERESTARTSYS to the caller; this value is used internally by the virtual filesystem (VFS) layer, which either restarts the system call or returns -EINTR to user space. We use the same type of check to deal with signal handling for every read and write implementation.

Source : http://www.makelinux.net/ldd3/chp-6-sect-2

解决方案

-ERESTARTSYS is connected to the concept of a restartable system call. A restartable system call is one that can be transparently re-executed by the kernel when there is some interruption.

For instance the user space process which is sleeping in a system call can get a signal, execute a handler, and then when the handler returns, it appears to go back into the kernel and keeps sleeping on the original system call.

Using the sigaction API, processes can arrange the restart behavior associated with signals. This is all part of POSIX. Look up sigaction.

In the Linux kernel, when a driver or other module blocking in the context of a system call detects that a task has been woken because of a signal, it can return -EINTR. But -EINTR will bubble up to user space and cause the system call to return -1 with errno set to EINTR.

If you return -ERESTARTSYS instead, it means that your system call is restartable. The ERESTARTSYS code will not necessarily be seen in user space. It either gets translated to a -1 return and errno set to EINTR (then, obviously, seen in user space), or it is translated into a system call restart behavior, which means that your syscall is called again with the same arguments (by no action on part of the user space process: the kernel does this by stashing the info in a special restart block).

Note the obvious problem with "same arguments" in the previous paragraph: some system calls can't be restarted with the same parameters, because they are not idempotent! For instance, suppose there is a sleep call like nanosleep, for 5.3 seconds. It gets interrupted after 5 seconds. If it restarts naively, it will sleep for another 5.3 seconds. It has to pass new parameters to the restarted call to sleep for only the remaining 0.3 seconds; i.e. alter the contents of the restart block. There is a way to do that: you stuff different arguments into the task's restart block and use the -ERESTART_RESTARTBLOCK return value.

To address the second question: 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.

这篇关于什么是ERESTARTSYS而写的Linux驱动程序使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆