【问题标题】:Does the linux system call read(fd, buf, count) return less than count when fd is a regular file?当 fd 是常规文件时,linux 系统调用 read(fd, buf, count) 返回是否小于 count?
【发布时间】:2015-04-14 14:03:06
【问题描述】:

当我们在Linux上调用read(fd, buf, count)时,系统(函数)调用的返回值除了到文件末尾的字节数较少的情况外,是否可以小于count?

我在手册页上查了一下,上面写着

"成功时,返回读取的字节数(零表示文件结束),文件位置由此前进 数字。如果此数字小于请求的字节数,则不是错误;例如,这可能会发生 因为现在实际上可用的字节更少(可能是因为我们接近文件结尾,或者因为我们正在阅读 来自管道或终端),或因为 read() 被信号中断。”

所以这是我的问题: 普通文件上的read() 怎么会被信号打断?通过什么可能的信号?

【问题讨论】:

  • 它不应该是open(fd, buf, count) ... :-)
  • 为 SIGINT 实现信号处理程序,然后发送 SIGINT
  • 您可以发送SIGINT 到某个软挂载的NFS 文件读取。
  • 请注意,如果您考虑 count 的小值而不是大值,这是一个更有趣的问题。
  • 即使一个特定的内核确实保证它不会返回更少的数据,你为什么要做出这样的假设? read() 函数为您提供返回的字节数。用它。当一个函数返回一个值或一个可能的错误代码时,就像它可能返回任何东西一样进行编码。不要假设任何事情。

标签: c linux system-calls


【解决方案1】:

是的,read() 可以被信号中断。但当进程从属于文件系统上的文件的描述符中读取时则不然。

当进程在文件中调用read() 时,它会进入所谓的不间断睡眠。在这种模式下,直到系统调用完成,进程才会处理任何信号。可能是因为某些错误,或者是在读取请求的数据时。

注意:当进程处于不间断睡眠时,您甚至无法使用 SIGKILL 信号终止它。或者换句话说,kill $pid -9 将不起作用。

在这个问题中有一个不间断睡眠的解释: What is an uninterruptable process?

进一步注意:当硬盘驱动器发生故障以及所有进程尝试将数据写入该磁盘(文件系统)或从中读取被卡住并且除了重新启动系统之外无法通过任何方式被杀死。对于通过网络装载的卷(例如 NFS)也是如此。

编辑:正如 psmears 所指出的,如果从卷上通过 NFS 挂载的文件读取,read() 可能会被中断iff em> intr 指定了挂载选项。

【讨论】:

  • 这是错误的:在某些情况下,文件系统文件上的read()可以被中断。经典示例是使用 intr 选项挂载的 NFS 挂载。
  • @psmears,请仔细阅读文档:intr — Allows NFS requests to be interrupted if the server goes down or cannot be reached。这意味着操作系统(驱动程序)不会无限期地等待。这与从已安装卷中读取/写入文件的进程发送一些信号会导致系统调用被中断是不同的。
  • 不,您更仔细地阅读了文档;-) soft 表示驱动程序将超时。 intr(取决于内核版本)允许用户中断(信号)进程。来自文档:“如果指定了 intr,则如果正在进行的 NFS 操作被信号中断,系统调用将返回 EINTR。”
【解决方案2】:

This documentation page 指定哪些调用可以被信号中断,read() 在列表中。您必须在 Linux 中启用此行为(使用 SA_RESTART),默认情况下不启用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-13
    • 2011-02-02
    • 2023-01-19
    相关资源
    最近更新 更多