通过fork()在C中创建多进程和模拟

通过fork()在C中创建多进程和模拟,c,unix,C,Unix,我想创建多个进程组,它们将调用不同的函数 我在下面写代码。 首先,我想得到以下输出 /叉子4 5 I am a child: 1 PID: 22330 I am a child2: 1 PID: 22334 I am a child: 2 PID: 22331 I am a child2: 5 PID: 22338 I am a child: 4 PID: 22333 I am a child: 3 PID: 22332 I am a child2: 2 PID: 22335 I

我想创建多个进程组,它们将调用不同的函数

我在下面写代码。 首先,我想得到以下输出

/叉子4 5

 I am a child: 1 PID: 22330
 I am a child2: 1 PID: 22334
 I am a child: 2 PID: 22331
 I am a child2: 5 PID: 22338
 I am a child: 4 PID: 22333
 I am a child: 3 PID: 22332
 I am a child2: 2 PID: 22335
 I am a child2: 4 PID: 22337
 I am a child2: 3 PID: 22336
"

如果这是您的问题,这意味着您的根进程比其子进程早退出。使用waitpid()[1]使根目录等待其子进程

[1]

LE:您将waitpid放在根进程而不是分叉进程中

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int forkChildren(int nChildren) {
    int i;
    pid_t pid;
    for (i = 1; i <= nChildren; i++) {
        pid = fork();
        if (pid == -1) {
            /* error handling here, if needed */
            return -1;
        }
        if (pid == 0) {
            printf("I am a child: %d PID: %d\n",i, getpid());
            sleep(5);
            return 1;
        }
    }
    return 0;
}

int forkChildren2(int nChildren) {
    int i;
    pid_t pid;
    for (i = 1; i <= nChildren; i++) {
        pid = fork();
        if (pid == -1) {
            /* error handling here, if needed */
            return -1;
        }
        if (pid == 0) {
            printf("I am a child2: %d PID: %d\n", i, getpid());
            sleep(2);
            return 1;
        }
    }
    return 0;
}

int main(int argc, char **argv) {
    int ret;
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <nChild> <nChild2>\n", getprogname());
        return EXIT_FAILURE;
    }
    ret = forkChildren(atoi(argv[1]));
    if (ret == 0)
        forkChildren2(atoi(argv[2]));
    // wait(...) for all pids here, if you wish
    return EXIT_SUCCESS;
}
LLE:好的,我终于得到了您想要做的事情,jweyrich观察得出了一个想法,它是这样的:返回子进程的PID数组,然后从根进程终止它们

主视图应如下所示:

int* child_pids
//mem allocation
forkChildren();
for each pid in child_pids
  kill(pid,*signal termination*)
forkChildren2()
如果这是您的问题,这意味着您的根进程比其子进程早退出。使用waitpid()[1]使根目录等待其子进程

[1]

LE:您将waitpid放在根进程而不是分叉进程中

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int forkChildren(int nChildren) {
    int i;
    pid_t pid;
    for (i = 1; i <= nChildren; i++) {
        pid = fork();
        if (pid == -1) {
            /* error handling here, if needed */
            return -1;
        }
        if (pid == 0) {
            printf("I am a child: %d PID: %d\n",i, getpid());
            sleep(5);
            return 1;
        }
    }
    return 0;
}

int forkChildren2(int nChildren) {
    int i;
    pid_t pid;
    for (i = 1; i <= nChildren; i++) {
        pid = fork();
        if (pid == -1) {
            /* error handling here, if needed */
            return -1;
        }
        if (pid == 0) {
            printf("I am a child2: %d PID: %d\n", i, getpid());
            sleep(2);
            return 1;
        }
    }
    return 0;
}

int main(int argc, char **argv) {
    int ret;
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <nChild> <nChild2>\n", getprogname());
        return EXIT_FAILURE;
    }
    ret = forkChildren(atoi(argv[1]));
    if (ret == 0)
        forkChildren2(atoi(argv[2]));
    // wait(...) for all pids here, if you wish
    return EXIT_SUCCESS;
}
LLE:好的,我终于得到了您想要做的事情,jweyrich观察得出了一个想法,它是这样的:返回子进程的PID数组,然后从根进程终止它们

主视图应如下所示:

int* child_pids
//mem allocation
forkChildren();
for each pid in child_pids
  kill(pid,*signal termination*)
forkChildren2()

根据您在@Cristina's answer上的评论,问题是它正在生成20个child2,而不是命令行参数中指定的5个。原因是由
forkChildren
创建的每个子进程都返回到
main
并调用
forkChildren2
。因为4(forkChildren)*5(forkChildren2)=20,加上父进程创建的5,所以得到了20(实际上是25)个child2

我将返回值添加到函数中(这两个函数都是为了保持它们的相似性),如果是子进程,则添加一个
if
条件以跳过
forkChildren2

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int forkChildren(int nChildren) {
    int i;
    pid_t pid;
    for (i = 1; i <= nChildren; i++) {
        pid = fork();
        if (pid == -1) {
            /* error handling here, if needed */
            return -1;
        }
        if (pid == 0) {
            printf("I am a child: %d PID: %d\n",i, getpid());
            sleep(5);
            return 1;
        }
    }
    return 0;
}

