Linux 0.11 内核在内核空间创建进程时不使用写时复制技术

2023-05-16

       在Linux0.12内核完全剖析中,有这样一段话:"由于创建新进程的过程是通过完全复制父进程代码段和数据段的方式实现,因此在首次使用fork()创建新进程init()时,为了确保新进程用户态栈中没有进程0的多余信息,要求进程0在创建第一个新进程(进程1)之前不要使用其用户态堆栈,即要求任务0不要调用函数。"

       一直对这段话不太理解,今天研究了一下午,总算有点眉目了。

       首先,内核在内核地址空间并不使用写时复制技术,这是因为在系统内核代码的实现中,写时复制机制代码限定了写时复制只能用于用户空间,具体代码流程如下:fork()-->copy_mem()->copy_page_tables()。在copy_page_tables()函数中有这样一段代码:

      nr = (from==0)?0xA0:1024;
        for ( ; nr-- > 0 ; from_page_table++,to_page_table++) {
            this_page = *from_page_table;
            if (!this_page)
                continue;
            if (!(1 & this_page)) {
                if (!(new_page = get_free_page()))
                    return -1;
                read_swap_page(this_page>>1, (char *) new_page);
                *to_page_table = this_page;
                *from_page_table = new_page | (PAGE_DIRTY | 7);
                continue;
            }
            this_page &= ~2;
            *to_page_table = this_page;
            if (this_page > LOW_MEM) {
                *from_page_table = this_page;
                this_page -= LOW_MEM;
                this_page >>= 12;
                mem_map[this_page]++;
            }
        }

       在调用写时复制机制相关函数时,系统会判断要复制的地址空间是否位于内核代码地址空间,即nr = (from==0)?0xA0:1024;若位于内核地址空间,则肯定是系统第一次调用fork()复制内核地址空间,即任务0创建任务1,由于任务0的特殊性,只需要复制640KB空间就可以了。关键是if (this_page > LOW_MEM) 这段代码,系统判断要复制的地址空i安是否属于内核地址空间,若是,则什么也不做,若不是,则进行写时复制机制,将原页表项所指内存页也设为只读,如此而来,则不论是父进程还是子进程,只要有一个进程写共享的物理内存,就会引起缺页异常,导致写时复制。若是内核地址空间,则只有子进程即任务1所指的内存页面是只读的,子进程对内存页面的写操作仍会导致写时复制,但父进程可随时读写其地址空间,不会引起写时复制。

       补充一下对"内核空间不使用写时复制机制"的本质理解:参看另一篇博客:http://blog.csdn.net/yihaolovem/article/details/37958351(在这片博客之后很长时间写的)

       因为任务0和任务1这两个进程比较特殊,他们的进程虚拟地址空间不同,但是引用的却是完全相同的内核代码区内(小于1M的物理内存)相同的代码和物理内存页面(640KB)只是执行的代码不在一处。由于引用的是相同的一段物理内存地址空间,而执行的代码不在一处,相当于一段物理内存空间中有两个进程,但两个进程共享着同一个用户堆栈,由于每个进程都有自己的私有内核堆栈(存在于任务描述符结构体中),所以这两个进程各自有自己的内核堆栈。

       在进程0创建新进程1之前应当禁止使用其用户态堆栈,以保持其干净的状态,因为进程0必然要创建进程1,所以其用户态堆栈必然在创建进程1的过程中由两个进程共享,而不能独立成进程0的私有用户态堆栈。若进程0弄脏了用户堆栈,则进程1被fork后,用户堆栈中也会存在进程0中遗留下来的脏东西,而他们虽然共享同一段内核代码,但执行的地址不同,故用户堆栈不可苟同。

        由于内核空间并不使用写时复制机制(我想,可能是因为内核是全局的,由所有进程共享的,故不需要进行写时复制,还有就是安全性方面的考虑还有进程0和1的特殊性所致),所以进程0创建进程1后,其代码数据地址空间仍是共享的,但进程1如要执行函数调用,则会读写其用户堆栈,引起写时复制(必须保证此时的用户堆栈干净),在主内存分配一页内存作为其私有用户堆栈,至此,进程0和进程1的用户堆栈独立开来。由于内核调度程序是随即的,所以创建进程1后,仍不能确定进程0和1的执行顺序,若进程0先执行但弄脏了用户堆栈,则仍是有问题的,会导致进程1因写用户堆栈引起写时复制时复制脏了的用户堆栈,所以要保证进程0不可调用函数而弄脏用户堆栈。

       综上所述,由于进程0的特殊性,导致其fork进程1时要保证用户堆栈的干净,就要保证其不调用函数,所以他的fork().pause()函数都是内联函数。

       另外,进程0执行内联的系统调用fork(),pause()时也是一种函数调用,但是这是系统调用,使用的是系统堆栈,故不会影响其用户堆栈。我觉得其实内核fork还是使用了写时复制的,即进程1写操作会引起写时复制操作。追踪内核代码也可以看到,写时复制调用的函数也只是对内核空间的写时复制打印一句警告,但仍会最终执行un_wp_page()函数为其在主内存分配一页内存,并取消写保护。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux 0.11 内核在内核空间创建进程时不使用写时复制技术 的相关文章

  • C++ 一个简单的判断子网掩码是否有效的函数

    简介 子网掩码 subnet mask 又叫网络掩码 地址掩码 子网络遮罩 xff0c 它是一种用来指明一个IP地址的哪些位标识的是主机所在的子网 xff0c 以及哪些位标识的是主机的位掩码 子网掩码不能单独存在 xff0c 它必须结合IP
  • css中块元素和内联元素有什么区别?

    块级元素和内联元素 xff0c 我想接触过CSS的朋友都有所了解 xff0c 但是在实际写CSS代码时却考虑的并不多 xff0c 我们无意中就已经按照块级元素和内联元素的规则进行布局样式了 我有时在想 xff0c 为什么要区别块级元素和内联
  • 用docker启动ubuntu的桌面环境

    在win10下使用了docker之后 xff0c 已经完全抛弃了之前虚拟机的开发方式 xff0c 在学习一些计算机视觉相关的内容时 xff0c 可能需要在图形化界面进行开发和调试 xff0c 所以尝试了下在dockerhub上搜索了下支持d
  • 使用Git Extensions直接push代码到Gerrit审核

    公司使用Gerrit代码审核 xff0c 本地push代码只能提交到refs for branch xff0c 所以使用git bash进行push时 xff0c 需要使用如下命令 git push origin HEAD refs for
  • C++避免变量重复定义

    C 43 43 小白选手 求轻拍 在A cpp B cpp文件中同时包含B h 这样的话在B h中的变量就会重复定义了 解决的办法是在B h中 变量前面加上extern关键字 在B cpp文件中再定义一次
  • 使用Eclipse编译运行MapReduce程序

    下载eclipse 64位 http eclipse bluemix net packages mars 1 JAVA LINUX64 解压到安装目录 安装 Hadoop Eclipse Plugin 要在 Eclipse 上编译和运行 M
  • 内部网盘phpdisk创建记录

    PHPDISK的这次创建是在PHPWIND8 7的基础上 xff0c 一起安装的 xff0c 所以单独安装PHPDISK所需要的RPM包就不需要再安装了 将PHPDISK解压缩后 xff0c UPLOAD文件夹里面的东西 xff0c 复制到
  • July 17th 模拟赛C T2 Number Solution

    空降题目处 外网 点我点我点我 空降题目处 内网 点我点我点我 Description 给出一个整数 xff0c 你可以对 进行两种操作 1 将x变成4x 43 3 2 将x变成8x 43 7 问 xff0c 最少通过多少次操作 xff0c
  • np.maximum vs np.minimum

    一直按照字面意思理解 xff0c 以为maxmum取最大值 examples 原来是有广播机制的 xff0e np maximum 取对应位置上的大值 xff0c np minimum 取对应位置上的较小值 xff0e import num
  • tensorflow通过模型文件,使用tensorboard查看其模型图Graph

    Google提供了一个工具 xff0c TensorBoard xff0c 它能以图表的方式分析你在训练过程中汇总的各种数据 xff0c 其中包括Graph结构 所以我们可以简单的写几行Pyhton xff0c 加载Graph xff0c
  • numpy中np.maximum的使用

    np maximum X Y out 61 None X和Y逐位进行比较 选择最大值 xff0c 最少接受两个参数 gt gt gt np maximum 2 3 4 1 5 2 array 2 5 4 gt gt gt np maximu
  • [svn]status命令

    wangyetao 64 linux u1604 LinuxRoom SVN FILE 个人空间 xx wangyetao 64 linux u1604 LinuxRoom SVN FILE 个人空间 xx svn help status
  • 维护型项目的管理

    最近 xff0c 一直在维护一个项目 项目很大 xff0c 有很多个系统相互配合 xff0c 且使用的语言也不一样 有JAVA写的系统 xff0c 有PHP写的 xff0c 各系统用的数据库也不一样 xff0c 还有一些我说不出来的技术 项
  • cas5.2.6 搭建cas服务端

    1 打包cas服务器端war包 下载cas overlay template 5 2 zip 1 1配置pom xml lt dependencies gt lt dependency gt lt groupId gt org apereo
  • PHP516 用phpize增加扩展PDO_OCI和OCI8

    环境 xff1a centos5 5 PHP5 1 6 oracle10 2 0 5 客户端 1 从oracle官网下载oracle客户端包 oracle instantclient basic 10 2 0 5 1 i386 rpm or
  • npm ERR! enoent This is related to npm not being able to find a file.解决

    一 问题描述 运行sudo npm install color name出现如下错误 xff1a npm ERR path root blog node modules color namenpm ERR code ENOENT npm E
  • ROS中最重要的变量$ROS_PACKAGE_PATH

    昨天刚成功安装了ardrone autonomy 和 tum ardrone xff0c 运行也是通过了 今天又尝试了一下昨天的命令 xff0c 结果发现tum ardrone居然又运行不了了 xff0c 郁闷 xff01 说是没有在环境变
  • 用TIKZ在LaTex中画图

    我之前是用Edraw max画图的 xff0c 但是有一个致命的问题就是在图上写字母的时候与图解释中不一致 xff0c 所以尝试了一下LaTex画图 xff0c 哎呀 xff0c 耗费我一下午的时间呀 首先导入包 xff1a usepack
  • NLP中三种特征抽取器的优与劣

    RNN LSTM GRU xff1a 缺点 xff08 1 xff09 xff1a 无法并行 xff0c 因此速度较慢 xff08 2 xff09 xff1a RNN无法很好地学习到全局的结构信息 xff0c 尤其对于序列结构很长的 CNN
  • python List中元素两两组合

    aa span class token operator 61 span span class token punctuation span span class token string 39 a 39 span span class t

