内核抢占[转]

与其他大部分Unix变体和其他大部分的操作系统不同, Linux完整地支持内核抢占。

在不支持内核抢占的内核中,内核代码可以一直执行,到它完成为止。也就是说,调度程序没有办法在一个内核级的任务正在执行的时候重新调度 — 内核中的各任务是协作方式调度的,不具备抢占性。

在2.6版的内核中,内核引人了抢占能力;现在,只要重新调度是安全的,那么内核就可以在任何时间抢占正在执行的任务。

那么,什么时候重新调度才是安全的呢?只要没有持有锁,内核就可以进行抢占。锁是非抢占区域的标志。由于内核是支持SMP的,所以,如果没有持有锁,那么正在执行的代码就是可重新导入的,也就是可以抢占的。

为了支持内核抢占所作的第一处变动就是每个进程的thread_info引入了preempt_count(thread_info.preempt_count)计数器。该计数器初始值为0,每当使用锁的时候数值加1,释放锁的时候数值减1。当数值为0的时候,内核就可执行抢占。从中断返回内核空间的时候,内核会检查need_resched和preempt_count的值。如果need_resched被设置,并且preempt_count为0的话,这说明有一个更为重要的任务需要执行并且可以安全地抢占,此时,调度程序就会调度(抢占当前进程)。如果preempt_count不为0,说明当前任务持有锁,所以抢占是不安全的。这时,就会像通常那样直接从中断返回当前执行进程。如果当前进程所持有的所有的锁都被释放了。那么preempt_count就会重新为0。此时,释放锁的代码会检查need_resched是否被设置。如果是的话,就会调用调度程序。有些内核代码需要允许或禁止内核抢占。

如果内核中的进程被阻塞了,或它显式地调用了schedule(),内核抢占也会显式地发生。这种形式的内核代码从来都是受支持的,因为根本无需额外的逻辑来保证内核可以安全地发生被抢占。如果代码显式的调用了schedule(),那么它应该清楚自己是可以安全地被抢占的。

内核抢占发生在:

  1. 当”从中断处理程序”正在执行,且返回内核空间之前
  2. 内核代码再一次具有可抢占性的时候
  3. 如果内核中的任务显式的调用schedule()
  4. 如果内核中的任务阻塞(这同样也会导致调用schedule())

并发与同步

两个或多个线程同时操作同一资源时将产生不一致的情况,这就是所谓的竞态。竞态的产生皆源于并发,加入每次只有一个线程运行,自然不会产生竞态条件。并发是计算机发展的趋势,自然不能因咽废食,只要足够细心,竞态条件总是可以轻易避开。

并发是竞态之源。有两种所谓的并发,一种是将任务分为一个个小片段,多个任务交替执行,从而宏观上产生多个任务同时执行的假象,这就是俗称的“假并发”。另外一种是在对称多处理器(SMP),多个线程在不同的CPU核中同时运行,这就是所谓的“真并发”。在对称多处理器中,为了增加处理器的利用率,CPU核之间进行真并发处理的同时每个CPU核又在进行假并发处理。

我们通常将可能被多个线程同时操作的代码段称为临界区。临界区中的代码必须被互斥执行,也就是说如果有线程进入了该段代码,其他线程就不得进入,只有进入临界区的线程退出该区后,其他线程才可以试图进入。实现互斥进入临界区的方式是加锁,每把锁配上一把钥匙,谁抢到钥匙谁就可以进入临界区,并在退出时归还钥匙,然后其他线程再来抢这把钥匙。加锁是一种同步方法,使各个线程可以根据某种协议进入临界区修改其中的代码而不会产生不一致的情况。

编程小技巧

#define OK_STAT(stat,good,bad)  (((stat)&((good)|(bad)))==(good))

该宏用于测试IDE硬盘的状态寄存器,只出现good状态,而无bad状态是返回真。

383 typedef union {
384         unsigned all                    : 8;
385         struct {
386 #if defined(__LITTLE_ENDIAN_BITFIELD)
387                 unsigned head           : 4;
388                 unsigned unit           : 1;
389                 unsigned bit5           : 1;
390                 unsigned lba            : 1;
391                 unsigned bit7           : 1;
392 #elif defined(__BIG_ENDIAN_BITFIELD)
393                 unsigned bit7           : 1;
394                 unsigned lba            : 1;
395                 unsigned bit5           : 1;
396                 unsigned unit           : 1;
397                 unsigned head           : 4;
398 #else
399 #error “Please fix <asm/byteorder.h>”
400 #endif
401         } b;
402 } select_t, ata_select_t;
该结构体定义既可以获取all成员而得到整个结构体的值,也可以通过b结构体获取各个位。

消隐

