最近,在阅读有关linux编程的书时,我收到了一条消息:
给_exit()的status参数定义了进程的终止状态,当调用wait()时,该进程的父进程可以使用该进程。虽然定义为int,但实际上只有父8的状态的底部8位可用。并且仅建议使用
0 ~ 127
,因为由于某种原因,128~255可能在shell中混淆。由于-1
将在2的补码中成为255
。
以上是关于子进程的退出状态。
我的问题是:
0 ~ 127
是否合理或可行?因为我确实使用-1
作为返回值来指示错误,所以我今后应该更正。更新 - 状态由wait()/ waitpid()获取:
我在书中读到了更多的chps(TLPI),并发现在返回状态中有更多技巧。 wait()/ waitpid()值得一提,我应该在提出问题之前阅读更多的chps。无论如何,我自己添加一个答案来描述它,以防将来可能对某人有所帮助。
答案 0 :(得分:4)
为什么父进程只获得子进程的8位退出状态?
因为POSIX says so。 POSIX之所以如此,是因为原始Unix的工作方式,以及许多操作系统都是从它衍生出来的,并在它继续工作之后建模。
正常功能的返回值怎么样?
他们是无关的。返回任何合理的东西。 -1
与任何其他值一样好,实际上是在大量标准C和POSIX API中指示错误的标准方法。
答案 1 :(得分:1)
来自@n.m的回答。很好。
但是后来,我在书中读到了更多的chps(TLPI),并发现在返回状态中还有更多技巧。 wait()/ waitpid()值得一提,这可能是为什么子进程在退出时不能使用完整位的另一个重要或根本原因。
basicly:
状态的字节使用情况:
event byte 1 byte 0 ============================================================ * normal termination exit status (0 ~ 255) 0 * killed by signal 0 termination signal (!=0) * stopped by signal stop signal 0x7F * continued by signal 0xFFFF *
剖析返回状态:
header 'sys/wait.h', defines a set of macros that help to dissect a wait status, macros: * WIFEXITED(status) return true if child process exit normally, * * WIFSIGNALED(status) return true if child process killed by signal, * WTERMSIG(status) return signal number that terminate the process, * WCOREDUMP(status) returns ture if child process produced a core dump file, tip: this macro is not in SUSv3, might absent on some system, thus better check whether it exists first, via: #ifdef WCOREDUMP // ... #endif * * WIFSTOPPED(status) return true if child process stopped by signal, * WSTOPSIG(status) return signal number that stopp the process, * * WIFCONTINUED(status) return true if child process resumed by signal SIGCONT, tip: this macro is part of SUSv3, but some old linux or some unix might didn't impl it, thus better check whether it exists first, via: #ifdef WIFCONTINUED // ... #endif *
<强> wait_status_test.c 强>
// dissect status returned by wait()/waitpid()
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>
#define SLEEP_SEC 10 // sleep seconds of child process,
int wait_status_test() {
pid_t cpid;
// create child process,
switch(cpid=fork()) {
case -1: // failed
printf("error while fork()\n");
exit(errno);
case 0: // success, child process goes here
sleep(SLEEP_SEC);
printf("child [%d], going to exit\n",(int)getpid());
_exit(EXIT_SUCCESS);
break;
default: // success, parent process goes here
printf("parent [%d], child created [%d]\n", (int)getpid(), (int)cpid);
break;
}
// wait child to terminate
int status;
int wait_flag = WUNTRACED | WCONTINUED;
while(1) {
if((cpid = waitpid(-1, &status, wait_flag)) == -1) {
if(errno == ECHILD) {
printf("no more child\n");
exit(EXIT_SUCCESS);
} else {
printf("error while wait()\n");
exit(-1);
}
}
// disset status
printf("parent [%d], child [%d] ", (int)getpid(), (int)cpid);
if(WIFEXITED(status)) { // exit normal
printf("exit normally with [%d]\n", status);
} else if(WIFSIGNALED(status)) { // killed by signal
char *dumpinfo = "unknow";
#ifdef WCOREDUMP
dumpinfo = WCOREDUMP(status)?"true":"false";
#endif
printf("killed by signal [%d], has dump [%s]\n", WTERMSIG(status), dumpinfo);
} else if(WIFSTOPPED(status)) { // stopped by signal
printf("stopped by signal [%d]\n", WSTOPSIG(status));
#ifdef WIFCONTINUED
} else if(WIFCONTINUED(status)) { // continued by signal
printf("continued by signal SIGCONT\n", WSTOPSIG(status));
#endif
} else { // this should never happen
printf("unknow event\n");
}
}
return 0;
}
int main(int argc, char *argv[]) {
wait_status_test();
return 0;
}
<强>编译:强>
gcc -Wall wait_status_test.c
<强>执行:强>
./a.out
并等待它正常终止,在fork(),./a.out
,然后kill -9 <child_process_id>
才能完成睡眠,./a.out
,然后kill -STOP <child_process_id>
在完成睡眠之前,然后kill -CONT <child_process_id>
恢复它,