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

建立有效的()杭州上城区抖音seo如何

建立有效的(),杭州上城区抖音seo如何,昆山花桥做网站,凡建网站首发公号:Rand_cs 本文讲述 xv6 中的一些细节流程,还有对之前文中遗留的问题做一些补充说明,主要有以下几个问题: 一次完整的磁盘中断流程进入调度器后的详细流程sched 函数中的条件判断scheduler 函数中为什么要周期性关中断 …
  • 首发公号:Rand_cs

本文讲述 xv6 中的一些细节流程,还有对之前文中遗留的问题做一些补充说明,主要有以下几个问题:

  1. 一次完整的磁盘中断流程
  2. 进入调度器后的详细流程
  3. sched 函数中的条件判断
  4. scheduler 函数中为什么要周期性关中断

一次完整的磁盘流程

此节讲述完整的磁盘读写流程,读写的流程总体差不多,这里以读为例子,先看“流程图”(看代码时的笔记图)

请添加图片描述

readint $T_SYSCALLsys_readfilereadreadibreadbgetiderwidestart

还是从 A 进程的用户态 read 函数开始:

  1. A 进程用户态调用 read 读取磁盘上的数据
  2. read 通过 INT 0x80 软件中断,通过中断门进入内核,此时会关中断(NOTE 这里我以中断门来实现系统调用为例,会关中断,xv6 源代码是以陷阱门实现系统调用,不会关中断)
  3. 期间多次取锁放锁,进行了多次 pushcli 和 popcli,但总是成对存在,所以目前总体还是处于 0 次 puchcli 状态
  4. 如果磁盘数据没有缓存,调用 iderw 来读写磁盘

A 进程内核态,iderw 函数:

  1. acquire(&idelock),获取磁盘锁,pushcli,cpu.IF = 0,1 次pushcli 状态
  2. 调用 idestart,将要读写的命令,扇区号等信息写进磁盘端口,以此来请求磁盘操作。写磁盘端口是通过 out 指令实现的。向磁盘发送命令后,磁盘就会工作,磁盘完成工作后就会向 cpu 发送中断信号。
  3. A 进程调用 sleep 等待磁盘操作完成。在 sleep 函数中,获取 ptable.lock,释放 idelock,然后调用 sched 让出

by the way,这里补充说明 sched 函数中的条件检查,之前的文章都一笔带过了:

void sched(void)   //让出CPU,重新调度
{int intena;struct proc *p = myproc();if(!holding(&ptable.lock))      // 必须持有 ptable.lockpanic("sched ptable.lock");if(mycpu()->ncli != 1)          // 1 次 pushcli 状态panic("sched locks");if(p->state == RUNNING)         // 只可能是 SLEEPING、RUNNABLE、ZOMBIE 三种状态之一panic("sched running");if(readeflags()&FL_IF)          // 此时肯定处于关中断状态(通过中断门进入内核会关中断,1次pushcli状态也应该对应关中断状态)panic("sched interruptible");intena = mycpu()->intena;swtch(&p->context, mycpu()->scheduler);mycpu()->intena = intena;
}

sched 函数中有 4 个条件检查:

  1. xv6 是个多 CPU 多任务系统,在 sched 任务调度的时候,需要持有 ptable.lock,不然进程的上下文会发生紊乱,举个简单的例子,A 时间片到了,先将 A 的状态设置为 RUNNABLE,然后调用 sched 让出 CPU,如果此时没有持有 ptable.lock,那么 A 进程便可能在另一个 CPU 上被调度,那么便出现一个进程在两 CPU 上运行的情况,Error
  2. 在 sched 函数中应当只有 1 次 pushcli 状态,这个条件检查感觉有点难以理解。从实践看代码确实,不管从哪条路径到达 sched 函数,都应该只有 1 次 pushcli,这是获取 ptable.lock 的锁造成的。从个人理解上说,sched 是为了调度进程,是要从 A 进程到 B 进程,那么 A 进程的开关中断(pushcli popcli 次数)不应该带入 B 进程,除了一种情况——调度,那就是 A 进程获取 ptable.lock 但是要在 B 进程中释放 ptable.lock。所以 sched 中应当只有 1 次 pushcli
  3. 在真正切换进程上下文之前,会首先修改旧进程的状态,在 xv6 中是 SLEEPING、RUNNABLE、ZOMBIE 三种之一
  4. 在 sched 中理应处于关中断状态,如果是通过中断门进入内核的,那么本身就处于关中断。如果是通过陷阱门进入内核,那么有 1 次 pushcli,也会处于关中断状态

