要理解fork(),首先需要懂得c程序和进程的概念:
c程序组成部分如下:
Text segment,正文段,由CPU执行的及其指令部分,可共享,通常是只读.
Initialized data segment, 初始化数据段,包含程序中需要明确赋初值的变量.
Uninitialized data segment, 非初始化数据段,对应于初始化数据段,又称bss段(block started by symbol,由符号开始的段),程序执行前,由内核初始化为0或空指针.
Stack,栈,存储自动变量和每次函数调用时所需保存的信息,程序递归时回用到栈保存返回地址和调用者的环境信息.
Heap, 堆,通常在堆中进行动态存储分配,位于非初始化数据段和栈之间.
典型的存储器安排如图所示:
至于进程,它主要包含三个元素:
一个可以执行的程序;
和该进程相关联的全部数据(包括变量,内存空间,缓冲区等等);
程序的执行上下文(execution context).
操作系统对进程的管理,典型的情况,是通过进程表完成的.进程表中的每一个表项,记录的是当前操作系统中一个进程的情况.当分给某个进程的 CPU时间已经用完,操作系统将该进程相关的寄存器的值,保存到该进程在进程表中对应的表项里面;把将要接替这个进程占用 CPU的那个进程的上下文,从进程表中读出,并更新相应的寄存器,这个过程称为上下文交换(process context switch).
然后是fork(),由fork创建的新进程称为子进程(child process),操作系统在进程表中相应为子进程建立一个新的表项.fork函数有个特性,”一次调用,二次返回”.它在调用进程(即父进程(parent process))中返回一次,返回值是子进程的ID号;在子进程又返回一次,返回值为0.因此,我们可以通过返回值判断当前进程是父进程还是子进程.
父进程调用fork之前打开的所有描述子在fork返回之后由子进程分享,也就是说,子进程是父进程的副本,它获得父进程的数据空间,堆和栈的拷贝.注意,这里是拷贝,而不是分享,父进程与子进程分享的是正文段.(见前图)
fork()的两个典型用法为:
一个进程创建自身的一个拷贝,这样每个拷贝可以在另外一个拷贝在执行其他任务的同时处理各自的操作,这在网络编程中是很常见的.
一个进程想要执行另外一个程序.因为创建一个新进程的唯一方法是调用fork,所以我们可以用fork创建一个拷贝,然后在子进程中调用exec把自身替换成新的程序.
下面是一个很简单的fork()示例:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
fork();
printf("P1\n");
fork();
printf("P2\n");
}
注意在fork之后,由父进程先执行还是子进程先执行是不确定的,这取决于内核使用的调度算法..
#include <unistd.h>
#include <sys/types.h>
int main(void)
{
pid_t pid;
printf("fork!\n");
pid=fork();
if (pid < 0)
printf("error in fork!");
else if (pid == 0)
printf("i am the child process, my process id is %d\n",getpid());
else
printf("i am the parent process, my process id is %d\n",getpid());
}
输出结果很诡异,为:
fork!
i am the child process, my process id is 4286
i am the parent process, my process id is 4285
为什么这里fork!只输出一次呢?为了对比,可以将printf(“fork!\n”);里面的\n去掉,这时候程序倒是输出两次fork!了..解释如下,其实这与printf的缓冲机制有关了,printf某些内容时,操作系统仅仅是把该内容放到了stdout的缓冲队列里,并没有实际显示到屏幕上.因此fork()后,子进程得到这份拷贝.而当printf()中含有\n时,printf将刷新stdout,因此子进程无法得到这份拷贝,fork!也就理所当然地只输出一次罢了.
- 大小: 14 KB
分享到:
相关推荐
### Linux中的`fork()`函数详解 #### 一、`fork()`函数基础介绍 在Linux操作系统中,`fork()`函数是一个非常重要的系统调用,用于创建一个新的进程。这个新进程被称为子进程,而调用`fork()`函数的原进程则称为父...
创建新进程:fork 函数 fork 函数是 UNIX 统操作系统中用于创建新进程的系统调用。它创建了一个完全相同的子进程副本,并返回一个进程标识符(PID)。fork 函数的返回值在父进程和子进程中不同:在父进程中,返回子...
fork 函数详解 fork 函数是 Unix 系统中一个非常重要的系统调用,它允许一个进程创建一个新的进程,该新的进程是原来进程的副本。fork 函数的返回值在父进程和子进程中不同,在父进程中返回新创建的子进程的进程 ID...
### fork函数和子进程知识点详解 #### 一、引言 在计算机编程中,特别是针对多任务处理领域,进程管理是实现系统并发的关键技术之一。其中,`fork()`函数是Unix/Linux系统中创建新进程的核心手段。通过深入理解`...
### Linux 内核 do_fork 函数源代码浅析 #### 一、引言 在 Linux 内核中,进程的创建是一项基本且重要的功能。本文将深入剖析 do_fork 函数,它作为核心组件之一,在 Linux 内核中扮演着创建新进程的关键角色。do_...
在"演示fork函数的效果"这个主题中,我们将深入探讨`fork()`的工作原理以及如何使用它。 首先,`fork()`函数的调用会返回两次:一次在父进程中,一次在子进程中。在父进程中,`fork()`返回新创建子进程的进程ID...
### c语言中的`fork()`函数详解 #### 一、引言 `fork()`函数作为操作系统提供的核心系统调用之一,在进程管理和并发编程中扮演着重要角色。本文将深入探讨`fork()`函数的基本概念、工作原理及其在C语言中的具体应用...
《深入理解fork函数:进程创建的艺术》 fork函数在软件开发中扮演着至关重要的角色,尤其是在操作系统编程和并发处理中。它是Unix/Linux系统中创建新进程的主要方式。当我们谈论fork时,我们实际上是在讨论如何复制...
实验二fork函数kkkkkkkkkkkkk
关于fork函数的介绍,和测试程序,原版fork linux平台
2.fork 函数被调用一次,但返回两次, 两次返回的唯一区别是子进程的返回值是 0, 而父进程的返回值是新子进程的 PID。 3.子进程和父进程继续执行 fork 调用之后的指令。 在上图的存储空间布局中,父子进程只共享正文...
wait函数允许父进程挂起,直到一个子进程终止或者接收到信号,然后恢复并返回子进程的退出状态。 在实验中,通过fork系统调用,我们可以创建一个新的进程。在创建过程中,父进程会复制自身的内存空间,包括代码、...
`fork()`函数是Linux操作系统中用于创建新进程的关键系统调用。在本文档中,我们将深入探讨`fork()`的工作原理,以及如何通过示例代码理解其执行过程。 首先,让我们来了解一下`fork()`函数的基本概念。`fork()`会...
用fork创建子进程; 回答no执行父进程,yes执行父进程并复制进程的操作;在父进程将str3,str4接至str0中,并输出str0 ;在子进程中,将str1,str2接至str0中,并输出str0
在Linux操作系统中,`fork()`函数是一个非常关键的系统调用,它被用来创建一个新的进程——也就是我们常说的子进程。这个过程被称为进程复制,因为子进程会继承父进程的大部分属性,包括打开的文件、内存空间、信号...
在win系统下模拟linux中的fork()函数执行过程与基础通信过程 备注清晰。
fork函数的写时拷贝技术 fork函数是一种用于创建子进程的系统调用,它在创建子进程时,会将父进程的虚拟存储空间复制给子进程的虚拟存储空间。这种机制使得父子进程可以共享文件等资源,但是为了避免多个进程之间的...
原来刚刚开始做Linux下面的多进程编程的时候,对于下面这段代码感到很奇怪: #include #include #include #include #include #include #define LEN 2 void err_exit(char*fmt,…);...
本文档以ppt形式编写,通过例子,学习fork()函数的应用及用法,适合初学者。