1

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

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

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

我认为,如果内核可以在内部重新启动系统调用('do_nanosleep'),则无需将您还剩下多长时间的睡眠时间再次返回给用户空间。那是我无法理解的。

4

2 回答 2

2

ERESTARTSYS永远不应该从用户代码中看到,你是对的。它是内核重新启动调用或将 EINTR 返回给用户代码的标志。请参阅Linux Kernel Mailing List 上的讨论

那么它应该是哪种方式(所以有人可以修补 |> 使其保持一致):|> |> 1. 用户空间不应该从任何系统调用中看到 ERESTARTSYS

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

或LWN.net 上的这篇文章

但是,如果一个信号在等待的过程中排队等待进程,会发生什么?在这种情况下,系统调用需要中止其工作并允许实际传递信号。出于这个原因,休眠的内核代码往往会在休眠之后进行如下测试:

if (signal_pending(current))  return -ERESTARTSYS;

处理完信号后,系统调用将重新启动(从头开始),用户空间应用程序无需处理“系统调用中断”错误。对于不适合重新启动的情况,-EINTR 返回状态将导致(后信号)返回用户空间而不重新启动系统调用。

我认为这与参数无关,nanosleep(2)除了它使用这种机制的掩护之外。 nanosleep 文档告诉您参数的作用,req您想睡多长时间,以及rem如果您早起,您还剩下多长时间。

于 2020-05-17T12:06:47.953 回答
2

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

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

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

以下是几个用例EINTR

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

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

关于您的“辅助问题”,我会 tl;@dsolimano 博士的回答:

ERESTARTSYS和 和有什么区别EINTR

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

ERESTARTSYS仅在内核或驱动程序中使用?

是的。

为什么nanosleep()需要类型为 is 的参数struct timespec *req

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

于 2020-05-19T06:45:23.670 回答