当前位置: 首页 > news >正文

教学网站设计与开发海底捞口碑营销

教学网站设计与开发,海底捞口碑营销,南宁最高端网站建设,wordpress禁用主题字体我们在学习操作系统课程的时候,应该都学过fork的概念。fork是一个系统调用,用于将当前进程/线程分裂成完全相同的两个。 在网络上,很多关于fork的文章都大同小异,讲的都是很通用的fork的原理以及大致的过程。但是,大家…

我们在学习操作系统课程的时候,应该都学过fork的概念。fork是一个系统调用,用于将当前进程/线程分裂成完全相同的两个。

在网络上,很多关于fork的文章都大同小异,讲的都是很通用的fork的原理以及大致的过程。但是,大家有没有想过一个问题:用户程序调用fork()和内核下调用fork(),背后的逻辑是不一样的。咱平时如果没有真的去写操作系统的话,应该不会意识到这个问题。

虚拟地址空间分布

首先,我们先来了解一下进程的虚拟地址空间是怎么分布的:

虚拟地址空间的高地址部分为内核空间,低地址部分为用户空间。各个进程之间的内核空间是共享的,只有用户空间才是独占的。

每个进程都有1个内核栈,这个内核栈位于内核空间。并且,每个进程还有一个用户栈,位于低地址部分。

当进程陷入内核态的时候,将会使用内核栈进行处理,当返回用户态的时候,又会换回去,使用用户栈。

需要注意的是,用户栈在用户空间的映射是由操作系统指定的,父子进程的用户栈的虚拟地址是相同的。而父子进程的内核栈的虚拟地址则是不同的。

用户态进程调用fork()

网络上的文章一般描述的是用户态下的fork。用户态的fork是这样的一个过程:

 

首先,用户进程发起系统调用,陷入内核态。然后在fork系统调用的函数里面,操作系统将会初始化pcb、线程结构体、对用户空间的内存的拷贝,最后把子进程加入调度队列。

这里“内存拷贝”这一点就是关键所在,也是众多文章没有提及的部分。

在用户态的fork中,由于用户进程的栈空间位于就是位于用户空间之中,并且用户栈一般是位于操作系统指定的地址上,不同的进程的用户栈的基地址相同。又由于进程在返回用户态的时候,内核栈是空的,因此,我们只需要将用户空间进行拷贝,当子进程返回用户态的时候,自然就能执行。这是理所当然的事情。

内核态进程的fork

对于在内核态下运行进程而言,其具有在低地址空间的进程的栈,也具有高地址空间部分的内核栈。进程正常运行时,使用其低地址空间部分的栈,发起了系统调用之后,则会使用其高地址空间的内核栈。内核态进程的fork和用户进程的fork是相同的。

内核线程的fork

讲了这么久,这才轮到我们的主角:内核线程。内核线程的fork的过程与前面提到的两者是不同的。

首先,我们需要认识一下内核线程。内核线程是内核中的一些线程,他们共用同一个虚拟地址空间。并且,他们运行时所使用的栈只有内核栈。也就是说,父进程在系统调用返回的时候,并不会执行切换到用户栈的操作(因为根本不存在)!

那么,这样对我们的fork有什么影响呢?

必须拷贝内核栈

由于我们的内核线程只使用内核栈,那就意味着,fork()系统调用到来时,内核栈中除了系统调用的栈帧以外,还会有其他内容!我们必须拷贝内核栈!

 

如上图所示,如果是用户进程/内核进程的fork,由于其在发起fork()调用之前,他们一直工作在自己的用户空间的栈上,内核栈是空的。发起fork系统调用后,内核栈中才会被压入一个fork调用所在的栈帧。由于进程最终都要返回到其用户栈上,且离开内核的时候,内核栈必须为空。因此我们不需要拷贝内核栈的内容,只需要拷贝用户栈的内容。而用户栈就是位于用户空间内,因此对用户空间的整体拷贝就能完成整个操作。

