📄 00000012.htm
字号:
<BR>Linux包含两种类型的系统定时器,它们都可以在某个系统时间上被队列例程使用, <BR>但是它们的实现稍有区别。 <BR> <BR>第一个是老的定时器机制,它包含指向timer_struct结构的32位指针的静态数组以 <BR>及当前活动定时器的屏蔽码:time_active。 <BR> <BR>此定时器表中的位置是静态定义的(类似底层部分处理表bh_base)。其入口在系 <BR>统初始化时被加入到表中。第二种是相对较新的定时器,它使用一个到期时间以升 <BR>序排列的timer_list结构链表。 <BR> <BR>这两种方法都使用jiffies作为终结时间,这样希望运行5秒的定时器将不得不将5秒 <BR>时间转换成jiffies的单位并且将它和以jiffies记数的当前系统时间相加从而得到 <BR>定时器的终结时间。在每个系统时钟滴答时,定时器的底层部分处理过程被标记成活 <BR>动状态以便调度管理器下次运行时能进行定时器队列的处理。定时器底层部分处理 <BR>过程包含两种类型的系统定时器。老的系统定时器将检查timer_active位是否置位。 <BR> <BR>如果活动定时器已经到期则其定时器例程将被调用同时它的活动位也被清除。新定 <BR>时器位于timer_list结构链表中的入口也将受到检查。每个过期定时器将从链表中 <BR>清除,同时它的例程将被调用。新定时器机制的优点之一是能传递一个参数给定时器 <BR>例程。 <BR> <BR> <BR> <BR>11.4 等待队列 <BR> <BR>进程经常要等待某个系统资源。例如某个进程可能需要描叙文件系统中某个目录的VFS <BR>inode但是此inode可 能不在buffercache中。此时这个进程必须等到该inode从包含此 <BR>文件系统的物理介质中取出来才可以继续运行。 <BR> <BR> wait_queue <BR> *task <BR> *next <BR> <BR> 等待队列 <BR> <BR>Linux核心使用一个非常简单的队列:等待队列(见图11.4)。它包含一个指向进程 <BR>task_struct结构的指针以及等待队列中下一个元素的指针。加入到等待队列中的进程 <BR>既可以是可中断也可以是不可中断的。可中断进程能够被如定时器到期或者信号等时间 <BR>中断。此等待进程的状态必须说明成是INTERRUPTIBLE还是UNINTERRUPTIBLE。由于进程 <BR>现在不能继续运行则调度管理器将接过系统控制权并选择一个新进程运行而等待进程将 <BR>被挂起。处理等待进程时,每个处于等待队列中的进程都被置为RUNNING状态。如果此 <BR>进程已经从运行队列中删除则它将被重新放入运行队列。下次调度管理器运行时,由于 <BR>这些进程不再等待所以它们都将是运行候选者。等待队列可以用来同步对系统资源的访问, <BR>同时它们还被Linux用于信号灯的实现中。 <BR> <BR>11.5 Buzz 锁 <BR> <BR>它使用更频繁的名字叫自旋锁。这是一种保护数据结构或代码片段的原始方式。在某个 <BR>时刻只允许一个进程访问临界区内的代码。Linux还同时将一个整数域作为锁来限制对数 <BR>据结构中某些域的存取。每个希望进入此区域的进程都试图将此锁的初始值从0改成1。 <BR>如果当前值是1则进程将再次尝试,此时进程好象在一段紧循环代码中自旋。对包含此 <BR>锁的内存区域的存取必须是原子性的,即检验值是否为0并将其改变成1的过程不能被任 <BR>何进程中断。多数CPU结构通过特殊指令提供对此方式的支持,同时我们可以在一个非缓 <BR>冲主存中实现这个流言锁。 <BR> <BR>当控制进程离开临界区时它将递减此Buzz锁。任何处于自旋状态的进程都可以读取它, <BR>它们中最快的那个将递增此值并进入临界区。 <BR> <BR>11.6 信号灯 <BR> <BR>信号灯被用来保护临界区中的代码和数据。请记住每次对临界区数据,如描叙某个目录 <BR>VFS inode的访问,是通过代表进程的核心代码来进行的。允许某个进程擅自修改由其他 <BR>进程使用的临界区数据是非常危险的。防止此问题发生的一种方式是在被存取临界区 <BR>周围使用buzz锁,但这种简单的方式将降低系统性能。Linux使用信号灯来迫使某个时 <BR>刻只有唯一进程访问临界区代码和数据,其他进程都必须等待资源被释放才可使用。这 <BR>些等待进程将被挂起而系统中其他进程可以继续运行。 <BR> <BR>一个Linux semaphore结构包含了以下信息: <BR> <BR>count <BR> 此域用来保存希望访问此资源的文件个数。当它为正数时表示资源可用。负数和0 <BR> 表示进程必须等待。当它初始值为1时表示一次仅允许一个进程来访问此资源。当 <BR> 进程需要此资源时它们必须将此count值减1并且在使用完后将其加1。 <BR>waking <BR> 这是等待此资源的进程个数,同时也是当资源可利用时等待被唤醒的进程个数。 <BR>wait queue <BR> 当进程等待此资源时,它们被放入此等待队列。 <BR>lock 访问waking域时使用的buzz锁。 <BR> <BR>假设此信号灯的初始值为1,第一个使用它的进程看到此记数为正数,然后它将其减去1 <BR>而得到0。现在此进程拥有了这些被信号灯保护的段代码和资源。当此进程离开临界区 <BR>时它将增加此信号灯的记数值,最好的情况是没有其他进程与之争夺临界区的控制权。 <BR>Linux将信号灯设计成能在多数情况下有效工作。 <BR> <BR>如果此时另外一个进程希望进入此已被别的进程占据的临界区时,它也将此记数减1。 <BR>当它看到此记数值为-1则它知道现在不能进入临界区,必须等待到此进程退出使用临界 <BR>区为止。在这个过程中Linux将让这个等待进程睡眠。等待进程将其自身添加到信号灯 <BR>的等待队列中然后系统在一个循环中检验waking域的值并当waking非0时调用调度管理器。 <BR> <BR>临界区的所有者将信号灯记数值加1,但是如果此值仍然小于等于0则表示还有等待此 <BR>资源的进程在睡眠。在理想情况下此信号灯的记数将返回到初始值1而无需做其他工作。 <BR>所有者进程将递增waking记数并唤醒在此信号灯等待队列上睡眠的进程。当等待进程醒 <BR>来时,它发现waking记数值已为1,那么它知道现在可以进入临界区了。然后它将递减 <BR>waking记数,将其变成0并继续。所有对信号灯waking域的访问都将受到使用信号灯的 <BR>buzz锁的保护。 <BR> <BR> <BR>-- <BR>※ 来源:·BBS 水木清华站 bbs.net.tsinghua.edu.cn·[FROM: 202.114.2.2] <BR><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -