学习笔记(二):学习系统调用fork

一个进程调用fork()函数创建一个新的运行的子进程。
使用 fork() 函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间:包括代码,数据段,进程上下文、进程堆栈、打开的文件描述符等。
简单来说, 一个进程调用 fork() 函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中。
需要注意的是**fork()函数被调用一次,却会返回两次。**两次返回的区别是,子进程的返回值的是0,而父进程返回的是子进程的ID。若调用出错则返回-1.
以以下程序为例

void fork1()
{
    int x = 1;
    pid_t pid = fork();
    if (pid == 0) {
	printf("Child has x = %d\n", ++x);
    } 
    else {
	printf("Parent has x = %d\n", --x);
    }
    printf("Bye from process %d with x = %d\n", getpid(), x);
}

当在Linux系统上运行该代码,我们会得到如下结果
在这里插入图片描述
` 执行到fork()函数后,就创建了一个子进程,然后根据父进程和子进程返回值的不同,执行相应代码段。系统把原来的进程的所有代码,数据都复制到新的新进程中,所以子进程和父进程都会继续执行fork()调用之后的代码,最后一句输出会打印两次(其中getpid()函数是返回调用进程的ID)

例2.然后可以看看有多个循环的例子

void fork2()
{
    printf("L0\n");
    fork();
    printf("L1\n");    
    fork();
    printf("Bye\n");
}

可以先尝试画一下它的进程图

在这里插入图片描述
按照进程图,它会输出L0 L1 Bye Bye L1 Bye Bye
但一般来说,在 fork() 之后是父进程先执行还是子进程先执行是不确定的。这取决于内核所使用的调度算法。
在Linux上运行之后
在这里插入图片描述
而提示符会在子进程之前运行是因为父进程是当前shell命令执行的,父进程结束后就返回了shell。之后才是子进程继续打印的信息。
例3

void doit()
{
if (fork()==0){
fork();
printf("hello\n");
exit(0);
}
return;
}

可先尝试画进程图
在这里插入图片描述
运行结果:
在这里插入图片描述
子进程符合返回值等于0,运行语句块,再调用fork()之后该进程和他的子进程都运行后续代码,所以打印出两个hello。
例4:关于waitpid函数

int main()
{
if (fork()==0){
printf("a");fflush(stdout);
exit(0);
}
else{
printf("b");fflush(stdout);
waitpid(-1,NULL,0);
}
printf("c");fflush(stdout);
exit(0);
}

运行结果如下
在这里插入图片描述
关于waitpid: 当子进程退出时, 父进程需要wait/waitpid系统调用来读取子进程的退出状态, 然后子进程被系统回收.

如果父进程没有wait的话, 子进程将变成一个"僵尸进程", 内核会释放这个子进程所有的资源,包括打开的文件占用的内存等, 但在进程表中仍然有一个PCB, 记录进程号和退出状态等信息, 并导致进程号一直被占用, 而系统能使用的进程号数量是有限的

如果产生大量僵尸进程的话, 将因为没有可用的进程号而导致系统不能产生新的进程

waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束
waitpid()共有3个参数,在这个程序中第一个参数pid=-1表示waitpid就等待任何一个子进程结束,第二个参数statusp用于返回回收子进程的退出状态,第三个参数option提供了一些额外的选项来控制waitpid,值为0表示没有这些选项。

在这个程序先运行父进程,输出b,然后调用waitpid等待子进程结束,输出a,子程序正常退出后,输出c;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值