2.6内核抢占的新特性

内核抢占补丁在2.5系列中就已被打上,接下来在2.6中也会打。这将显著地降低用户交互式应用程式、多媒体应用程式等类似应用程式的延迟。这一特性对实时系统和嵌入式系统来说特别有用。
2.5的内核抢占模块的工作由 Robert Love 完成。在先前的内核版本中(包括2.4内核),不允许抢占以内核模式运行的任务(包括通过系统调用进入内核模式的用户任务),直到他们自己主动释放 CPU。
在内核2.6中,内核是可抢占的。一个内核任务能被抢占,为的是让重要的用户应用程式能继续运行。这样做最主要的优势在于,能极大地增强系统的用户交互性,用户将会觉得鼠标点击和击键的事件得到了更快速的响应。
当然,不是所有的内核代码段都能被抢占。能锁定内核代码的关键部分,不允许抢占。锁定能确保每个 CPU 的数据结构和状态始终受到保护而不被抢占。
以下的代码片断显示了每个 CPU 的数据结构问题(在SMP系统中):
清单 1. 存在内核抢占问题的代码
          int arr[NR_CPUS];
          arr[smp_processor_id()] = i;
          /* kernel preemption could happen here */
          j = arr[smp_processor_id()]   /* i and j are not equal as
   smp_processor_id() may not be the same */
在这种情形下,如果在特定点发生了内核抢占,任务将会由于重新调度而被分配到其他处理器??smp_processor_id() 将返回一个不同的值。
这种情形应该通过锁定来进行保护。
FPU 模式是另外一种CPU应该被保护起来不被抢占的情形。当内核在执行浮点指令时,FPU 状态不被保存。如果这时发生了抢占,由于重新调度,FPU 状态就会和抢占前完全不同。所以 FPU 代码必须始终被锁定,以防止内核抢占。
锁定能这样来实现,在关键部分禁止抢占,在之后再激活抢占。以下是在2.6内核中禁止和激活抢占的定义:

  • preempt_enable() -- 抢占计数器减1
  • preempt_disable() -- 抢占计数器加1
  • get_cpu() -- 先后调用 preempt_disable() 和 smp_processor_id()
  • put_cpu() -- 重新激活preemption()
    使用这些定义,清单 1能重写成这样:
    清单 2. 使用防抢占锁的代码
            int cpu, arr[NR_CPUS];
             arr[get_cpu()] = i;  /* disable preemption */
             j = arr[smp_processor_id()];
             /* do some critical stuff here */
             put_cpu()    /* re-enable preemption */
    注意 preempt_disable()/enable()调用是能嵌套的。也就是说,preempt_disable() 能被调用 n 次,只有当第 n 次 preempt_enable() 被调用后,抢占才被重新激活。
    当使用自旋锁时,抢占是被隐式地禁止的。例如,一个 spin_lock_irqsave() 调用会隐式地通过调用 preempt_disable() 来防止抢占;spin_unlock_irqrestroe() 通过调用 preempt_enable() 来重新激活抢占。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值