关于何时使用的一般评论errno
没有设置标准 C 或 POSIX 库函数errno
为零。根据以下内容打印错误消息errno
when fd
不为NULL是不合适的;错误编号不是来自popen()
(或者没有设置,因为popen()
失败的)。印刷res
after pclose()
还可以;添加strerror(errno)
遇到同样的问题(信息errno
可能完全无关)。您可以设置errno
在调用函数之前清零。如果该函数返回失败指示,则可能需要查看errno
(查看函数的规范——它是否被定义为设置errno
失败?)。然而,errno
即使成功,也可以通过函数设置为非零。用于设置 Solaris 标准 I/Oerrno = ENOTTY
如果输出流未连接到终端,即使操作成功;也许现在仍然如此。和 Solaris 设置errno
即使成功也是完全合法的;看看才是合法的errno
如果 (1) 该功能报告故障并且 (2) 该功能被记录为设置errno
(通过 POSIX 或系统手册)。
See C11 §7.5 错误<errno.h> ¶3:
The value of errno in the initial thread is zero at program startup (the initial value of errno in other threads is an indeterminate value), but is never set to zero by any library function.202) The value of errno may be set to nonzero by a library function call whether or not there is an error, provided the use of errno is not documented in the description of the function in this International Standard.
202) Thus, a program that uses errno
for error checking should set it to zero before a library function call, then inspect it before a subsequent library function call. Of course, a library function can save the value of errno
on entry and then set it to zero, as long as the original value is restored if errno
's value is still zero just before the return.
POSIX 类似(errno):
许多函数都提供错误号errno
,其类型为int
并定义在<errno.h>
。的价值errno
仅应在调用明确声明要设置的函数之后定义,直到下一个函数调用更改它或应用程序为其分配值为止。的价值errno
仅当函数的返回值表明它有效时才应检查它。应用程序应获得以下定义errno
通过包含<errno.h>
。 POSIX.1-2017 本卷中的函数不得将 errno 设置为 0。errno
成功调用函数后未指定,除非该函数的描述指定errno
不得修改。
popen()
and pclose()
POSIX 规范popen()并不是很有帮助。只有一种情况可以popen()
'必须失败';其他一切都是“可能会失败”。
然而,详细信息为pclose()更有帮助,包括:
如果命令语言解释器无法执行,则返回子终止状态pclose()
应如同命令语言解释器终止使用exit(127)
or _exit(127)
.
and
成功返回后,pclose()
应返回命令语言解释器的终止状态。否则,pclose()
应返回 -1 并设置 errno 来指示错误。
这意味着pclose()
返回它收到的值waitpid()
— 调用的命令的退出状态。注意,必须使用waitpid()
(或同等的选择性功能——寻找wait3()
and wait4()
在 BSD 系统上);它无权等待除由创建的子进程之外的任何其他子进程popen()
对于这个文件流。有关于的处方pclose()
必须确保子进程已退出,即使某些其他函数在此期间等待已死亡的子进程,从而导致系统丢失由popen()
.
如果将十进制 32512 解释为十六进制,则会得到 0x7F00。如果你使用了WIFEXITED
and WEXITSTATUS
宏来自<sys/wait.h>
就这样,你会发现退出状态是127
(因为0x7F
is 127
十进制,退出状态编码在返回状态的高位中waitpid()
.
int res = pclose(fd);
if (WIFEXITED(res))
printf("Command exited with status %d (0x%.4X)\n", WEXITSTATUS(res), res);
else if (WIFSIGNALED(res))
printf("Command exited from signal %d (0x%.4X)\n", WTERMSIG(res), res);
else
printf("Command exited with unrecognized status 0x%.4X\n", res);
请记住0
是表示成功的退出状态;其他任何内容通常都表明存在某种错误。您可以进一步分析退出状态来查找127
或中继信号等。您不太可能获得“已发出信号”状态或无法识别的状态。
popen()
告诉你孩子失败了。
当然,有可能执行的命令实际上以状态 127 退出;这不可避免地会造成混乱,唯一的解决方法是避免退出状态在 126 到 128 +“最大信号数”范围内(如果有 63 个已识别信号,则可能意味着 126 .. 191)。价值126
POSIX 也使用它来报告 shebang 中指定的解释器(#!/usr/bin/interpreter
) 丢失(与要执行的程序不可用相反)。是否返回pclose()
是一个单独的讨论。信号报告是由 shell 完成的,因为否则没有(简单)方法来报告孩子因信号而死亡。