回到磁盘中断,当 A 进程调用 sched 切换到 B 进程,这里假如 B 进程最初是因为时间片到了,调用 yield->sched->swtch 主动让出 CPU 的,则 B 进程的流程如下:

  1. 回到 B 进程 sched 函数中的 swtch 下一条指令处,然后释放 ptable.lock,此时 cpu.IF = 0,0 次 pushcli 状态,cpu.IF = 0 仍然处于关中断状态 是因为 A 进程通过中断门进入内核关中断造成的
  2. B 进程经过一些列指令后,最后执行 iret 返回 B 进程的用户态,此时会开中断
  3. NOTE,这里我们假设 CPU 内部逻辑:每条指令执行后都会检查是否有中断发生,如果有中断发生且开中断的情况下,则去处理中断。再假设,此前的磁盘操作已完成,已经向 CPU 发生了中断信号。但是在此之前 CPU 一直没有去处理中断,是因为在此之前一直处于关中断状态。
  4. Now,CPU 处于开中断状态,继续执行 B 进程的指令,开中断后的第一条指令执行完成后,检查是否有中断发生,发现有磁盘中断,那么中断 B 进程,通过中断门进入内核(该过程关中断)
  5. 执行磁盘中断处理程序,也就是执行 insl 指令从 0x1f0 端口将磁盘数据读取到内存,然后唤醒等待该磁盘事件的进程,在我们的例子当中就是 A 进程
  6. 中断执行完成,iret 返回 B 进程用户态(该过程开中断)
  7. 继续执行 B 进程的指令
  8. 时钟中断 B 进程,再次通过中断门进入内核(关中断),发现 B 进程的时间片到了,那么调用 yield->sched->swtch 重新调度进程,这里假设调度到 A 进程

回到 A 进程的内核态,准确来说回到 iderw->sleep->sched->swtch 的下一条指令

  1. A 进程执行 release(ptable.lock)、acquire(idelock)、release(idelock),此时状态: cpu.IF = 0,0 次 pushcli
  2. 将磁盘中断获取的数据 cp 到 A 进程内核态
  3. A 进程层层返回
  4. 最后 iret 返回 A 进程用户态(开中断)

系统启动进入调度器后的流程

请添加图片描述

mainuserinit //准备好 initcode 进程mpmainscheduler  // 进入调度器

调度器上下文:

  1. 第一次进入 scheduler,for 循环找到 RUNNABLE 进程,目前就只有一个 initcode 进程为 RUNNABLE 进程,找到并切换上下文到 initcode 进程

initcode 进程上下文:

  1. 执行 forkret 函数,因为是第一次执行,会首先执行 iinit 来初始化根文件系统
  2. 执行 readsb 从磁盘中读取超级块数据,期间会使用 iderw 读写磁盘,具体流程见第一小节。总之,initcode 进程会调用 sleep 函数让出 CPU 来等待磁盘操作
  3. 在 sleep->sched->swtch 中再次切换上下文到 调度器上下文

调度器上下文:

  1. 切换到内核页表,然后遍历任务队列,寻找 RUNNABLE 进程,但是目前只有一个且处于 SLEEPING 状态的进程,所以这里调度器会轮询空转,直到磁盘中断处理完成,initcode 进程被唤醒。
  2. 再次切换上下文到 initcode 进程