随机推荐

  • JRE not compatible with project .class file compatibility: 1.7

    电脑上刚装了jdk1 7 xff0c 运行一般程序的时候没有出现什么问题 xff0c 由于内存不够用 xff0c 在设置虚拟内存时却出现问题 xff0c 如下 xff1a 还好找到了解决办法 xff0c 错误的原因是JRE库配置与Java
  • BufferedWriter 的 flush() 方法

    package com corpus import java io import java util List import edu stanford nlp ling HasWord import edu stanford nlp lin
  • 正则表达式匹配连续多个空格或tab空格

    Pattern p 61 Pattern compile 34 s 2 t 34 Matcher m 61 p matcher str String strNoBlank 61 m replaceAll 34 34 System out p
  • LaTex中插入花体字母

    特别要注意的是 xff1a 在LaTeX中 xff0c 别把希腊字母和英文的花体字母搞混哦 xff0c 哈哈 举个例子 xff1a 后面显示的 X 不是希腊字母 西 即 也就是说不能通过 Chi 的方式插入这个特殊符号 xff0c 正确的花
  • 气哭了的C++调试,cmake 找不到 eigen

    这才刚刚开头 xff0c 可是就是不知道错误在哪里 xff1f 百度了问题后 xff0c 打开了很多很多相关的解答 xff0c 从昨天上午遇到这个问题 xff0c 历经昨天下午和晚上 xff0c 还是错误 xff0c 终于在今天上午圆满解决
  • 对ORACLE SCN的理解

    1 SCN数值实际来源于系统的timestamp xff0c 这个实际可以证明 select current scn from v database select timestamp to scn sysdate from dual 这两个
  • Ubuntu 下 终端界面转图形界面

    在运行程序的时候 xff0c 错误的使用了快捷键 ctrl 43 alt 43 F10 然后 unbuntu就黑屏了 xff0c 整个界面只剩下左上角有一个白色的字符在闪 xff0c 然后 Ctrl 43 alt 43 F2时跳出终端的登录
  • python错误:TypeError: 'module' object is not callable

    TrainCorpusStructure py 文件中的代码如下 xff1a class TrainCorpusStructure inputs 61 Demo py中的代码如下 xff1a from corpusProcess impor
  • python 除法保留两位小数点

    span class hljs operator a span 61 span class hljs number 1 span b 61 span class hljs number 3 span print span class hlj
  • pytorch中contiguous()

    contiguous xff1a view只能用在contiguous的variable上 如果在view之前用了transpose permute等 xff0c 需要用contiguous 来返回一个contiguous copy 一种可
  • tensorflow中control_flow_ops.while_loop

    self h0 61 tf zeros self batch size self hidden dim self h0 61 tf stack self h0 self h0 相当于 h0和C0 generator on initial r
  • k8s基础

    目录 一 基本介绍 二 组件介绍 1 master组件 2 node组件 三 核心概念 1 Pod 2 controller 3 service 四 单master搭建集群 1 系统初始化 2 安装k8s核心组件 3 容器化安装其他插件 4
  • 论文解读:Tips and Tricks for Visual Question Answering: Learnings from the 2017 Challenge

    这是关于VQA问题的第十二篇系列文章 这篇论文具有很强的指导意义 xff0c 本篇文章将介绍论文 xff1a 主要思想 xff1b 模型方法 xff1b 试验细节 有兴趣可以查看原文 xff1a Tips and Tricks for Vi
  • 总结2014——迷茫以及迷茫过后的坚持

    首先 xff0c 借用一句话和大家共勉 xff1a 少一些功利主义的追求 xff0c 多一些不为什么的坚持 xff01 xff01 不知不觉15年也快过了1个月了 xff0c 还是想着要为14年做一下总结 xff1a 记录一下自己的历程 今
  • 在faster rcnn中使用soft nms,faster rcnn的改进(一)

    1 背景介绍 我的项目是利用faster rcnn检测kiiti数据集 xff0c 用原始nms xff0c iters 61 10000的情况下 xff0c 得到的mAP 61 0 586 在改用soft nms后 xff0c 其他参数均
  • 建立DATAGUARD最大保护模式-测试手记

    建立DATAGUARD 最大保护模式 xff08 自写 xff09 xff08 备注 xff1a 本文档符合最大保护模式 xff0c 所有参数均为最大保护模式下适用 xff0c 其他模式不适用 xff09 1 主库 xff0c 启动归档 x
  • docker中安装ping | vim | nginx镜像

    docker安装nginx镜像并常见nginx容器 docker pull nginx latest docker run detach publish 9999 80 name nginxSer restart unless stoppe
  • 从操作系统内核解释电脑死机原理

    关于电脑死机的原因或者说原理 xff0c 即电脑为什么会死机 xff0c 电脑死机时计算机底层都发生了什么 一直不太明白 xff0c 在网上也查过相关的资料 xff0c 但是都没有找到自己想要的 网上谈的都是外部导致电脑死机的原因 xff0
  • 自己动手写操作系统第二章 pmtest1.asm分析

    34 pm inc 34 描述符 Usage Descrptor Base Limit Attr Base dd Limit dd Low 20 bits available Attr dw lower 4 bits of higher b
  • Linux 0.11 内核在内核空间创建进程时不使用写时复制技术

    在Linux0 12内核完全剖析中 xff0c 有这样一段话 34 由于创建新进程的过程是通过完全复制父进程代码段和数据段的方式实现 xff0c 因此在首次使用fork 创建新进程init 时 xff0c 为了确保新进程用户态栈中没有进程0