Linux学习总结(八)fork函数循环创建n个子进程

fork函数

fork函数用来创建一个子进程。

pid_t fork(void);

失败返回-1,成功返回:

  • 父进程返回子进程的ID(非负)
  • 子进程返回0

pid_t类型表示进程ID,但为了标识-1,它是有符号整数。(0不是有效进程ID,init最小,为1)
注意返回值,不是fork函数能返回两个值,而是fork后,fork函数变为两个,父子需各自返回一个

循环创建n个子进程

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
    
    
    int i;						//默认创建5个子进程
    pid_t pid;
    printf("xxxxxxxx\n");		
    for (i = 0; i < 5; i++)		//父进程专用出口,i会自增
    {
    
    
        pid = fork();
        if(pid == 0)
        {
    
    
            break;				//子进程专用出口,i不会自增
        }
    }
    if(i < 5)
    {
    
    
        sleep(i);
        printf("I'm %d child , pid = %u\n", i+1, getpid());
    }
    else
    {
    
    
        sleep(i);
        printf("I'm parent\n");
    }
}

注意,创建完子进程之后一定要break,因为创建完子进程后,父进程和子进程都会继续往下执行,互不干扰。

父子进程fork后异同

刚fork后:
父子相同处:

全局变量,data,text,栈,堆,环境变量,用户ID,宿主目录,进程工作目录,信号处理方式…

父子不同处

进程ID,fork返回值,父进程ID,进程运行时间,闹钟(定时器),未决信号集

似乎,子进程复制了父进程0-3G用户空间内容,以及父进程的PCB,但pid不同。真的每fork一个一个子进程都要将父进程0-3G地址空间完全拷贝一份,然后再映射至物理内存吗?
当然不是,父子进程间遵循读时共享写时复制的原则,这样设计,无论子进程执行父进程的逻辑还是执行自己的逻辑都能节省内存开销。

父子进程共享的地方:

  • 文件描述符(打开文件的结构体)
  • mmap建立的映射区

猜你喜欢

转载自blog.csdn.net/bureau123/article/details/111933245