fork函数辨析

本文详细介绍了fork函数在创建进程过程中的作用,包括如何通过fork生成子进程,父子进程之间的关系,如代码共享与数据私有化,以及写时拷贝技术。通过实例代码展示了fork函数的基本用法,并探讨了进程间的区别,如PID、资源利用率、信号等。最后,提到了fork在实际应用中的场景,如处理客户端请求和执行不同程序。
摘要由CSDN通过智能技术生成

如何创建进程?

在这里插入图片描述
子进程会继承父进程的大部分信息(其中包括环境变量,当前目录,父进程的文件锁,pending alarms和pending signals等等),但是pid(进程号) 是不同的,

fork函数理解认识

先认识这两点即可

  1. fork有两个返回值(父进程返回子进程的pid,子进程返回0)
  2. 父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)

第一点验证代码:
在这里插入图片描述
运行结果:
在这里插入图片描述
第二点验证代码:
在这里插入图片描述
运行结果:
在这里插入图片描述

问题1

这里我们看到fork之前只有一句,而fork之后有两句,为什么呢?
在这里插入图片描述
这是因为,子进程是从fork之后开始执行的,虽然父子进程代码相同,但是开始执行的地方不同,这其中有关程序计数器的作用。

问题2

好,代码共享理解了,数据私有表现独立性?但是如果父子进程的数据大部分相同,全部拷贝会浪费空间,所以采用写时拷贝,那什么是写时拷贝?
通常,父子代码共享,父子再不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副本。
在这里插入图片描述

问题3

操作系统是如何知道任意一方想要修改数据的呢? 注意看,父子进程页表项会统一记录内存地址是只读的,当某一进程试图写入的时候,捕获这个写入意图,然后重新开辟空间写入数据,但是页表项 原本数据的虚拟内存是不会改变的, 改变的是虚拟内存对应的物理内存指向(指向那个刚写入的新数据的空间),这也是为什么ret虽然只占用一个int空间,但是却有两个值的原因。

fork常规用法

  1. 一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。
  2. 一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数

fork是怎么做到?

  • 分配新的内存块和内核数据结构给子进程
  • 将父进程部分数据结构内容拷贝至子进程
  • 添加子进程到系统进程列表当中
  • fork返回,开始调度器调度
    在这里插入图片描述

附:linux手册fork描述

NAME
fork - create a child process

SYNOPSIS
#include <unistd.h>

   pid_t fork(void);

DESCRIPTION
fork() creates a new process by duplicating the calling process. The new process, referred to as the child, is an exact duplicate of the calling process, referred to as the parent, except for the
following points:

   *  The child has its own unique process ID, and this PID does not match the ID of any existing process group (setpgid(2)).

   *  The child's parent process ID is the same as the parent's process ID.

   *  The child does not inherit its parent's memory locks (mlock(2), mlockall(2)).

   *  Process resource utilizations (getrusage(2)) and CPU time counters (times(2)) are reset to zero in the child.

   *  The child's set of pending signals is initially empty (sigpending(2)).

   *  The child does not inherit semaphore adjustments from its parent (semop(2)).

   *  The child does not inherit record locks from its parent (fcntl(2)).

   *  The child does not inherit timers from its parent (setitimer(2), alarm(2), timer_create(2)).

   *  The child does not inherit outstanding asynchronous I/O operations from its parent (aio_read(3), aio_write(3)), nor does it inherit any asynchronous I/O contexts from its  parent  (see  io_set‐
      up(2)).

   The process attributes in the preceding list are all specified in POSIX.1-2001.  The parent and child also differ with respect to the following Linux-specific process attributes:

   *  The child does not inherit directory change notifications (dnotify) from its parent (see the description of F_NOTIFY in fcntl(2)).

   *  The prctl(2) PR_SET_PDEATHSIG setting is reset so that the child does not receive a signal when its parent terminates.

   *  The default timer slack value is set to the parent's current timer slack value.  See the description of PR_SET_TIMERSLACK in prctl(2).

翻译结果:

姓名

fork-创建子进程

简介

#包括<unistd.h>

pid\ t叉(空);

说明

fork()通过复制调用进程来创建一个新进程。新进程(称为子进程)与调用进程(称为父进程)完全相同,但

以下几点:

*子进程有自己唯一的进程ID,并且此PID与任何现有进程组的ID不匹配(setpgid(2))。

*子进程的父进程ID与父进程ID相同。

*子级不继承其父级的内存锁(mlock(2)、mlockall(2))。

*子进程中的进程资源利用率(getrusage(2))和CPU时间计数器(times(2))重置为零。

*子级的挂起信号集最初为空(sigpending(2))。

*子级不从其父级继承信号量调整(semop(2))。

*子项不从其父项继承记录锁(fcntl(2))。

*子级不从其父级继承计时器(setitimer(2)、alarm(2)、timer\u create(2))。

*子级不会从其父级继承未完成的异步I/O操作(aio\ U read(3)、aio\ U write(3)),也不会从其父级继承任何异步I/O上下文(请参阅io\ U set‐0)

向上(2))。

上述列表中的流程属性都在POSIX.1-2001中指定。父进程和子进程在以下特定于Linux的进程属性方面也有所不同:

*子目录不从其父目录继承目录更改通知(dnotify)(请参阅fcntl(2)中F_NOTIFY的描述)。

*prctl(2)PR\u SET\u PDEATHSIG设置被重置,这样子级在其父级终止时不会收到信号。

*默认计时器时差值设置为父级的当前计时器时差值。参见prctl(2)中PR\u SET\u TIMERSLACK的描述。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值