电子枪从左到右画出象素,它每次只能画一条扫描线,画下一条之前要先回到左边并做好画下一条扫描线的准备,这之间有一段时间叫做水平消隐(HBlank)。在画完全部扫描线(行)之后它又回到屏幕左上角准备下一次画屏幕(帧),这之间的一段时间就是垂直消隐(VBlank)。

颜色空间

颜色空间是颜色集合的数学表示。三个最常用的颜色模型分别是:RGB;YIQ、YUV或YCbCr;CMYK。这三种颜色空间分别用于计算机图形学、视频系统和彩色答应。尽管所有这些颜色空间都是相互关联,并可以相互转化,但他们之间还是有相当的差异,对他们的处理和使用也会不同。所有颜色空间都能够有RGB信息推导而来,摄像机和扫描仪都采用RGB信息。

RGB颜色空间

RGB颜色空间使用红绿蓝三种颜色相加来形成所需的颜色,广泛用于计算机图形学和显示器。RGB颜色空间存在许多不同类型的实现,包括sRGB和scRGB等,sRGB是RGB颜色空间的规范化,而scRGB颜色空间扩展了sRGB的动态范围、颜色范围和位精度。

YUV颜色空间

YUV颜色空间是三大符合颜色视频标准PAL、NTSC和SECAM所采用的颜色空间。YUV中的“Y”表示明亮度(Luminance、Luma),“U”和“V”则是色度浓度(Chrominance、Chroma)。与RGB颜色空间不同,YUV颜色空间中的亮度信息和颜色信息相分离,可以单独修改亮度信息或颜色信息。

YIQ颜色空间

YIQ颜色空间是有YUV颜色空间推导而来,YIQ中的Y与YUV颜色空间中的Y分量相同,都是表示亮度,而I则代表“同相”,Q代表“正交”。

YCbCr颜色空间

YCbCr颜色空间是YUV颜色空间的缩放和偏移版本。Y定义为具有8位,标称颜色表示范围为16~235;Cb和Cr标称颜色表示范围定义为16~240。YCbCr有多种采样格式,包括4:4:4、4:2:2、4:1:1和4:2:0等。

4:4:4 YCbCr格式

在4:4:4的YCbCr采样格式中,每个采样点有Y、Cb和Cr值,每个颜色值的各个分量具有典型的8位(消费类应用)或10位(专业视频应用),因此每个采样点需要24位或30位。

4:2:2 YCbCr格式

在4:2:2的YCbCr采样格式中,每2个水平Y采样点才有一个Cb和一个Cr采样点。当每个采样颜色值的各颜色分量为8位时,则每个采样点平均需要16位。

4:1:1 YCbCr格式

在4:1:1的YCbCr采样格式中,每4个水平Y采样点才有一个Cb和一个Cr采样点。当每个采样颜色值的各颜色分量为8位时,则每个采样点平均需要12位。

4:2:0 YCbCr格式

在4:2:0的YCbCr采样格式中,每两个水平Y采样点采样一个Cb或Cr,Cb和Cr交替采样。当每个采样颜色值的各颜色分量为8位时,则每个采样点平均需要12位。

为了显示4:2:0的YCbCr数据,首先要转换为4:4:4的YCbCr数据,这需要通过插值来生成丢失的Cb和Cr采样信息。需要注意的是,有些解并不能正确地将4:2:0的YCbCr数据转换为4:4:4格式的数据,因而导致“色度陷阱”。

视频分辨率

标准清晰度

标准清晰度视频定义为具有480或576的隔行有效扫描线的视频,分别称为“480i”和“576i”。

增强清晰度

增强清晰度视频定义为具有480或576逐行有效扫描线的视频,分别称为“480p”和“576p”。

高清清晰度

高清晰度视频定义为具有720逐行或1080隔行有效扫描线的视频,分别称为720p和1080i。

视频码率

固定码率

固定码率是指编码器的输出码率是固定值,这样可以更好的控制通信信道的使用,使编码器的输出码率能够满足信道带宽的约束。但固定码率有两个主要的缺点:

  1. 复杂的视音频信号经过编码后需要更多的码率来传输,如果码率固定,则编码器将强制减少码率的输出,导致信号质量的下降;
  2. 简单的信号需要更少的码率,为了保证码率的不变,编码器可能需要往数据流中加入无效的数据,浪费了带宽。

可变码率

可变码率是指编码器的输出码率是可变的,编码器可以根据输入信号的类型自动调整输出码率,这样避免了固定码率的既有缺点,既保证了输出信号的质量,同时不会浪费不必要的空间。

现在几乎所有视频编码器都是使用可变码率。

平均码率

简单来说就是文件大小除以时间。平均码率很难精确控制,可以通过二次编码部分实现。

最高码率

码率峰值,当码率峰值高过处理器所能处理的强度时,可能会造成播放延迟。