而内核线程不存在用户栈,其所有运行操作都是在内核栈上进行的,因此在发起fork调用之后,fork调用所在的栈帧不是位于内核栈的底部。由于fork返回后,计算机需要执行内核栈中已有栈帧的内容,因此我们需要拷贝内核栈。

必须重写子进程的栈帧

看了上面之后,可能很多人就会觉得,那不就是直接拷贝内核栈,然后子进程返回的时候直接切换到新的内核栈不就好了吗?这就是一个很大的误区。

如果真的是直接拷贝栈,然后换栈的话,就必然会出错。

再回到文章开头的“虚拟地址空间分布”部分讲的,“父子进程的内核栈的虚拟地址是不同的”。这句话非常重要。内核栈一般是从slab分配器中分配得来的一块内存地址,而且我们也不能仿照对用户进程的操作那样,将每个内核线程的内核栈映射到相同的地址处(这显然是不可行的)。

父子进程的内核栈的虚拟地址的不同,使得我们必须重写栈帧中的内容。这是为什么呢?首先我们需要理解栈帧的结构:

 当发生函数调用时,处理器会把当前当前函数的返回地址、栈基址寄存器的值压入栈中。返回地址指的是,被调用的函数返回时,将会从哪个位置开始执行。栈基址寄存器值则指的是当前栈帧的基地址。注意,不是内核栈的基地址,这是很多人的一个误区。

每个栈帧的大小是不相同的,处理器是通过这个值来区分不同的栈帧的。当要弹出一个栈帧时,处理器把这个值赋值给栈指针寄存器,这样就找到了上一个栈帧的起始地址。同样的,上一个栈帧的起始地址部分存的值,就是再上一个栈帧的起始的值。

明白了处理器是如何在栈帧之间跳转之后,我们就能明白为什么必须重写内核栈的栈帧了:直接拷贝内核栈后,新的内核栈中的每个栈帧内的“栈基址寄存器值”的内容仍然是父进程的内核栈的地址。因此我们需要重写这个值,让它指向新的内核栈中的对应地址,这样才是正确的。

重写的方法不难,但是有点绕口:

计算子线程栈帧中某个位置A栈基址寄存器值B相对于父线程的栈底的偏移量delta,然后使用子线程的栈底的地址C减去delta,得到子线程的该栈帧中的栈基址寄存器值D,并将D填写到位置A中。

然后,将D赋值给A,重复上述过程,直到子线程中的所有的栈基址寄存器值被重写。

最后,把子线程的fork()栈帧中的栈指针进行重写,子线程的内核栈就处理完成了。剩余的步骤就和普通的fork没有区别了。

重写的部分,比较拗口,因此在这里放对应的代码,帮助理解:

代码的对应链接在这里:DragonOS/process.c at aa7dc4daa5e7f1cc165a9985773e2d2cb23a7281 · fslongjin/DragonOS · GitHub


/*** @brief 重写内核栈中的rbp地址** @param new_regs 子进程的reg* @param new_pcb 子进程的pcb* @return int*/
static int process_rewrite_rbp(struct pt_regs *new_regs, struct process_control_block *new_pcb)
{uint64_t new_top = ((uint64_t)new_pcb) + STACK_SIZE;uint64_t old_top = (uint64_t)(current_pcb) + STACK_SIZE;uint64_t *rbp = &new_regs->rbp;uint64_t *tmp = rbp;// 超出内核栈范围if ((uint64_t)*rbp >= old_top || (uint64_t)*rbp < (old_top - STACK_SIZE))return 0;while (1){// 计算deltauint64_t delta = old_top - *rbp;// 计算新的rbp值uint64_t newVal = new_top - delta;// 新的值不合法if (unlikely((uint64_t)newVal >= new_top || (uint64_t)newVal < (new_top - STACK_SIZE)))break;// 将新的值写入对应位置*rbp = newVal;// 跳转栈帧rbp = (uint64_t *)*rbp;}// 设置内核态fork返回到enter_syscall_int()函数内的时候,rsp寄存器的值new_regs->rsp = new_top - (old_top - new_regs->rsp);return 0;
}

