linux的学习 fork进程创建

fork()函数用于创建子进程,它通过系统调用复制父进程的状态,包括代码、数据和资源。每个进程根据fork()的返回值来判断自身身份,子进程会得到0,而父进程则得到子进程的ID。在多层fork()调用中,会形成复杂的父子关系,影响进程执行顺序。
摘要由CSDN通过智能技术生成

一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。

一个进程调用fork()函数

系统先给新的进程分配资源,例如存储数据和代码的空间。

然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。

相当于克隆了一个自己。

参考下面一个例子:

#include <stdio.h>
#include<unistd.h>
int main(void ){
pid_t fpid ;//fpid表示fork函数到返回值
int count=0;
fpid=fork();
if(fpid<0) printf("错误,结束\n");
if(fpid==0) printf("son  %4d  %4d  %4d \n",getppid(),getpid(),fpid);
else printf("pa %4d  %4d  %4d \n",getppid(),getpid(),fpid);
return 0;

}

fpid=fork(); 这里通过fork函数创建了一个子进程,并且把返回值存在fpid中。

下一步,操作系统会选择一个进程运行。因为两个进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。

所以我们根据fpid的返回值进行判断

如果fpid=0 说明现在处于子进程中,这时fpid返回的值为0。

如果fpid>0 说明现在处于父进程中,这时fpid为儿子的编号。

那为什么不是从#include处开始复制代码的?

因为fork是把进程当前的情况拷贝一份,执行fork时,进程已经执行完了int count=0;fork只拷贝下一个要执行的代码到新的进程。

 

对上面执行的一个解释:

程序运行到fpid=fork();的时候,进程当前的情况拷贝一份,创建出另外一个和当前进程几乎一模一样的子进程,然后继续选择一个进程运行,在这里很明显选择了pa,然后再son。最后结束运行。

二、fork进阶知识

首先我们来看这一段代码:

#include <stdio.h>
#include<unistd.h>
int main(void ){
pid_t fpid ;//fpid表示fork函数到返回值
​
int count=0;
printf("son/pa ppid pid fpid  count\n");
for(;count<2;count++){
​
fpid=fork();
if(fpid<0) printf("错误,结束\n",count);
​
if(fpid==0) printf("son  %4d  %4d  %4d %d\n",getppid(),getpid(),fpid,count);
​
else printf("pa %4d  %4d  %4d %d\n",getppid(),getpid(),fpid,count);
}
return 0;
}

 

 

第一行:2868创建子进程2869(i=0)

第二行:2868创建子进程2870(i=1)

第三行:子进程2869运行(i=0)

第四行:2869创建子进程2871(i=1)

第五行:进程2871运行(i=1)

第六行:进程2870运行(i=1)

为什么前面有的进程的父进程为1?因为原来的父进程已经运行结束了。

结论:

2*(1+2+4+……+2的N-1次方)

参考链接:(111条消息) 【linux】linux中fork()详解(实例讲解)|fork的运行机制_fork()_bandaoyu的博客-CSDN博客

Linux中,`fork()` 函数是一个用于创建进程的标准库函数,它通常用于初始化子进程。下面是如何使用 `fork()` 函数创建进程的基本步骤: 1. **包含头文件**: ```c #include <unistd.h> ``` 2. **调用 fork() 函数**: ```c pid_t pid = fork(); // fork() 函数返回值 ``` `fork()` 函数会创建一个新的进程,如果调用成功,返回当前进程的ID(0),新创建的子进程返回其自身的ID(通常是大于0的)。如果遇到错误,会返回-1。 3. **处理返回值**: - 如果 `pid == 0` (即返回0),这表示我们是在子进程中,可以继续执行特定于子进程的操作。 - 如果 `pid > 0` (父进程),那么我们可以对子进程进行监控,也可以忽略这个返回值,因为父进程无需进一步操作子进程。 4. **避免无限递归**(如果在子进程中再次调用 `fork()`,会陷入死循环): ```c if (pid == 0) { // 子进程代码... exit(0); // 或者使用 _exit() 来退出子进程 } else if (pid < 0) { // 错误处理 perror("fork failed"); exit(-1); } ``` 5. **子进程的行为**: - 子进程从父进程复制了大部分上下文,并有自己的地址空间,除了复制的部分外,父子进程之间共享的数据区(如全局变量、静态变量)都是相同的。 6. **通信和同步**(如果有需要的话): 使用 `wait()`、`waitpid()` 等函数来等待子进程结束,或者使用管道、消息队列等机制进行进程间通信。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

HUN晓巫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值