几年前,我在面试现在的公司的时候,被问过一个很经典的问题
抢占式的内核是怎么工作的?
那个时候我对OS的调度流程理解很肤浅,并且也没有过hands-on experiences,读Linux内核的一些书其实也没有真正理解整个软件+硬件的行为。
只能凭着过去 CS 537和本科时候一点OS课的经验,泛泛的回答了一点 time slice,调度器,优先级之类的名词,结合自己想象中的流程瞎扯了一通。
听完我的回答后,我还记得谷雨并不满意的说道,“不是这样的。” 我们那个时候在用RTOS,做开发时,对进程调度,抢占式内核的理解是很重要的。
不过谢天谢地,最后大佬们还是offer了我,把对OS渣理解的我捞了起来。但是这个事情让我一直耿耿于怀,以至于后面有机会学习6.828的JOS,真正自己动手做round-robin的调度器、抢占式内核的时候,这个知识点还是我着重想去理解的地方。
闲话少说,关于JOS的preemptive multitasking,这里记录一些重要的细节以及个人理解:
The IF (interrupt-enable flag) controls the acceptance of external interrupts signalled via the INTR pin. When IF=0, INTR interrupts are inhibited; when IF=1, INTR interrupts are enabled. As with the other flag bits, the processor clears IF in response to a RESET signal. The instructions CLI and STI alter the setting of IF.
CLI (Clear Interrupt-Enable Flag) and STI (Set Interrupt-Enable Flag) explicitly alter IF (bit 9 in the flag register). These instructions may be executed only if CPL <= IOPL. A protection exception occurs if they are executed when CPL > IOPL.
The IF is also affected implicitly by the following operations:
Interrupts through interrupt gates automatically reset IF, disabling interrupts. (Interrupt gates are explained later in this chapter.)
(x86 i386手册)
我们用了 i386 interupt gates注册了INT 31和所有的外部中断,所以发生系统调用和外部中断的时候,会自动reset EFLAGS里的IF 。
SETGATE(idt[T_SYSCALL], 0, GD_KT, t48_entry, 3);
SETGATE(idt[IRQ_OFFSET + IRQ_TIMER], 0, GD_KT, irq_timer, 0);
1 // Set up a normal interrupt/trap gate descriptor.
2 // - istrap: 1 for a trap (= exception) gate, 0 for an interrupt gate.
3 // see section 9.6.1.3 of the i386 reference: "The difference between
4 // an interrupt gate and a trap gate is in the effect on IF (the
5 // interrupt-enable flag). An interrupt that vectors through an
6 // interrupt gate resets IF, thereby preventing other interrupts from
7 // interfering with the current interrupt handler. A subsequent IRET
8 // instruction restores IF to the value in the EFLAGS image on the
9 // stack. An interrupt through a trap gate does not change IF."
10 // - sel: Code segment selector for interrupt/trap handler
11 // - off: Offset in code segment for interrupt/trap handler
12 // - dpl: Descriptor Privilege Level -
13 // the privilege level required for software to invoke
14 // this interrupt/trap gate explicitly using an int instruction.
15 #define SETGATE(gate, istrap, sel, off, dpl) \
16 { \
17 (gate).gd_off_15_0 = (uint32_t) (off) & 0xffff; \
18 (gate).gd_sel = (sel); \
19 (gate).gd_args = 0; \
20 (gate).gd_rsv1 = 0; \
21 (gate).gd_type = (istrap) ? STS_TG32 : STS_IG32; \
22 (gate).gd_s = 0; \
23 (gate).gd_dpl = (dpl); \ (gate).gd_p = 1; \
24 (gate).gd_off_31_16 = (uint32_t) (off) >> 16; \
25 }
env_pop_tf(struct Trapframe *tf)
{
// Record the CPU we are running on for user-space debugging
curenv->env_cpunum = cpunum();
asm volatile( "\tmovl %0,%%esp\n"
"\tpopal\n"
"\tpopl %%es\n"
"\tpopl %%ds\n"
"\taddl $0x8,%%esp\n" /* skip tf_trapno and tf_errcode */
"\tiret\n"
: : "g" (tf) : "memory");
panic("iret failed"); /* mostly to placate the compiler */ }

