Fork() 子链
Fork() Child Chain
我有以下代码,它使用 fork()
创建定义数量的子线程:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#define NUM_THREADS 4
int main()
{
int i;
pid_t pid;
for(i = 0; i < NUM_THREADS; i++){ //Do this equal to the number of threads
pid = fork();//Use this to avoid multiple forking
if(pid == 0){ //If it's a child process
printf("Hello World! Greetings from PID: %ld! :D\n", (long)getpid()); //getpid returns the pid of the process
exit(0); //Exit the process
}else if(pid == -1){
printf("Oh no! Could not fork! :( Exiting!\n");
return 0;
}
}
int status;
for(i = 0; i < NUM_THREADS; i++){
wait(&status);//wait until all the children processes have finished.
}
printf("All done! I am the parent process! My PID is: %ld if you were curious! \n", (long)getpid());
return 0;
}
这是作为示例提供给我们的。
它的输出是这样的:
Hello World! Greetings from PID: 118358! :D
Hello World! Greetings from PID: 118359! :D
Hello World! Greetings from PID: 118360! :D
Hello World! Greetings from PID: 118362! :D
我想要做的是让父进程创建一个子进程,而不是让 1 个父进程有多个子进程,子进程创建一个子进程,依此类推定义的线程数。我该怎么做?
您的示例代码使用 fork()
的 return 值来区分 parent 和 child。它继续在 parent 中迭代(假设 fork()
没有报告错误),并且它 exit()
没有在 child 中迭代(在发出一些输出之后)。这完全是例行公事。
你打算做的事情并没有太大的不同;你描述的主要只是交换parent和child的角色。事实上,你有一个更简单的工作,因为每个 parent 只需要 wait()
一个 child。它可以在循环内部或外部执行此操作,前提是如果最后一个 child wait()
s 那么它应该期望调用指示错误,因为 child 没有任何 child任其自有。但是,如果 parent 不是来自循环内部的 exit()
或 return
,那么它确实需要突破而不是进一步迭代。
此任务与将迭代解决方案转换为递归解决方案相同。第一步是删除 for
循环。然后修改child代码,使每个child:
- 打印其消息
- 更新计数变量,如果计数小于最大值
- 分叉一个新的 child
- 等待其 child
关键是每个 child 都会得到它的 parent 变量的副本,所以如果 child 更新一个计数变量,然后分叉,新的 child 将看到更新后的计数。
首先,您使用的术语 "thread" 在这种情况下是不合适的。
Fork 表示 "creating process" 而不是 "threads".
您可以使用递归解决方案,但您必须记住,每个创建进程的进程都应等待 return 状态以避免 Zombie Process。在进程之间不使用任何共享变量的情况下,您可以使用单个变量计数器,该计数器会在每次分叉时递增。但是一旦计数器变量达到最大值,"youngest" 进程,我的意思是最后创建的进程应该退出,一个接一个的进程将退出。
这是一个运行良好的简单代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define NUM_PROCESS 5
int counter = 0;
void child_func()
{
pid_t pid;
if (counter < NUM_PROCESS) {
counter++;
pid = fork();
if (pid < 0) {
printf("fork failed counter = %d\n", counter);
}
else if (pid == 0) {
printf("Hello world ! Greetings from pid %ld\n", (long)getpid());
if (counter == NUM_PROCESS) {
exit(0);
}
else {
child_func();
}
}
else {
long var = pid;
wait(&pid);
printf("My pid is %ld and i am the parent of %ld child, i exit\n", (long)getpid(), var);
exit(0);
}
}
}
int main(void)
{
pid_t pid;
pid = fork();
if (pid < 0) {
printf("Fork failed %d\n", counter);
return -1;
}
if (pid == 0) {
child_func();
}
else {
wait(&pid);
}
return 0;
}
See output
我有以下代码,它使用 fork()
创建定义数量的子线程:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#define NUM_THREADS 4
int main()
{
int i;
pid_t pid;
for(i = 0; i < NUM_THREADS; i++){ //Do this equal to the number of threads
pid = fork();//Use this to avoid multiple forking
if(pid == 0){ //If it's a child process
printf("Hello World! Greetings from PID: %ld! :D\n", (long)getpid()); //getpid returns the pid of the process
exit(0); //Exit the process
}else if(pid == -1){
printf("Oh no! Could not fork! :( Exiting!\n");
return 0;
}
}
int status;
for(i = 0; i < NUM_THREADS; i++){
wait(&status);//wait until all the children processes have finished.
}
printf("All done! I am the parent process! My PID is: %ld if you were curious! \n", (long)getpid());
return 0;
}
这是作为示例提供给我们的。 它的输出是这样的:
Hello World! Greetings from PID: 118358! :D
Hello World! Greetings from PID: 118359! :D
Hello World! Greetings from PID: 118360! :D
Hello World! Greetings from PID: 118362! :D
我想要做的是让父进程创建一个子进程,而不是让 1 个父进程有多个子进程,子进程创建一个子进程,依此类推定义的线程数。我该怎么做?
您的示例代码使用 fork()
的 return 值来区分 parent 和 child。它继续在 parent 中迭代(假设 fork()
没有报告错误),并且它 exit()
没有在 child 中迭代(在发出一些输出之后)。这完全是例行公事。
你打算做的事情并没有太大的不同;你描述的主要只是交换parent和child的角色。事实上,你有一个更简单的工作,因为每个 parent 只需要 wait()
一个 child。它可以在循环内部或外部执行此操作,前提是如果最后一个 child wait()
s 那么它应该期望调用指示错误,因为 child 没有任何 child任其自有。但是,如果 parent 不是来自循环内部的 exit()
或 return
,那么它确实需要突破而不是进一步迭代。
此任务与将迭代解决方案转换为递归解决方案相同。第一步是删除 for
循环。然后修改child代码,使每个child:
- 打印其消息
- 更新计数变量,如果计数小于最大值
- 分叉一个新的 child
- 等待其 child
关键是每个 child 都会得到它的 parent 变量的副本,所以如果 child 更新一个计数变量,然后分叉,新的 child 将看到更新后的计数。
首先,您使用的术语 "thread" 在这种情况下是不合适的。 Fork 表示 "creating process" 而不是 "threads".
您可以使用递归解决方案,但您必须记住,每个创建进程的进程都应等待 return 状态以避免 Zombie Process。在进程之间不使用任何共享变量的情况下,您可以使用单个变量计数器,该计数器会在每次分叉时递增。但是一旦计数器变量达到最大值,"youngest" 进程,我的意思是最后创建的进程应该退出,一个接一个的进程将退出。
这是一个运行良好的简单代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define NUM_PROCESS 5
int counter = 0;
void child_func()
{
pid_t pid;
if (counter < NUM_PROCESS) {
counter++;
pid = fork();
if (pid < 0) {
printf("fork failed counter = %d\n", counter);
}
else if (pid == 0) {
printf("Hello world ! Greetings from pid %ld\n", (long)getpid());
if (counter == NUM_PROCESS) {
exit(0);
}
else {
child_func();
}
}
else {
long var = pid;
wait(&pid);
printf("My pid is %ld and i am the parent of %ld child, i exit\n", (long)getpid(), var);
exit(0);
}
}
}
int main(void)
{
pid_t pid;
pid = fork();
if (pid < 0) {
printf("Fork failed %d\n", counter);
return -1;
}
if (pid == 0) {
child_func();
}
else {
wait(&pid);
}
return 0;
}
See output