Linux中fork()函数的底层实现【转】
转自:http://blog.csdn.net/duoru_xiong/article/details/76358812
1. fork(),vfork(),clone()的区别
- 这三个系统调用的底层都是通过do_fork()内核函数实现,只不过是通过对do_fork()传递的不同参数来实现不同的功能。
- 其中参数clone_flags由两部分组成,其最低的字节为信号类型,用以规定子进程去世时应该向父进程发出的信号;第二部分是一些表示资源和特性的标志位,来标识对于父进程的资源是拷贝还是通过指针共享。
- fork(),这些标志全为0,表示要全部拷贝;vfork(),则是父、子进程公用虚存空间;clone(),由调用者设定并作为参数传递。
所以,fork()创建进程;vfork()是创建的线程,它是创建进程的中间步骤,如若创建进程后会直接调用exec(),则可用vfork()来减少不必要的拷贝;clone()创建线程,可以是内核线程,也可以是用户线程。
2. fork()的底层实现
- fork()是通过调用do_fork()内核函数来实现的,在do_fork()中,通过查找位图,为子进程分配新的pid参数,再通过copy_process()复制父进程的PCB以及资源,最后检查clone_flags中CLONE_STOPPED是否被设置,如若未设置,将子进程先于父进程插于运行队列并唤醒,fork()完成。
- 在这些步骤中,copy_proceee()完成fork()大部分任务,其中dup_task_struct()完成子进程在内核分空间分配以及对父进程task_struct,thread_info的拷贝,并使这两部分互指;在检查一系列clone_flags之后确定拷贝父进程的哪些资源:
if ((retval = copy_semundo(clone_flags, p)))
goto bad_fork_cleanup_audit;
if ((retval = copy_files(clone_flags, p)))
goto bad_fork_cleanup_semundo;
if ((retval = copy_fs(clone_flags, p)))
goto bad_fork_cleanup_files;
if ((retval = copy_sighand(clone_flags, p)))
goto bad_fork_cleanup_fs;
if ((retval = copy_signal(clone_flags, p)))
goto bad_fork_cleanup_sighand;
if ((retval = copy_mm(clone_flags, p)))
goto bad_fork_cleanup_signal;
if ((retval = copy_keys(clone_flags, p)))
goto bad_fork_cleanup_mm;
if ((retval = copy_namespace(clone_flags, p)))
goto bad_fork_cleanup_keys;
retval = copy_thread(, clone_flags, stack_start, stack_size, p, regs); 在此之后,设置子进程的状态,各个字段,并将其插入进程链表,copy_process()完成任务。
在以上拷贝资源的内核函数中,最为重要的是copy_mm()以及copy_thread(),copy_mm()完成的是对父进程虚存空间的拷贝,而copy_thread()通过eax寄存器将子进程返回值强制置为0并初始化子进程内核栈。
copy_mm()内核函数:
()先完成对子进程mm_struct的拷贝: struct mm_struct * mm, *oldmm;
int retval; tsk->min_flt = tsk->maj_flt = ;
tsk->nvcsw = tsk->nivcsw = ; tsk->mm = NULL;
tsk->active_mm = NULL; ()判断是否是内核线程: if (!oldmm)
return ; ()通过clone_flags标志位确定是否需要拷贝虚存空间: if (clone_flags & CLONE_VM) {//有标志位,共享父进程空间
atomic_inc(&oldmm->mm_users);
mm = oldmm;
spin_unlock_wait(&oldmm->page_table_lock);
goto good_mm;
}
//没有CLONE_VM标志,就必须创建一个新的地址空间。必须要有地址空间,即使此时并没有分配内存。
retval = -ENOMEM;
//分配一个新的内存描述符。把它的地址存放在新进程的mm中。
mm = allocate_mm();
if (!mm)
goto fail_nomem;
//并从当前进程复制mm的内容。
memcpy(mm, oldmm, sizeof(*mm));
if (!mm_init(mm))
goto fail_nomem; ...... //dup_mmap不但复制了线程区和页表,也设置了mm的一些属性.
//它也会改变父进程的私有,可写的页为只读的,以使写时复制机制生效。
retval = dup_mmap(mm, oldmm);
if (retval)
goto free_pt; 至此,copy_mm()对父进程资源拷贝完毕。
fork()底层流程图如下:
PS:终于码完…第一篇博客, 如若有什么错误,欢迎大家指正,请将错误发送至xiongduoru@163.com,谢谢~
Linux中fork()函数的底层实现【转】的更多相关文章
- 【转】linux 中fork()函数详解
在看多线程的时候看到了这个函数,于是学习了下,下面文章写的通俗易懂,于是就开心的看完了,最后还是很愉快的算出了他最后一个问题. linux 中fork()函数详解 一.fork入门知识 一个进程,包括 ...
- Linux中fork()函数详解(转载)
linux中fork()函数详解 一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事, ...
- linux中fork()函数
man fork: FORK() Linux Programmer's Manual FORK(2) NAME fork - create a child process SYNOPSIS #incl ...
- linux中fork函数详解(转)
add by zhj: 在Linux,创建进程是用fork(),它其实就是拷贝父进程的数据段和其它数据,这相当于C函数调用中的值传递,这是 此后两者的修改都互不影响.因为两者的数据虽相同,但却在不同的 ...
- Linux中fork()函数详解(转)
一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同, ...
- Linux中fork()函数详解
一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程, 也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同 ...
- Linux中fork函数的例子
- Linux中fork的秘密
linux中fork()函数详解 一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以 ...
- Linux环境fork()函数详解
Linux环境fork()函数详解 引言 先来看一段代码吧, 1 #include <sys/types.h> 2 #include <unistd.h> 3 #include ...
随机推荐
- 【bzoj5099】[POI2018]Pionek 双指针法
题目描述 给你 $n$ 个平面向量,选出它们中的一部分,使得它们的和的长度最大.求这个最大长度的平方. 输入 第一行包含一个正整数n(n<=200000),表示指令条数. 接下来n行,每行两个整 ...
- Telnet 远程控制
Telnet 远程控制 一.挂第3张盘,进入RPMS中: 挂盘:mount /dev/cdrom /mnt/cdrom 路径:cd /mnt/cdrom/RedHat/RPMS 二.将rpm文件复制到 ...
- 题解 P1423 【小玉在游泳】
这道题可以用简单的蒟蒻do-while循环,方式:直到型 因为是萌新/蒟蒻,所以并不知道这道题的时间/空间复杂度是多大 脚踩std(^▽^)摩擦 #include <iostream> # ...
- 【刷题】BZOJ 4573 [Zjoi2016]大森林
Description 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力.小 ...
- 【刷题】BZOJ 1453 [Wc]Dface双面棋盘
Description Input Output Sample Input Sample Output HINT Solution 不强制在线的动态图问题,那就LCT了 类似二分图那道题目 对于四个方 ...
- 【BZOJ1497】【NOI2006】最大获利(网络流)
[BZOJ1497][NOI2006]最大获利(网络流) 题面 BZOJ Description 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU集团旗下的CS& ...
- 洛谷 P4240 毒瘤之神的考验 解题报告
P4240 毒瘤之神的考验 题目背景 \(\tt{Salamander}\)的家门口是一条长长的公路. 又是一年春天将至,\(\tt{Salamander}\)发现路边长出了一排毒瘤! \(\tt{S ...
- 第一个python教程(1)
使用文本编辑器 在Python的交互式命令行写程序,好处是一下就能得到结果,坏处是没法保存,下次还想运行的时候,还得再敲一遍. 所以,实际开发的时候,我们总是使用一个文本编辑器来写代码,写完了,保存为 ...
- SQLite中的自增关键字:AUTO_INCREMENT、INTEGER PRIMARY KEY与AUTOINCREMENT
1.SQLite不支持关键字AUTO_INCREMENT 1)AUTO_INCREMENT不生效的问题 SQL语句: CREATE TABLE todo ( id INTEGER AUTO_I ...
- bzoj2734:[HNOI2012]集合选数(状压DP)
菜菜的喵喵题~ 化序列为矩阵!化腐朽为神奇!左上角为1,往右每次*3,往下每次*2,这样子就把问题转化成了在矩阵里选不相邻的数有几种可能. 举个矩阵的例子 1 3 9 27 2 6 18 54 4 1 ...