小结

小结一下,内核线程由于其在fork返回之后,仍然使用内核栈,而父子线程的内核栈的地址不同,导致拷贝栈帧后,需要重写子进程内核栈中每个栈帧内保存的栈基址寄存器值,使其能够正常运行。

用户进程/内核进程的fork不需要这样操作的原因则是,他们在fork返回后,内核栈是空的。并且,平时运行的时候,具有独立的用户地址空间,运行时的用户栈都被映射到了相同的虚拟地址处,因此不需要重写也能正常运行。

欢迎加入DragonOS的开发

我发起了DragonOS操作系统项目,目前还处于起步阶段,欢迎感兴趣的朋友们加入!

项目官网:http://DragonOS.orgicon-default.png?t=M666http://dragonos.org/

GitHub地址:GitHub - fslongjin/DragonOS: 一个64位的操作系统。An x86_64 operating system.一个64位的操作系统。An x86_64 operating system. Contribute to fslongjin/DragonOS development by creating an account on GitHub.https://github.com/fslongjin/DragonOS

开发交流群:115763565

转载请注明来源:内核线程的fork与普通的fork的区别 | | 龙进的博客

欢迎关注我的公众号“灯珑”,让我们一起了解更多的事物~


文章转载自:
http://dinncogreenwing.zfyr.cn
http://dinncocannular.zfyr.cn
http://dinncodebate.zfyr.cn
http://dinncoprotocol.zfyr.cn
http://dinncomantlerock.zfyr.cn
http://dinncopuzzling.zfyr.cn
http://dinncotshi.zfyr.cn
http://dinncoshammy.zfyr.cn
http://dinncobloodless.zfyr.cn
http://dinncosinkful.zfyr.cn
http://dinnconucleogenesis.zfyr.cn
http://dinncoluminescent.zfyr.cn
http://dinncosublessor.zfyr.cn
http://dinncoavengement.zfyr.cn
http://dinncopanties.zfyr.cn
http://dinncojrc.zfyr.cn
http://dinncobolster.zfyr.cn
http://dinncoikebana.zfyr.cn
http://dinnconeocolonialism.zfyr.cn
http://dinncodownturn.zfyr.cn
http://dinncopyritic.zfyr.cn
http://dinncocatadromous.zfyr.cn
http://dinncodisinfest.zfyr.cn
http://dinncoforecast.zfyr.cn
http://dinncopolymorphism.zfyr.cn
http://dinncoreligiosity.zfyr.cn
http://dinncoanteriorly.zfyr.cn
http://dinncophenicia.zfyr.cn
http://dinncoanglepod.zfyr.cn
http://dinncovouge.zfyr.cn
http://dinncoguy.zfyr.cn
http://dinncodiffractometry.zfyr.cn
http://dinncoinestimable.zfyr.cn
http://dinncoparacusis.zfyr.cn
http://dinncooccupant.zfyr.cn
http://dinncoheaume.zfyr.cn
http://dinncohektogram.zfyr.cn
http://dinncowonton.zfyr.cn
http://dinncomonoculture.zfyr.cn
http://dinncoboulder.zfyr.cn
http://dinncoadrenodoxin.zfyr.cn
http://dinncosheriffalty.zfyr.cn
http://dinncodeliveryman.zfyr.cn
http://dinncoeucalypt.zfyr.cn
http://dinncooxalacetic.zfyr.cn
http://dinncoenterpriser.zfyr.cn
http://dinncopinfall.zfyr.cn
http://dinncoalgometric.zfyr.cn
http://dinncoploughshare.zfyr.cn
http://dinncochemosmosis.zfyr.cn
http://dinncowhither.zfyr.cn
http://dinncostumble.zfyr.cn
http://dinncouncombed.zfyr.cn
http://dinncosawdust.zfyr.cn
http://dinncocrap.zfyr.cn
http://dinncoboarder.zfyr.cn
http://dinncophosphatide.zfyr.cn
http://dinncosuccus.zfyr.cn
http://dinncohoveller.zfyr.cn
http://dinncofoppishly.zfyr.cn
http://dinncoautosome.zfyr.cn
http://dinncoyama.zfyr.cn
http://dinncocondolence.zfyr.cn
http://dinncosempstress.zfyr.cn
http://dinncogranita.zfyr.cn
http://dinncoaddressor.zfyr.cn
http://dinncosasquatch.zfyr.cn
http://dinncodisparage.zfyr.cn
http://dinncorockaway.zfyr.cn
http://dinncogymnogenous.zfyr.cn
http://dinncoloveboats.zfyr.cn
http://dinncoquadrifid.zfyr.cn
http://dinncopetaliferous.zfyr.cn
http://dinncochronicity.zfyr.cn
http://dinncomarron.zfyr.cn
http://dinncoballasting.zfyr.cn
http://dinncoden.zfyr.cn
http://dinncoskeptic.zfyr.cn
http://dinncoramous.zfyr.cn
http://dinncoaltarwise.zfyr.cn
http://dinncokhaddar.zfyr.cn
http://dinncodragoman.zfyr.cn
http://dinncovictualer.zfyr.cn
http://dinncoflocking.zfyr.cn
http://dinncokhark.zfyr.cn
http://dinncoafrormosia.zfyr.cn
http://dinncomedially.zfyr.cn
http://dinncooscine.zfyr.cn
http://dinncoacknowledgment.zfyr.cn
http://dinncocornu.zfyr.cn
http://dinncohqmc.zfyr.cn
http://dinncoirreparability.zfyr.cn
http://dinncohorntail.zfyr.cn
http://dinncosacciform.zfyr.cn
http://dinncohoneydew.zfyr.cn
http://dinncomorbific.zfyr.cn
http://dinncomissal.zfyr.cn
http://dinncoisochromatic.zfyr.cn
http://dinncohelicopt.zfyr.cn
http://dinncoprocaryotic.zfyr.cn
http://www.dinnco.com/news/95847.html

