我正在研究使用 fork() exec() wait() 的 ac 程序。第一个进程有这个代码:
int main(int argc, const char * argv[]) {
// insert code here...
int pid = fork();
if(pid == 0){
//we are the child process.
execlp("/Users/matthewdunn/Library/Developer/Xcode/DerivedData/PA2-hekivoaqvsegnggdvcfguasystig/Build/Products/Debug/Checker", "Checker", "1", "5", (char*) NULL);
}else{
//we are the parent process.
printf("Coordinator: forked process with ID ");
printf("%d\n", pid);
printf("Coordinator: waiting for process [");
printf("%d", pid);
printf("]\n");
int status;
waitpid(pid, &status, 0);
int returned = WEXITSTATUS(status);
printf("Coordinator: child process ");
printf("%d", pid);
printf(" returned ");
printf("%d", returned);
printf(".\n");
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
第二个过程有代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
void printProcessInfo(){
printf("Checker process [");
printf("%d", getpid());
printf("]: ");
}
int main(int argc, const char * argv[]) {
// insert code here...
printProcessInfo();
printf("Starting.\n");
int arg1;
int arg2;
arg1 = atoi(argv[1]);
arg2 = atoi(argv[2]);
if((arg2 % arg1) > 0){
printProcessInfo();
printf("%d", arg2);
printf(" *IS NOT* divisible by ");
printf("%d\n", arg1);
printProcessInfo();
printf("Returning 0.\n");
return 0;
}
else{
printProcessInfo();
printf("%d", arg2);
printf(" *IS* divisible by ");
printf("%d\n", arg1);
printProcessInfo();
printf("Returning 1.\n");
return 1;
}
}
Run Code Online (Sandbox Code Playgroud)
由于我无法弄清楚的原因,父函数总是读取 0 的返回值,即使我得到下降的输出:
Coordinator: forked process with ID 2865
Coordinator: waiting for process [2865]
Checker process [2865]: Starting.
Checker process [2865]: 5 *IS* divisible by 1
Checker process [2865]: Returning 1.
Coordinator: child process 2865 returned 0.
Program ended with exit code: 0
Run Code Online (Sandbox Code Playgroud)
第二个过程显然返回 1,但我的状态仍然是 0。我不知道是什么原因造成的。我正在使用 Xcode 编写此代码。WEXITSTATUS(status) 总是返回 0 有什么原因吗?
这里:
int* status;
waitpid(pid, status, 0);
Run Code Online (Sandbox Code Playgroud)
您的指针status从未设置为实际指向任何内容。您需要一个实际int值来存储值:
int status;
waitpid(pid, &status, 0);
Run Code Online (Sandbox Code Playgroud)
如果您对退出状态特别感兴趣,您还应该检查以确保它实际上正常退出。可以说,就像所有系统调用一样,waitpid()在尝试对该值执行任何操作之前,您应该检查返回的错误。
共:
int status;
if ( waitpid(pid, &status, 0) != -1 ) {
if ( WIFEXITED(status) ) {
int returned = WEXITSTATUS(status);
printf("Exited normally with status %d\n", returned);
}
else if ( WIFSIGNALED(status) ) {
int signum = WTERMSIG(status);
printf("Exited due to receiving signal %d\n", signum);
}
else if ( WIFSTOPPED(status) ) {
int signum = WSTOPSIG(status);
printf("Stopped due to receiving signal %d\n", signum);
}
else {
printf("Something strange just happened.\n");
}
}
else {
perror("waitpid() failed");
exit(EXIT_FAILURE);
}
Run Code Online (Sandbox Code Playgroud)
这是一个工作示例:
parent.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
int pid = fork();
if ( pid == -1 ) {
perror("fork() failed");
exit(EXIT_FAILURE);
}
else if ( pid == 0 ) {
execlp("./child", "child", "1", "5", (char *)NULL);
perror("execlp() failed");
exit(EXIT_FAILURE);
} else {
printf("Coordinator: forked and waiting for process %d\n", pid);
int status;
if ( waitpid(pid, &status, 0) != -1 ) {
if ( WIFEXITED(status) ) {
int returned = WEXITSTATUS(status);
printf("Exited normally with status %d\n", returned);
}
else if ( WIFSIGNALED(status) ) {
int signum = WTERMSIG(status);
printf("Exited due to receiving signal %d\n", signum);
}
else if ( WIFSTOPPED(status) ) {
int signum = WSTOPSIG(status);
printf("Stopped due to receiving signal %d\n", signum);
}
else {
printf("Something strange just happened.\n");
}
}
else {
perror("waitpid() failed");
exit(EXIT_FAILURE);
}
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
child.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
void printProcessInfo()
{
printf("Checker process [%d]: ", getpid());
}
int main(int argc, char * argv[])
{
printProcessInfo();
printf("Starting.\n");
int arg1, arg2;
arg1 = atoi(argv[1]);
arg2 = atoi(argv[2]);
if ( (arg1 != 0) && (arg2 % arg1) > 0 ){
printProcessInfo();
printf("%d *IS NOT* divisible by %d\n", arg2, arg1);
printProcessInfo();
printf("Returning 0.\n");
return 0;
}
else {
printProcessInfo();
printf("%d *IS* divisible by %d\n", arg2, arg1);
printProcessInfo();
printf("Returning 1.\n");
return 1;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
带输出:
paul@horus:~/src/sandbox/ft$ ./parent
Coordinator: forked and waiting for process 40330
Checker process [40330]: Starting.
Checker process [40330]: 5 *IS* divisible by 1
Checker process [40330]: Returning 1.
Exited normally with status 1
paul@horus:~/src/sandbox/ft$
Run Code Online (Sandbox Code Playgroud)
编辑:如果您在 Xcode 中构建它,发生的情况是您的waitpid()呼叫被信号中断(很可能SIGCHLD)。在这种情况下,您只需要重新启动它,如下所示:
int status;
while ( waitpid(pid, &status, 0) == -1 ) {
if (errno == EINTR) {
printf("Parent interrrupted - restarting...\n");
continue;
}
else {
perror("waitpid() failed");
exit(EXIT_FAILURE);
}
}
if ( WIFEXITED(status) ) {
int returned = WEXITSTATUS(status);
printf("Exited normally with status %d\n", returned);
}
else if ( WIFSIGNALED(status) ) {
int signum = WTERMSIG(status);
printf("Exited due to receiving signal %d\n", signum);
}
else if ( WIFSTOPPED(status) ) {
int signum = WSTOPSIG(status);
printf("Stopped due to receiving signal %d\n", signum);
}
else {
printf("Something strange just happened.\n");
}
Run Code Online (Sandbox Code Playgroud)