-ERESTARTSYS理解

来源:互联网 发布:数据化人生txt下载 编辑:程序博客网 时间:2024/05/18 01:03
1,
http://blog.csdn.net/xjingfeng/article/details/11603887
-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 be seen in user space. It either gets translated to a -1 return and errno set to EINTR, 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: some system calls can't be restarted with the same parameters! 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.
http://stackoverflow.com/questions/9576604/what-does-erestartsys-used-while-writing-linux-driver
2,
http://blog.csdn.net/vhghhd/article/details/6856659
经常我们在睡眠的代码中 会看到这样的例子:
    if (signal_pending(current)) {
     ret = -ERESTARTSYS;
     return ret;
    }
    关于 -ERESTARTSYS 到底是什么意思? 
-ERESTARTSYS表示信号函数处理完毕后重新执行信号函数前的某个系统调用.
也就是说,如果信号处理函数前有发生系统调用,在调度用户信号函数之前,内核会检查系统调用的返回值,看看是不是因为这个信号而中断了系统调用.如果返回值-ERESTARTSYS,并且当前调度的信号具备-ERESTARTSYS属性,系统就会在用户信号函数返回之后再执行该系统调用
这个过程,不必深究,你就知道上层的库函数 ,当收到 -ERESTARTSYS这个返回值后,对于Linux来讲,会自动的重新调用这个调用就可以了。
至于
signal_pending( current )―――》检查当前进程是否有信号处理,返回不为0表示有信号需要处理。
情景分析:
1,当一个系统调用处于等待状态时,比如等待输入缓冲区不为空,此时产生了信号,这个信号仅仅是在该进程的thread_info结构中标识一下,就是所谓的“发信号”,然后唤醒进程的系统调用,系统调用醒来后,此时仅仅用signal_pending()检查一下是否有信号,这里,不处理信号的,当此时有信号,系统调用返回ERESTARTSYS,在从系统调用的返回用户空间时,会根据thread_info中信号标识位调用相应的信号处理函数,这里就是所谓的“接收信号”对于Linux,上层库函数会根据系统调用的ERESTARTSYS返回值重启该系统调用,而对于Solaris则会让系统调用失败,在Linux中,重启的系统调用会再次检查缓冲区,为空,说明刚才的信号不是缓冲区有数据了的信号,继续等待,重复刚才的过程,不为空,就可以直接处理数据,系统调用正常结束
注:“发信号”仅仅是标识thread_info,系统调用醒来检查信号,仅仅是signal_pending()判断一下thread_info中是否有任何一个信号标识,真正的“接受信号”是从系统调用返回时,或者异常处理程序返回时,比如每次的时钟中断处理函数返回时,检查thread_info中具体哪个信号,调用相应处理程序
补:对于Solaris,上面的情况,read在等,缓冲区满了,唤醒read进程,不同通过我们这里所谈的“信号”
检测进程p是否有待处理的信号(p->thread_info->flags中TIF_SIGPENDING位是否置位)
-----------------------------------------------------
static inline int signal_pending(struct task_struct *p)
{
    return unlikely(test_tsk_thread_flag(p, TIF_SIGPENDING));
}