先写到这里吧
在Ruby(1.8.X)中为什么Object既继承了内核又包含了内核?仅仅继承还不够吗?irb(main):006:0>Object.ancestors=>[Object,Kernel]irb(main):005:0>Object.included_modules=>[Kernel]irb(main):011:0>Object.superclass=>nil请注意,在Ruby1.9中情况类似(但更简洁):irb(main):001:0>Object.ancestors=>[Object,Kernel,BasicObject]irb(main):002:0>Object.included
我有一个正在开发的命令行Ruby应用程序,我想允许它的用户提供将在部分过程中作为过滤器运行的代码。基本上,应用程序是这样做的:读入一些数据如果指定了过滤器,则使用它来过滤数据处理数据我希望过滤过程(第2步)尽可能灵活。我的想法是,用户可以提供一个Ruby文件,该文件设置一个已知常量以指向实现我定义的接口(interface)的对象,例如:#user'sfilterclassMyFilterdefdo_filter(array_to_filter)filtered_array=Array.new#domyfilteringonarray_to_filterfiltered_arrayen
在Ruby中的面向对象设计一书中,SandiMetz说模块的主要用途是用它们实现鸭子类型,并将它们包含在每个需要的类中。为什么RubyKernel是包含在Object中的模块?据我所知,它没有在其他任何地方使用。使用模块有什么意义? 最佳答案 理想情况下,Methodsinspirit(适用于任何对象),即使用接收器的方法,应在Object上定义上课,而Procedures(全局提供),即忽略接收者的方法,应该收集在Kernel中模块。Kernel#puts,例如不对其接收者做任何事情;它不调用它的私有(private)方法,它不访
在笔者前面有一篇文章《驱动开发:断链隐藏驱动程序自身》通过摘除驱动的链表实现了断链隐藏自身的目的,但此方法恢复时会触发PG会蓝屏,偶然间在网上找到了一个作者介绍的一种方法,觉得有必要详细分析一下他是如何实现的进程隐藏的,总体来说作者的思路是最终寻找到MiProcessLoaderEntry的入口地址,该函数的作用是将驱动信息加入链表和移除链表,运用这个函数即可动态处理驱动的添加和移除问题。MiProcessLoaderEntry(pDriverObject->DriverSection,1)添加MiProcessLoaderEntry(pDriverObject->DriverSection,
在Ruby中,方法puts是Kernel的单例方法模块。通常,当一个模块是included或extend由另一个模块编辑,该模块(但不是它的单例类)被添加到继承树中。这有效地使模块的实例方法可用于模块或其单例类(分别用于include和extend)......但混合模块的单例方法仍然无法访问,因为单例类从未将模块添加到继承树中。那么为什么我可以使用puts(和其他内核单例方法)?Kernel.singleton_methods(false)#=>[:caller_locations,:local_variables,:require,:require_relative,:autolo
我是Sidekiq的新手,将它与AmazonEC2实例上的Ruby结合使用,以使用ImageMagick处理图像来完成一些工作。在运行它时,我意识到每个工作人员都在同一个核心上运行。我使用EC2c3.2xlarge机器,它们有8个内核。它显示CPU使用率为15%,但一个内核使用了100%,而其他内核使用了0%。Sidekiq可以为不同的worker使用不同的CPU内核吗?如果可以,这种低效率是由ImageMagic造成的吗?我怎样才能让它使用其他内核? 最佳答案 如果您想使用MRI使用多个内核,则需要启动多个Sidekiq进程;为您
我从Ruby开始,每天都在寻找新的、更短、更优雅的方式来编写代码。在解决ProjectEuler问题时,我写了很多类似的代码ifbest_score有没有更优雅的写法? 最佳答案 best_score=[best_score,current_score].max参见:可枚举。max免责声明:虽然这更具可读性(恕我直言),但性能较差:require'benchmark'best_score,current_score,n=1000,2000,100_000Benchmark.bmdo|x|x.report{n.timesdobest_
问题有没有可以保持的最佳值(value),这样我才能赢得尽可能多的比赛?如果是这样,那是什么?编辑:是否可以为给定的限制计算出确切的获胜概率,而与对手的所作所为无关?(自大学以来,我还没有做过概率和统计)。我有兴趣将其作为与模拟结果进行对比的答案。编辑:修复了我算法中的错误,更新了结果表。背景我一直在玩改进的二十一点游戏,其中对标准规则进行了一些相当烦人的规则调整。我已将与标准二十一点规则不同的规则斜体化,并为不熟悉的人添加了二十一点规则。修改二十一点规则正是两个人类玩家(经销商无关)每个玩家面朝下发两张牌双方玩家_ever_都不知道对手纸牌的_any_的值在_both_完成手牌之前,
原文链接,欢迎关注:你为什么学习Linux内核?-CodeAllen的回答-知乎https://www.zhihu.com/question/31369673/answer/2894981254主要是工作需要,其实对于我自己的工作来说,在Linux开发的具体业务和算法才是重要的,内核的知识并没有那么重要,对于很多应用开发来说也差不多,最多也是先看看用户态即可。但是出于对技术的追求还是在通过看书和阅读源码学习。书的话主要是看了下边本,其他乱七八糟的还有一些不列举了:深入Linux内核架构这本可能不是那么经典,看这本的原因是网上找到了高清的PDF书籍,于是就画时间看了,结论是非常不错,我很多内核的
我正在尝试向Kernel添加一个方法模块,而不是重新打开Kernel并直接定义一个实例方法,我正在编写一个模块,我想要Kernel至extend/include那个模块。moduleTalkdefhelloputs"hellothere"endendmoduleKernelextendTalkend当我在IRB中运行它时:$helloNameError:undefinedlocalvariableormethod`hello'formain:Objectfrom(irb):12from/Users/JackC/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16