关于创建 N 个子进程 和 fork 函数的理解

本文详细解析了C语言中使用fork函数创建多个子进程的代码示例。通过for循环和条件判断,确保父进程创建指定数量的子进程后退出。每个进程根据fork函数的返回值执行不同的操作,避免无限递归。示例中展示了如何通过sleep函数限制进程执行顺序,以及如何利用execl函数替换子进程执行新程序。
摘要由CSDN通过智能技术生成

关于创建 N 个子进程 和 fork 函数的理解

有如下 代码 创建 N个 子进程

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(void)
{
    int i;
    pid_t pid;
    printf("xxx\n");
    
    for(i = 0; i<5; i++){
        pid = fork();
        if(pid == -1){
            perror("fork error;");
            exit(1);
        }else if(pid == 0){
            break;
          
    //只创建子进程,不调用fork 函数 .一旦创建出子进程,立马退出for 循环执行for循环后面的语句,直到return 0; 结束这一个子进程。
        }else{
        printf("father , i=%d,pid = %u\n",i,getpid());   父进程
        }}
    
sleep(i);
    printf("===========pid = %u\n",pid);
    if(i < 5){
       
        printf("I am %d child , i=%d,pid = %u\n",i+1,i,getpid());
    }else{   // i= 5 时 创建的是父进程
   
        printf("I am  father , i=%d,pid = %u\n",i,getpid());
    }    return 0;
}

运行结果

xxx
father , i=0,pid = 19388
father , i=1,pid = 19388
father , i=2,pid = 19388
father , i=3,pid = 19388
father , i=4,pid = 19388
===========pid = 0
I am 1 child , i=0,pid = 19389
===========pid = 0
I am 2 child , i=1,pid = 19390
===========pid = 0
I am 3 child , i=2,pid = 19391
===========pid = 0
I am 4 child , i=3,pid = 19392
===========pid = 0
I am 5 child , i=4,pid = 19393
===========pid = 19393
I am  father , i=5,pid = 19388

可以看到 不仅 子进程 创建了 5个 , 父进程也有六次打印信息 (但父进程的个数只有 一个 ,因为 这六个 父进程的进程pid 相同)。
而且 我们隔离了 子进程使用 fork 函数(使用 break 语句 跳出循环 )。
我们要明白fork 函数 有两个返回值
先看 for 循环逻辑,如果是fork 函数 返回是 0 ,为子进程 ,就break .执行 for 循环之后的语句,return 0 ;结束
如果是fork 函数 返回 值 大于 0 ,为父 进程,i ++ ,又会执行 fork 函数 ,在i < 5,之前是不会跳出for循环的。
所以,后面可以使用 if( i< 5) 就是 子进程 跳出了循环。
而当 if (i >=5 ) 就是父进程 跳出循环,而且 并未执行 fork 语句,所以 i =5 就是一个干净的 父进程。.
在这里插入图片描述
如图 可见 当 n =6 (i=6)的时候 , 并未 调用fork 函数,只有一个 parent 进程。
这个过程中 parent 被打印 了六次,但全是一个 parent 进程(pid 相同),而子进程确是真创建了 五 个。 { 注意图上 是从 n =1 开始的 而代码里是 n=0 开始的,所以 n= 6 和 i=5 相同}
顺便一提,这六个进程 (父子进程) 如果 不使用 sleep 限制 ,他们是相等 地位 获得处理机的。所以 会 发生 抢占处理机

第二种 创建 多个子进程的方法相同

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
 
int main(void)
{
	pid_t pid;
	int i;
	for (i = 0; i < 3; i++)
	{
		pid = fork();
        /*
        这个地方要判断pid是否为0是因为fork函数的实现原理,fork函数最后的return 0是子进程进行 
        的,所以进入这个判断的是子进程,而子进程返回的pid就是0,如果这个地方不加上该判断,子进 
        程也会进入该for循环来创造进程,子又生孙孙又生子,而我们只希望父进程来创建三个子进程, 
        所以加上了该判断
        */
		if (pid == 0)
		{
			break;
		}
	}
     首先父进程进入下面的三个判断,因为父进程pid大于0,所以会进入第一个判断,打印出父进程的 
    pid,然后我们用while循环一直sleep(1)来阻塞父进程,让子进程进入三个判断,因为子进程的pid 
    是0,所以会进入第二个判断,第一个子进程先进入判断,进入if(i == 0)用execl函数重载来实现功 
    能,后面执行同样的步骤,也是父进程先进入判断, 之后两个进程分别进入判断

	if (pid > 0)
	{
		printf("parent pid %d\nsleeping..\n", getpid());
		while (1)
		{
			sleep(1);//如果检测到父进程创建 ,就阻塞掉父进程执行

		}
	}
	else if (pid == 0)
	{
		if (i == 0)
		{
			printf("child no.%d pid %d exec firefox..\n", i, getpid());
			
		}
		if (i == 1)
		{
			printf("child no.%d pid %d touch files..\n", i, getpid());
		
		}
		if (i == 2)
		{
			printf("child no.%d pid %d exec ls -l..\n", i, getpid());
		}
	}
 
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丁金金

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值