fork()创建子进程步骤、函数用法及常见考点(内附fork()过程图)
2017-12-21 09:46
239 查看
1、fork()创建子进程详细步骤
2、fork()系统调用函数用法
一个现有进程可以调用fork函数创建一个新的进程。#include《unistd.h>
pid_t fork(void);
返回值:子进程中返回0,父进程中返回子进程的ID,出错返回-1
fork函数被调用一次,但返回两次。两次返回的唯一出别是child process的返回值是0,而父进程的返回值则是child process的进程ID。所以可以通过fork函数的返回值来进入父子进程独有的代码段(但是要借助ifelse(else if else )选择语句)。
注:父子进程共享代码段,但是分别拥有自己的数据段和堆栈段
注:这里的父进程就是执行的main函数。子进程是父进程的副本,开始于fork函数
从fork函数开始以后的代码父子共享,即父进程要执行这段代码,子进程也要执行这段代码。(子进程获得父进程数据空间,堆和栈的副本。但是父子进程并不共享这些存储空间部分。父,子进程共享代码段。)现在很多现实并不执行一个父进程数据段,栈和堆的完全复制。而是采用写时复制技术。这些区域有父子进程共享,而且内核将他们的访问权限改变为只读的。如果父子进程中的任一个试图修改这些区域,则内核只为修改区域的那块内存制作一个副本,通常是虚拟存储器系统中的一“页”。
显然这样有助于节约内存。
一般来说,在fork之后的父进程先执行还是子进程先执行是不确定的。(取决于内核的调度算法)
因为fork使子进程得到的返回值是0,子进程可以通过这个返回值来确定自己执行代码(若有),通过if else 语句来确定实现。而这个ID=0的进程不可能是其他的进程,因为进程ID=0总是由内核交换进程使用,返回值pid<0,即是pid=-1,fork函数创建进程失败。而pid大于即子进程的ID返回给父进程(每个进程都有一个非负整数表示的唯一进程ID)。所以通过这个子进程ID,父进程也可以确定自己独有的可执行代码(若有)。其他fork之后的代码父子进程都要执行,除非有进程退出,或者通过pid的选择语句。
执行后的结果。可以看出共享代码段,独有自己数据段和堆栈段(写时复制技术)。
子进程可以通过getppid函数获得自己父进程的ID,进程可以通过getpid函数获得自己的ID。
2、一个fork() puzzle
Consider the below code snippet:[cpp] view
plain copy
int main()
{
fork();
fork();
fork();
printf("Hello World\n");
}
The output:[on ubuntu 12.04]
[cpp] view
plain copy
aashish@aashish-laptop:~$ ./a.out
Hello World
Hello World
Hello World
aashish@aashish-laptop:~$ Hello World <---------------------------
Hello World
Hello World
Hello World
Hello World
The short answer is that you are creating multiple processes, which run asynchronously with respect to each other. The long answer follows: When you type ./a.out at the shell prompt, that creates a process running your program. Let's call that process 1. Process 1 calls fork(). This creates a new child process, Process 2, and both 1 and 2 carry on execution after the first fork() call, proceeding to the second fork() call. Process 1 creates child Process 3, and Process 2 creates child process 4. All four processes carry on from after the second fork(), proceeding to the final fork() call. Process 1 creates Process 5; Process 2 creates Process 6; Process 3 creates Process 7; and Process 4 creates Process 8. Note that these process numbers are arbitrary: there's no guarantee they'd be created in that order. The asynchrony comes into play as soon as that first fork() gets executed. The system offers no guarantees about scheduling the parent with respect to the child. Theoretically the child could run to completion before the parent continues, the parent could finish before the child gets any resources. The most likely scenario lies somewhere in the middle: the original process shares resources with its progeny, so that all run concurrently. The final piece of the puzzle results from the fact that the shell is waiting for Process 1 to complete.Only Process 1. The shell doesn't know (or care) that Process 1 has started other processes. So when Process 1 completes, the shell displays a prompt. As it happened, some of the descendants of Process 1 hadn't yet reached the printf() statement. By the time they got there, the shell had already displayed its prompt. To explore this further, you might want to try changing the fork() calls toprintf( "%d\n", fork() );and/or changeprintf("Hello World\n") toprintf("Hello from pid %d\n", getpid() ) |
相关文章推荐
- fork()创建子进程步骤、函数用法及常见考点(内附fork()过程图)
- fork()创建子进程步骤、函数用法及常见考点(内附fork()过程图)
- fork()创建子进程步骤、函数用法及常见考点(内附fork()过程图)
- 进程的创建过程(fork函数)
- 举例讲解C语言的fork()函数创建子进程的用法
- 简单掌握Linux系统中fork()函数创建子进程的用法
- Linux下进程的创建过程分析(_do_fork/do_fork详解)--Linux进程的管理与调度
- C语言 进程控制---创建进程fork()函数
- Linux进程创建fork()函数
- Linux 内核--fork()函数创建进程 (续)之copy_mem(int nr, struct task_struct *p)
- 有意思的进程创建函数fork() && fork() || fork() .
- 通过fork函数创建进程的跟踪,分析linux内核进程的创建
- linux下利用fork()函数创建进程
- Linux下进程的创建过程分析(_do_fork/do_fork详解)--Linux进程的管理与调度(八)【转】
- Linux 内核--fork()函数创建进程 (续)之copy_mem(int nr, struct task_struct *p)
- Linux下C编程,子进程创建函数fork() 执行解析
- Linux下进程的创建过程分析(_do_fork do_fork详解)--Linux进程的管理与调度(八)
- 如何创建守护进程fork()函数的运用
- fork()函数的执行过程、孤儿进程和僵尸进程
- 创建进程 fork()函数的基本使用 父子进程之间的关系