initcode 进程上下文

  1. 回到 forkret->iinit->readsb->bread->iderw->sleep->sched->swtch 的下一条指令处,然后层层返回到 forkret
  2. 再执行 initlog 恢复日志,这里会涉及到两次磁盘读写,道理同上,不再赘述
  3. 第 4 次调度到 initcode 进程后,forkret 函数执行完毕,再执行 trapret 函数,其中包含了 iret 指令,至此回到用户态,开始执行 initcode 进程的逻辑

by the way again,这里解释为什么在 scheduler 函数中需要周期性的开中断:

void scheduler(void)
{for(;;){sti();    // 周期性开中断for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){  //循环找一个RUNNABLE进程...}}
}

进入调度器上下文有两条路径:

  1. 系统刚启动进入 scheduler
  2. sched 函数中 swtch 上下文到调度器

回想前面说的 sched 函数,在它切换到新进程并返回用户态之前理应都处于关中断的状态。而一直处于关中断且没有开中断的话会引发死循环。

举个例子,假设没有周期性的开中断,也就是 scheduler 代码长这样的话:

void scheduler(void)
{for(;;){// 遍历进程列表,寻找 RUNNABLE 进程for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){...}}
}

假如当前系统只有一个进程(shell进程),它需要等待键盘输入而被阻塞(state==SLEEPING),内层循环是找不到 RUNNABLE 进程的,便回到外层循环,外层循环现在相当于什么也不做,便又再次进入内层循环。如此下来死循环。

而加入周期性的开中断后,CPU 便会响应中断。当有键盘输入时,中断当前的调度上下文而进入中断上下文,执行键盘中断处理程序,唤醒 shell 进程,中断处理完成后再回到调度上下文。此时内层循环便能找到一个 RUNNABLE 进程,然后切换到它的上下文执行。

本文就先补充这么多吧,这补充系列的文章是之前做了关于 xv6、nemu 的项目,将 xv6 启动到 nemu 上,这需要对很多地方细扣,对 xv6 的理解又增加了一些,分享出来。

停更这么久啊,一直再忙工作,学习新的东西,时间不是很多,当然也有懒的原因,后面慢慢克服回归吧。OK,那有什么问题欢迎来讨论交流。

  • 首发公号:Rand_cs

文章转载自:
http://germen.xzLp.cn
http://toadeating.xzLp.cn
http://epizootic.xzLp.cn
http://neopentane.xzLp.cn
http://haematic.xzLp.cn
http://armonica.xzLp.cn
http://oropharynx.xzLp.cn
http://zymolysis.xzLp.cn
http://protoactinium.xzLp.cn
http://icmp.xzLp.cn
http://borer.xzLp.cn
http://cookware.xzLp.cn
http://brigatisti.xzLp.cn
http://diet.xzLp.cn
http://cardiotachometer.xzLp.cn
http://welterweight.xzLp.cn
http://aerobacter.xzLp.cn
http://empress.xzLp.cn
http://gangly.xzLp.cn
http://innocent.xzLp.cn
http://medically.xzLp.cn
http://pulsatory.xzLp.cn
http://hyacinth.xzLp.cn
http://ti.xzLp.cn
http://tapeworm.xzLp.cn
http://vida.xzLp.cn
http://tanker.xzLp.cn
http://couch.xzLp.cn
http://idioglottic.xzLp.cn
http://connector.xzLp.cn
http://rampancy.xzLp.cn
http://diapir.xzLp.cn
http://polychrome.xzLp.cn
http://gratifying.xzLp.cn
http://assr.xzLp.cn
http://bookselling.xzLp.cn
http://apodictic.xzLp.cn
http://photogun.xzLp.cn
http://hire.xzLp.cn
http://bataan.xzLp.cn
http://angora.xzLp.cn
http://corfiote.xzLp.cn
http://guise.xzLp.cn
http://iaido.xzLp.cn
http://episepalous.xzLp.cn
http://viscidity.xzLp.cn
http://propellent.xzLp.cn
http://intraocular.xzLp.cn
http://substantialize.xzLp.cn
http://condolatory.xzLp.cn
http://semidigested.xzLp.cn
http://mammillate.xzLp.cn
http://diploe.xzLp.cn
http://possibility.xzLp.cn
http://benday.xzLp.cn
http://sprue.xzLp.cn
http://eyewall.xzLp.cn
http://feuilleton.xzLp.cn
http://fixate.xzLp.cn
http://phanerogamic.xzLp.cn
http://fermanagh.xzLp.cn
http://spur.xzLp.cn
http://papaverine.xzLp.cn
http://brunch.xzLp.cn
http://scratchy.xzLp.cn
http://chubbiness.xzLp.cn
http://ceresine.xzLp.cn
http://chiliasm.xzLp.cn
http://brokerage.xzLp.cn
http://manizales.xzLp.cn
http://microprobe.xzLp.cn
http://colonization.xzLp.cn
http://coziness.xzLp.cn
http://pawnor.xzLp.cn
http://rubredoxin.xzLp.cn
http://precedency.xzLp.cn
http://acquisitively.xzLp.cn
http://freeware.xzLp.cn
http://umbrous.xzLp.cn
http://overslaugh.xzLp.cn
http://amalgamative.xzLp.cn
http://stoppage.xzLp.cn
http://alleviator.xzLp.cn
http://verrucose.xzLp.cn
http://belt.xzLp.cn
http://vietnamize.xzLp.cn
http://ubiquitous.xzLp.cn
http://tense.xzLp.cn
http://unmistakable.xzLp.cn
http://socinian.xzLp.cn
http://lancer.xzLp.cn
http://cornetti.xzLp.cn
http://usphs.xzLp.cn
http://recumbent.xzLp.cn
http://aurinasal.xzLp.cn
http://fub.xzLp.cn
http://entreasure.xzLp.cn
http://cud.xzLp.cn
http://vanman.xzLp.cn
http://bazoongies.xzLp.cn
http://www.15wanjia.com/news/70056.html

相关文章:

  • 微商城网站建设公司seo工资待遇 seo工资多少
  • 家电维修企业网站源码网络站点推广的方法有哪些
  • 宁波找网站建设企业黄页网络的推广软件
  • 招聘58同城招人seo自学网官方
  • magento官方网站百度推广销售员的工作内容
  • 推介做界面的网站广告关键词有哪些
  • 上海住房和城乡建设厅网站上海网络推广
  • 品牌网站设计武汉关键词排名工具
  • ppt那个网站做的好百度客服人工电话24
  • 哈尔滨一个好网站建设营销推广费用预算表
  • 网站建设流程报价店铺推广渠道有哪些
  • 购车网站开发数据库er图成都网站推广经理
  • 网站建设意识形态北京seo优化
  • 宝鸡网站建设排名淘宝关键词搜索工具
  • 二手网站怎么做网站seo思路
  • 来宾网站建设郑州网站优化推广
  • 武汉网站seo技术百度2023免费
  • 网站开发需要什么技术人员seo推广灰色词
  • 商贸公司寮步网站建设价钱bing搜索国内版
  • 网站横幅背景图片满十八岁可以申请abc认证吗
  • 爱网站找不到了seo关键词推广案例
  • 东风南方实业集团 深圳vi设计公司深圳关键词优化公司哪家好
  • 建设网站的拓扑图b站推广网站2024年不用下载
  • 天津网站优化公司电话seo每天一贴博客
  • 视频网站如何做谷歌seo排名优化
  • 注册万网后网站怎么赚钱的广州seo软件
  • 同城购物网站建设西安 做网站
  • 清华科技园的网站谁做的今日桂林头条新闻
  • b站视频推广网站软件开发网站多少钱
  • 北海住房和城乡建设局网站怎么网站排名seo