这里是Total C菜鸟,正在寻求一些有关
fork()
的帮助。我不知道为什么它会打印子进程 2 代码两次。我相信这与 sleep
调用有关,因为它之前工作正常。
Child Process 2
Process ID: 31973
Parent Process ID: 1
Child Process 1
Process ID: 31972
Parent Process ID: 1
Child Process 2
Process ID: 31974
Parent Process ID: 1
#define _XOPEN_SOURCE // required for cuserid to work
// includes
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <time.h>
int main(void) {
getP0Info();
putenv("WHALE=7");
forkProcesses();
return 0;
}
// Prints an error message and exits if one occurs. Else, returns the system call value.
int print_if_err(int syscall_val, const char* syscall_name) {
if (syscall_val < 0) {
perror(syscall_name);
exit(errno);
} else {
//No syscall error; we can return
return syscall_val;
}
}
void forkProcesses() {
pid_t child1_pid = print_if_err(fork(), "fork");
if (child1_pid == 0) {
printf("\nChild Process 1\n");
printf("Process ID: %d\n", getpid());
printf("Parent Process ID: %d\n", getppid());
sleep(1);
int whale = atoi(getenv("WHALE"));
printf("C1: %d\n", whale);
}
pid_t child2_pid = print_if_err(fork(), "fork");
if (child2_pid == 0) {
printf("\nChild Process 2\n");
printf("Process ID: %d\n", getpid());
printf("Parent Process ID: %d\n", getppid());
}
}
这是因为即使 if 语句结束,子进程 1 仍会继续执行。您需要显式调用
_exit()
或类似的方法来防止这种情况:
void forkProcesses() {
pid_t child1_pid = print_if_err(fork(), "fork");
if (child1_pid == 0) {
printf("\nChild Process 1\n");
printf("Process ID: %d\n", getpid());
printf("Parent Process ID: %d\n", getppid());
sleep(1);
int whale = atoi(getenv("WHALE"));
printf("C1: %d\n", whale);
_exit(0);
}
pid_t child2_pid = print_if_err(fork(), "fork");
if (child2_pid == 0) {
printf("\nChild Process 2\n");
printf("Process ID: %d\n", getpid());
printf("Parent Process ID: %d\n", getppid());
}
}
理论上,
return
或exit
也会避免运行其余代码,但这样做是危险的:如果使用exit
退出子进程,stdio缓冲区将在子进程和atexit
处理程序中刷新也跑吧如果分叉之前的任何数据保留在这些缓冲区中,则会被打印两次。
通过使用
_exit()
终止分叉可以避免这种情况。