C ++标准I / O和信号

时间:2019-06-11 05:31:35

标签: c++ posix

如果我调用不属于C ++标准库的read()之类的POSIX函数,则必须担心它会被信号中断并处理EINTR返回值。如果我基于this documentation调用诸如fread()之类的C ++标准库函数,则不会提及EINTR,因此标准库似乎对用户隐藏了此内容。我的理解正确吗,这是否适用于所有C ++标准库函数?

更新:因此,从响应中仍然不清楚的结论是,人们不能编写在每个平台上都能正常运行的标准C ++?我看到人们提到POSIX行为不是该标准的一部分,所以这很令人困惑。

3 个答案:

答案 0 :(得分:3)

  

如果我调用不属于C ++标准库的read()之类的POSIX函数,则必须担心它会被信号中断并处理EINTR返回值。

这对您的代码来说不是问题,因为:

  1. read可能会失败,因此无论如何都必须处理返回值和errno
  2. read可以进行部分读取,因此在阻塞模式下,您必须循环调用readerrno == EINTR只是在阻塞和非阻塞模式下重试呼叫的另一条件。

答案 1 :(得分:1)

POSIX covers fread也是很好的,因为C和C ++标准很少说明支持POSIX以外的信号。它说,在fgetc页面的一部分上,fread可能会提前返回(可能返回0),设置ferror,并将errno设置为EINTR。当然,如果信号导致短read,则C库无法检测到该信号,它将再次调用read,因此您不能依赖于响应及时的时尚。写作是类似的。

C ++标准库中很少有其他操作可以产生EINTR;不幸的是,POSIX并未涵盖C ++,因此对于sleep_for之类的不在C中的事物,尚无定论。

答案 2 :(得分:0)

fread()最初是libc中定义的C标准库<stdio.h>的一部分。 C ++标准库通过C库包装器fread()使相同的<cstdio>可用。

read()没有这样的包装器(也许是因为它会与istream的版本冲突),但是您仍然可以使用C库来调用它。您是正确的,read()来自特定于POSIX的extension <unistd.h>,它不是标准库的一部分,但是此后已被广泛实现,并且经常与{{1}一起分发}。

您还纠正了libc会在失败时设置read()的情况,并且其中一个错误可能是errno。另一方面,当EINTR失败时,可以使用no way来找出发生了什么错误,因此从技术上讲,您还纠正了在这种情况下fread()对用户隐藏的情况。实际上,EINTR如何处理任何平台特定的细节取决于实现。但是,要说这种模式适用于“所有C ++标准库函数”,您可能会感到有些牵强-您真的必须视情况进行检查。

如果要编写在每个平台上运行的“功能正常”的代码,请不要使用POSIX扩展。坚守fread()和朋友,接受一个事实,即跨平台的泛化意味着您可能无法获得特定于平台的详细信息,例如错误号。由于可能的错误是特定于平台的,因此无法通过通用方法知道是否应该重试。

herefread()read()之间差异的更多详细信息。