当前位置: 首页 > wzjs >正文

网站前置审批专项免费软文推广平台

网站前置审批专项,免费软文推广平台,广东省农业农村厅官网查询,wordpress 数据交互目录 一、fork函数的基本概念 pid_t的关键特性 fork的基本特性 二、fork的基本使用 1、简单示例 运行结果 关键点 注意事项 2、进一步探讨 运行结果说明 关键机制解析 实际应用提示 三、写时复制(Copy-On-Write)技术示例 执行流程分析: 关键点&#x…

目录

一、fork函数的基本概念

pid_t的关键特性

fork的基本特性

二、fork的基本使用

1、简单示例

运行结果

关键点

注意事项

2、进一步探讨

运行结果说明

关键机制解析

实际应用提示

三、写时复制(Copy-On-Write)技术示例

执行流程分析:

关键点:

三、fork的工作原理

四、关键问题解释

五、实际应用示例

区分父子进程的标准方法

六、注意事项


一、fork函数的基本概念

        fork()是Unix/Linux系统中用于创建新进程的系统调用函数。当调用fork()时,操作系统会创建一个与父进程几乎完全相同的子进程。

pid_t 是 进程 ID 的数据类型,在 Unix/Linux 系统编程中用于表示进程标识符(Process ID)。

pid_t的关键特性

  1. 定义位置

    • 通常在 <sys/types.h> 或 <unistd.h> 头文件中定义。

    • 实际类型可能是 int 或 long(取决于系统)。

  2. 用途

    • 存储进程 ID(getpid()getppid() 返回值)。

    • fork() 的返回值(父进程返回子进程 PID,子进程返回 0)。

    • 用于进程控制函数(如 waitpid()kill())。

fork的基本特性

  1. 两个返回值
    成功时:
    在父进程中返回子进程的PID(进程标识符)、在子进程中返回0
    失败时:
    在父进程中返回-1、不会创建子进程、同时会设置相应的errno(错误码)
    (注:errno是Linux系统记录错误状态的全局变量,可通过perror()或strerror()函数获取具体错误信息)

  2. 刚开始父进程与子进程的代码与数据都是同一份,因为子进程是由父进程创建的,而且子进程没有自己的代码和数据,同时目前也没有其他程序加载到内存中。

  3. 代码共享,数据独立的阶段

        发生在其中任意一个进程想要对数据修改的时候,此时数据段、堆栈等采用"写时复制"(Copy-On-Write)技术,各自拥有独立空间,但父子进程共享相同的代码段。


二、fork的基本使用

1、简单示例

#include <stdio.h>
#include <unistd.h>int main()
{fork();  // 创建子进程while(1){printf("I am a process...PID:%d, PPID:%d\n", getpid(), getppid());sleep(1);}return 0;
}

运行结果

程序运行后会输出两行交替出现的信息:

关键点

  1. 进程关系:子进程的PPID(父进程ID)就是父进程的PID

  2. 执行流程:fork()调用后,父进程和子进程都从fork()返回处继续执行

  3. PCB创建:操作系统会为每个新进程(包括fork创建的)创建进程控制块(PCB)

总的来说,遇到fork函数时,会进行以下操作:

  • 为子进程申请新的PCB
  • 子进程拷贝父进程PCB
  • 将子进程加入到进程列表
  • 然后再将子进程放入调度队列

注意事项

  • 父子进程执行顺序不确定,取决于系统调度

  • 父子进程共享代码段,但有各自独立的数据空间

  • fork()在父进程中返回子进程PID,在子进程中返回0

2、进一步探讨

        我们知道加载到内存当中的代码和数据是属于父进程的,那么fork函数创建的子进程的代码和数据又从何而来呢?

#include <stdio.h>
#include <unistd.h>int main()
{printf("I am running...\n");  // 只有父进程执行fork();  // 创建子进程的分界点while(1)  // 父子进程都从这里开始执行{printf("I am a process...PID:%d, PPID:%d\n", getpid(), getppid());sleep(1);}return 0;
}

运行结果说明

关键机制解析

  1. 代码共享机制

    • fork()之前的代码只由父进程执行

    • fork()之后的代码由父子进程共同执行

    • 父子进程共享相同的代码段(text segment)

  2. 数据管理机制

    • 采用写时拷贝(Copy-On-Write)技术

    • 初始时父子进程共享相同的数据空间

    • 当任一进程尝试修改数据时,操作系统才会为该进程创建数据的独立副本

  3. 进程调度特性

    • 父子进程被调度的顺序不确定

    • 执行顺序取决于操作系统的调度算法

    • 可能先执行父进程,也可能先执行子进程

实际应用提示

  • fork()前执行的代码不会被子进程重复执行(如示例中的第一个printf)

  • fork()后父子进程可以通过返回值区分(父进程得到子进程PID,子进程得到0)

  • 合理利用写时拷贝机制可以提高fork效率,减少不必要的内存复制


三、写时复制(Copy-On-Write)技术示例

一个典型的写时复制(COW)场景发生在fork()系统调用创建子进程时:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main() {int data = 42;  // 数据段变量pid_t pid = fork();  // 创建子进程if (pid == 0) {// 子进程printf("Child process - initial data: %d\n", data);data = 100;  // 修改数据printf("Child process - modified data: %d\n", data);} else if (pid > 0) {// 父进程sleep(1);  // 确保子进程先执行修改printf("Parent process - data remains: %d\n", data);} else {// fork失败perror("fork");return 1;}return 0;
}

