我试图了解在 Linux 上工作的 fork() 系统调用,这就是我编写以下 C 程序的原因:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char *argv[]) {
int n = atoi(argv[1]);
int i;
pid_t pid;
printf("Main: PID: %d, PPID:%d\n", getpid(), getppid());
for (i = 0; i <= n; i++) {
if (pid = fork()) {
pid = fork();
if (pid > 0) {
return (0);
}
if (i == n) {
printf("We are in the level %d and as a child PID:%d,PPID:%d\n", n,
getpid(), getppid());
}
}
}
return 0;
}
我所做的是:创建一个深度为 n 的进程树,其中每个进程创建 2 个子进程然后终止。最后我只是打印了最后一级的孩子 pid(所以如果 n=3,将有 8 个孩子,我想看看这些孩子的 pid)。根据我的理解,代码运行正常。(如果有任何错误,请纠正我)。
在这一点之后,我想改变我的代码来做这样的事情:
1
/ \
/ \
/ \
/ \
2 3
/ \ / \
/ \ / \
4 5 6 7
例如,如果 n=2。我想打印出如下内容:
Last Level Children: 1 2 4
Last Level Children: 1 2 5
Last Level Children: 1 3 6
Last Level Children: 1 3 7
为此,我编写了以下代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define SIZE 256
int main(int argc, char *argv[]) {
int n = atoi(argv[1]);
int i, k;
int m = 1;
int j = 0;
int arr[SIZE];
pid_t pid;
arr[j] = m;
m++;
j++;
for (i = 0; i <= n; i++) {
pid = getpid();
if (pid = fork()) {
arr[j] = m;
m++;
j++;
pid = fork();
if (pid > 0) {
arr[j] = m;
m++;
j++;
return (0);
}
if (i == n) {
printf("Process tree: ");
for (k = 0; k <= n; k++) {
printf("%d ", arr[k]);
}
printf("\n");
}
}
}
return 0;
}
但是当我运行程序时,我似乎得到了错误的结果。我在这里做错了什么?任何在正确方向上的帮助表示赞赏。
你的主要问题是你的孩子会继续他们父母的循环并创造更多你认为的孩子。我只能建议你读两次的曼努埃尔的fork()
。管理流程创建并不容易。您需要了解您的孩子会复制 (~) 其父母的所有状态。两者都将执行相同的代码,因此您需要注意在您的 fork 之后将执行哪些代码取决于fork()
.
EOF的评论是为了建议您不要fork()
在函数中使用更多。您会看到我的实现示例通过没有两个fork()
调用来保持简单,我将调用隔离在一个特定的地方。
这是您的第一个代码的正确实现:
#include <stdio.h>
#include <unistd.h>
static int create_two_child(int i, int n);
int main(void) { return create_two_child(0, 2); }
// tail recursive function: child will call this function to create two new
// child
static int create_two_child(int i, int n) {
if (i < n) { // we look our level
// debug output
printf("DEBUG: We are in the level %d and as a child PID:%d, PPID:%d\n", i,
getpid(), getppid());
fflush(stdout); // we don't want child print parent output
for (int j = 0; j < 2; j++) { // we loop to create two child
pid_t pid = fork();
if (pid == -1) { // error
perror("fork()");
return 1;
} else if (pid == 0) { // child
return create_two_child(i + 1, n); // we call ourself with i + 1 and
// stop function here wich return we
// don't want that child continue the
// loop
}
// parent will continue the loop to the number of child wanted
}
} else {
// if we are at max level we show our pid
printf("We are in the level max %d and as a child PID:%d, PPID:%d\n", i,
getpid(), getppid());
}
return 0;
}
您想要显示树的第二个实现:
#include <stdio.h>
#include <unistd.h>
static int create_two_child(size_t *backtrace, size_t id, size_t i, size_t n);
int main(void) {
// we create array to stock id
size_t backtrace[3];
size_t n = sizeof backtrace / sizeof *backtrace;
return create_two_child(backtrace, 1, 0, n);
}
// tail recursive function: child will call this function to create two new
// child
static int create_two_child(size_t *backtrace, size_t id, size_t i, size_t n) {
if (i < n) { // we look our level
for (size_t j = 0; j < 2; j++) { // we loop to create two child
pid_t pid = fork();
if (pid == -1) { // error
perror("fork()");
return 1;
} else if (pid == 0) { // child
backtrace[i] = id + 1;
// id * 2 cause we create 2 child each time
return create_two_child(backtrace, id * 2, i + 1,
n); // we call ourself with i + 1 and
// stop function here wich return we
// don't want that child continue the
// loop
}
id++;
// parent will continue the loop to the number of child wanted
}
} else {
// if we are at max level we show our backtrace
printf("Last Level Children: 1");
for (size_t j = 0; j < n; j++) {
printf(", %zu", backtrace[j]);
}
printf("\n");
}
return 0;
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句