int forkChildren2(int nChildren) {
    int i;
    pid_t pid;
    for (i = 1; i <= nChildren; i++) {
        pid = fork();
        if (pid == -1) {
            /* error handling here, if needed */
            return -1;
        }
        if (pid == 0) {
            printf("I am a child2: %d PID: %d\n", i, getpid());
            sleep(2);
            return 1;
        }
    }
    return 0;
}

int main(int argc, char **argv) {
    int ret;
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <nChild> <nChild2>\n", getprogname());
        return EXIT_FAILURE;
    }
    ret = forkChildren(atoi(argv[1]));
    if (ret == 0)
        forkChildren2(atoi(argv[2]));
    // wait(...) for all pids here, if you wish
    return EXIT_SUCCESS;
}
#包括
#包括
#包括
智力儿童(智力儿童){
int i;
pid_t pid;

对于(i=1;i根据您在@Cristina的回答中所做的评论,问题是它分叉了20个child2,而不是命令行参数中指定的5个。原因是由
forkChildren
创建的每个子进程都返回到
main
并调用
forkChildren2
。您得到了20个(实际上是25个)child2因为4(forkChildren)*5(forkChildren2)=20,加上父进程创建的5

我将返回值添加到函数中(这两个函数都是为了保持它们的相似性),如果是子进程,则添加一个
if
条件以跳过
forkChildren2

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int forkChildren(int nChildren) {
    int i;
    pid_t pid;
    for (i = 1; i <= nChildren; i++) {
        pid = fork();
        if (pid == -1) {
            /* error handling here, if needed */
            return -1;
        }
        if (pid == 0) {
            printf("I am a child: %d PID: %d\n",i, getpid());
            sleep(5);
            return 1;
        }
    }
    return 0;
}

int forkChildren2(int nChildren) {
    int i;
    pid_t pid;
    for (i = 1; i <= nChildren; i++) {
        pid = fork();
        if (pid == -1) {
            /* error handling here, if needed */
            return -1;
        }
        if (pid == 0) {
            printf("I am a child2: %d PID: %d\n", i, getpid());
            sleep(2);
            return 1;
        }
    }
    return 0;
}

int main(int argc, char **argv) {
    int ret;
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <nChild> <nChild2>\n", getprogname());
        return EXIT_FAILURE;
    }
    ret = forkChildren(atoi(argv[1]));
    if (ret == 0)
        forkChildren2(atoi(argv[2]));
    // wait(...) for all pids here, if you wish
    return EXIT_SUCCESS;
}
#包括
#包括
#包括
智力儿童(智力儿童){
int i;
pid_t pid;


对于(i=1;我是否使用fflush(stdout)使打印更加有序?仍在尝试理解此处的问题。您的“问题”中缺少一些详细信息,例如主代码和问题所在。抱歉,我添加了缺少的代码。请更新您的问题,以提及您在下面的评论中描述的问题。是否使用fflush(stdout)使打印更有序?仍在试图理解此处的问题。您的“问题”中缺少一些详细信息,例如主代码和问题的原因。抱歉,我添加了缺少的代码。请更新您的问题,以提及您在下面的评论中描述的问题。我很困惑。我将把wait()fork()放在哪里将被调用两次,其中是根进程。我想得到4个child和5个child2它给了我20个child2这是因为所有
child
都是从
forkChildren
返回并运行
forkChildren2
。因此得到4*5=20。您必须更改fork的方式,或者只在父进程。我很困惑。我将把wait()fork()放在哪里将被调用两次,其中是根进程。我想得到4个child和5个child2它给了我20个child2这是因为所有
child
都是从
forkChildren
返回并运行
forkChildren2
。因此得到4*5=20。您必须更改fork的方式,或者只在父进程。谢谢你的帮助。它工作正常。如果我不想模拟孩子们。让他们以不同的顺序工作会怎么样。睡眠函数不能。我应该尝试使用信号量吗?你说的以不同的顺序工作是什么意思?线程是相互独立的。信号量用于同步。如果你给出一个好的描述,我可能会提供帮助说明你想做什么。事实上,我正在尝试编写多生产者单消费者模拟。在forkChildren中,会调用forkChildren2 cosume中的add_a()函数。如果我首先将此函数添加到由第一个fork的子函数数调用的wfunction中,然后使用由第二个fork的子函数数调用的函数。我想模拟类似的示例。(它的工作顺序可能不同)add_a()consumer_()add_a()add_a()add_a()consumer_a()谢谢,现在我明白了。你不必担心它们的执行顺序,但你需要信号量来通知消费者线程队列/列表/任何东西上有一个项目可用。每当生产者将一个项目放入容器时,它都会通知消费者唤醒并处理该项目。这样做可以避免处理器消耗循环。有关更多信息,请阅读“谢谢帮助”。它工作正常。如果我不想模拟孩子们,让他们以不同的顺序工作会怎么样。睡眠功能无法做到。我应该尝试使用信号量吗?你说的以不同的顺序工作是什么意思?线程是相互独立的。信号量用于同步。如果你愿意,我可能会提供帮助很好地描述一下你想要做什么。事实上,我正在尝试编写多生产者单消费者模拟。在forkChildren中,add_a()将在forkChildren2中被调用,cosume_a将被调用。如果我把这个函数放在第一位,添加一个由第一位的子函数的数量调用的wfunction