执行流程分析:

  1. fork()调用前:只有一个进程,data变量值为42

  2. fork()调用后

    • 创建子进程,此时父子进程共享相同的代码段

    • 数据段、堆栈等内存区域也暂时共享(标记为COW)

    • 两个进程的页表都指向相同的物理内存页

  3. 子进程修改data时

    • 操作系统检测到写操作发生在COW页面

    • 内核为该页面创建副本,更新子进程的页表指向新副本

    • 子进程修改自己的副本(data=100),父进程的data保持不变

  4. 输出结果

关键点:

  • 写时复制延迟了实际的内存复制,直到真正需要时才进行

  • 父子进程共享相同的代码段(只读,无需复制)

  • 未修改的数据段/堆栈保持共享,节省内存

  • 修改操作触发页面错误,导致内核执行实际的复制


三、fork的工作原理

  1. 进程创建

    • 调用fork()后,操作系统创建子进程

    • 子进程获得父进程的代码段、数据段、堆栈等副本

    • 操作系统为子进程创建新的PCB(进程控制块)

  2. 写时复制

    • 初始时父子进程共享物理内存

    • 当任一进程尝试修改内存时,操作系统才会真正复制该内存页

  3. 执行流程

    • fork()之前的代码只由父进程执行

    • fork()之后的代码默认父子进程都会执行


四、关键问题解释

  1. 为什么fork有两个返回值

    • fork()在父进程和子进程中各返回一次

    • 父进程得到子进程PID,子进程得到0

  2. 返回值如何分配

    • 父进程:返回子进程的PID(>0)

    • 子进程:返回0

    • 错误:返回-1(仅在父进程中)

  3. if和else if如何同时成立

    • 实际上不是同时成立,而是分别在两个不同的进程中执行

    • 父进程执行else if(ret > 0)分支

    • 子进程执行if(ret == 0)分支


五、实际应用示例

        如前所述,fork函数创建的子进程会与父进程共享代码段。但如果父子进程执行完全相同的操作,创建子进程就失去了实际意义。

通常在实际应用中,我们会通过判断fork的返回值来区分父子进程的执行路径:

fork函数的返回值有以下几种情况:

  1. 成功创建子进程时:
    • 父进程获得子进程的PID
    • 子进程获得返回值0
  2. 创建失败时,父进程获得返回值-1

区分父子进程的标准方法

通过检查fork()的返回值来区分父子进程:

pid_t id = fork();if(id == 0) {// 子进程执行的代码
} 
else if(id > 0) {// 父进程执行的代码
} 
else {// fork失败处理
}

正是由于父子进程获取的返回值不同,我们可以据此编写不同的执行逻辑。例如:

#include <stdio.h>
#include <unistd.h>int main()
{printf("I am running...\n");pid_t id = fork();if(id == 0){ //childwhile(1){printf("I am child process...PID:%d, PPID:%d\n", getpid(), getppid());sleep(1);}}else if(id > 0){ //parentwhile(1){printf("I am parent process...PID:%d\n", getpid());sleep(1);}}else { //fork errorperror("fork failed");return 1;}return 0;
}

        fork创建出子进程后,子进程会进入到 if 语句的循环打印当中,而父进程会进入到 else if 语句的循环打印当中。


六、注意事项

  1. 调度顺序父子进程的执行顺序由操作系统调度决定,是不确定的

  2. 资源管理

    • 子进程会继承父进程打开的文件描述符

    • 需要适当处理文件描述符和避免僵尸进程

  3. 并发控制需要同步机制来协调父子进程的执行顺序(如管道、信号量等)

理解fork()的工作原理对于Unix/Linux系统编程至关重要,它是实现多进程应用程序的基础。

http://www.dtcms.com/wzjs/155824.html

相关文章:

  • 酒店管理公司网站建设方案列表网推广效果怎么样
  • 做网站上传照片的尺寸百度一下百度搜索首页
  • 做盗版电影网站赚钱吗seo优化课程
  • 如何查询一个网站所属的主机sem竞价开户
  • 做网站的时候网站的第一个字母怎么在网站标题前面显示 比如谷歌g一样百度网页入口
  • 辽宁网站制作seo流量工具
  • 工业物联网平台seo标题优化关键词怎么选
  • 沈阳装修公司网站建设发外链平台
  • 如何用dw做动态网站百度收录链接提交入口
  • 网站目录做二级域名经典软文案例标题加内容
  • 建设pc端网站是什么意思完整的品牌推广方案
  • 网站建设工资多少钱成都网站优化排名
  • 微信小程序api是什么优化设计一年级下册数学答案
  • 许昌工程建设信息网站2021年中国关键词
  • qq做兼职给网站给你打开百度首页
  • 好看的官网源码网站优化网站
  • 公司网站建设的签订合同自建网站流程
  • 公司建设网站费用属于什么费用外贸推广平台
  • 宁波大型网站制作网站优化推广排名
  • 什么网站有做面条的appseoul是韩国哪个城市
  • 密云青岛网站建设广告投放价目表
  • 住房与城乡建设厅网站如何点击优化神马关键词排名
  • 技术支持 石家庄网站建设枸橼酸西地那非片多长时间见效
  • 网站建设与管理总结报告推广之家
  • dw简易网站怎么做推广软件有哪些
  • 上海聚通装修公司地址烟台seo关键词排名
  • 基于h5的企业网站建设成都seo优化
  • 世界顶尖名表瑞士网站不要中国手表网站三生网络营销靠谱吗
  • 怎么做联盟网站互联网销售怎么做
  • 发布了一个网站 显示建设中网络热词的利弊