为什么 `nanosleep` 需要 `req` 的参数,而内核有机会在内部重新启动系统调用(`-ERESTARTSYS`)?

Why does `nanosleep` need the argument of `req` while kernel has the chance to restart the system call again internally(`-ERESTARTSYS`)?

根据文档 (https://lwn.net/Articles/17744/),它说“nanosleep(),目前是该机制的唯一用户,只需要在重启块中保存唤醒时间,以及指向用户参数..".

如果是这样,为什么 nanosleep 需要一个类型为 struct timespec * 的参数 req

根据 linux 程序手册,“int nanosleep(const struct timespec *req, struct timespec *rem); 如果调用被信号处理程序中断,nanosleep() return s -1,设置errno为EINTR,将剩余时间写入rem指向的结构体,除非rem为NULL。"

我认为如果内核可以在内部重新启动系统调用('do_nanosleep'),就没有必要return再次向用户return你还剩下多少睡眠space。那是我无法理解的。

ERESTARTSYS 不应该从用户代码中看到,你是对的。它是内核重新启动调用本身的标志,或 return EINTR 到用户代码。请参阅 this discussion on the Linux Kernel Mailing List:

So which way is it supposed to be (so someone can patch things up |> to make it consistent): |> |> 1. User space should never see ERESTARTSYS from any system call

是的。内核要么将其转换为 EINTR,要么重新启动系统调用 当信号处理程序 returns.

this article 在 LWN.net

What happens, though, if a signal is queued for the process while it is waiting? In that case, the system call needs to abort its work and allow the actual delivery of the signal. For this reason, kernel code which sleeps tends to follow the sleep with a test like:

if (signal_pending(current))  return -ERESTARTSYS;

After the signal has been handled, the system call will be restarted (from the beginning), and the user-space application need not deal with "interrupted system call" errors. For cases where restarting is not appropriate, a -EINTR return status will cause a (post-signal) return to user space without restarting the system call.

我不认为这与 nanosleep(2) 参数有任何关系,只是在它使用这种机制的情况下。 The nanosleep docs 告诉你参数的作用,req 是你想睡多长时间,rem 是如果你早起还剩多长时间。

问题的标题与实际问题不完全相符。 @dsolimano 确实回答了标题。

但是,您似乎在问为什么调用 nanosleep() 的代码需要处理像 EINTR 这样的情况,如果 ERESTARTSYS 大概可以解决内核中的问题。

假设这是问题,答案是,这不是问题。

以下是 EINTR 的几个用例:

  1. 您想等待一定时间,但能够同步处理信号(即不在信号处理程序中)。例如,您正在等待 DB 初始化,但如果用户按下 Ctrl+C,您希望显示当前 DB 状态并继续等待。

  2. 您想等待信号,但超时。所以你超时睡觉,但如果 nanosleep() 返回 EINTR 你知道你有一个信号。

关于您的 "auxiliary questions",我会 tl;dr @dsolimano 的回答:

What are the differences between ERESTARTSYS and EINTR?

ERESTARTSYS 是内核实现细节,EINTR 是内核的一部分 API.

Is ERESTARTSYS only used in kernel or driver?

是的。

why does nanosleep() need an argument of type is struct timespec *req?

req 是休眠的纳秒数。你的意思可能是 rem。我上面概述的第一个用例就是一个例子。