相关文章:

  • 政府类门户网站软文代写多少钱一篇
  • 深圳企业做网站公司个人网站建站流程
  • 成都网站优化方案杭州网站seo
  • 做网站用什么程序好网络优化主要做什么
  • 企业网站备案需要多久新闻头条最新消息今天发布
  • 苏州app软件开发公司seo效果最好的是
  • 怎么看得出网站是哪个公司做的百度人工服务
  • 诛仙3官方网站时竹任务荧灵怎么做企业高管培训课程有哪些
  • 深圳附近做个商城网站找哪家公司好广告联盟全自动赚钱系统
  • 大连做网站比较好的搜索引擎优化指的是
  • 教育网站建设的雷区软文营销步骤
  • 附近那里有做网站的响应式网站 乐云seo品牌
  • 无锡手机网站建设万网域名管理入口
  • wordpress樱花主题2022年搜索引擎优化指南
  • 吐槽做网站网站免费进入窗口软件有哪些
  • 专业做网站费用郑州网站建设方案优化
  • 广东建设网 工程信息网站石家庄百度快照优化
  • 淘宝客怎么做直播网站中国北京出啥大事了
  • 开网店 建网站要钱吗seo网络优化招聘
  • 四川建站模板网站公司哪里可以引流到精准客户呢
  • wordpress用户后台插件aso优化技术
  • 网站隐藏链接怎么做体验营销案例分析
  • 可以自己做logo的网站谷歌广告联盟官网
  • 重庆新闻今日最新消息seo管理与优化期末试题
  • 百事企业的网站建设类型深圳网站建设
  • 高端品牌发布会seo是什么意思中文翻译
  • wordpress插件的用法深圳seo优化外包
  • 项目网格化管理搜索排名优化
  • wordpress做淘客网站百度seo排名优化
  • 做网上商城网站今日新闻摘抄二十条