⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 00000045.htm

📁 一份很好的linux入门资料
💻 HTM
📖 第 1 页 / 共 5 页
字号:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list_del(&amp;p-run_list);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list_add_tail(&amp;p-run_list,&nbsp;&amp;runqueue_head);&nbsp;<BR>}&nbsp;<BR>static&nbsp;inline&nbsp;void&nbsp;move_first_runqueue(struct&nbsp;task_struct&nbsp;*&nbsp;p)&nbsp;<BR>{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list_del(&amp;p-run_list);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list_add(&amp;p-run_list,&nbsp;&amp;runqueue_head);&nbsp;<BR>}&nbsp;<BR>2.5&nbsp;Wait&nbsp;Queues&nbsp;<BR>When&nbsp;a&nbsp;process&nbsp;requests&nbsp;the&nbsp;kernel&nbsp;to&nbsp;do&nbsp;something&nbsp;which&nbsp;is&nbsp;currently&nbsp;imposs&nbsp;<BR>ible&nbsp;but&nbsp;that&nbsp;may&nbsp;become&nbsp;possible&nbsp;later,&nbsp;the&nbsp;process&nbsp;is&nbsp;put&nbsp;to&nbsp;sleep&nbsp;and&nbsp;is&nbsp;&nbsp;<BR>woken&nbsp;up&nbsp;when&nbsp;the&nbsp;request&nbsp;is&nbsp;more&nbsp;likely&nbsp;to&nbsp;be&nbsp;satisfied.&nbsp;One&nbsp;of&nbsp;the&nbsp;kernel&nbsp;&nbsp;<BR>mechanisms&nbsp;used&nbsp;for&nbsp;this&nbsp;is&nbsp;called&nbsp;a&nbsp;'wait&nbsp;queue'.&nbsp;<BR>Linux&nbsp;implementation&nbsp;allows&nbsp;wake-on&nbsp;semantics&nbsp;using&nbsp;TASK_EXCLUSIVE&nbsp;flag.&nbsp;Wit&nbsp;<BR>h&nbsp;waitqueues&nbsp;you&nbsp;can&nbsp;either&nbsp;use&nbsp;a&nbsp;well-known&nbsp;queue&nbsp;and&nbsp;then&nbsp;simply&nbsp;sleep_on/&nbsp;<BR>sleep_on_timeout/interruptible_sleep_on/interruptible_sleep_on_timeout&nbsp;or&nbsp;yo&nbsp;<BR>u&nbsp;can&nbsp;define&nbsp;your&nbsp;own&nbsp;waitqueue&nbsp;and&nbsp;use&nbsp;add/remove_wait_queue&nbsp;to&nbsp;add&nbsp;and&nbsp;rem&nbsp;<BR>ove&nbsp;yourself&nbsp;from&nbsp;it&nbsp;and&nbsp;also&nbsp;wake_up/wake_up_interruptible&nbsp;to&nbsp;wake&nbsp;up&nbsp;when&nbsp;&nbsp;<BR>needed.&nbsp;<BR>An&nbsp;example&nbsp;of&nbsp;the&nbsp;first&nbsp;usage&nbsp;of&nbsp;waiteueus&nbsp;is&nbsp;interaction&nbsp;between&nbsp;page&nbsp;alloc&nbsp;<BR>ator&nbsp;mm/page_alloc.c:__alloc_pages()&nbsp;using&nbsp;the&nbsp;well-known&nbsp;queue&nbsp;kswapd_wait&nbsp;&nbsp;<BR>declared&nbsp;in&nbsp;mm/vmscan.c&nbsp;and&nbsp;on&nbsp;which&nbsp;kswap&nbsp;kernel&nbsp;daemon&nbsp;is&nbsp;sleeping&nbsp;in&nbsp;mm/v&nbsp;<BR>mscan.c:kswap()&nbsp;and&nbsp;is&nbsp;woken&nbsp;up&nbsp;when&nbsp;page&nbsp;allocator&nbsp;needs&nbsp;to&nbsp;free&nbsp;up&nbsp;some&nbsp;pa&nbsp;<BR>ges.&nbsp;<BR>An&nbsp;example&nbsp;of&nbsp;autonomous&nbsp;waitqueue&nbsp;usage&nbsp;is&nbsp;interaction&nbsp;between&nbsp;user&nbsp;process&nbsp;<BR>&nbsp;requesting&nbsp;data&nbsp;via&nbsp;read(2)&nbsp;system&nbsp;call&nbsp;and&nbsp;kernel&nbsp;running&nbsp;in&nbsp;the&nbsp;interrupt&nbsp;<BR>&nbsp;context&nbsp;to&nbsp;supply&nbsp;the&nbsp;data.&nbsp;An&nbsp;interrupt&nbsp;handler&nbsp;might&nbsp;look&nbsp;like&nbsp;(simplifie&nbsp;<BR>d&nbsp;drivers/char/rtc_interrupt()):&nbsp;<BR>static&nbsp;DECLARE_WAIT_QUEUE_HEAD(rtc_wait);&nbsp;<BR>void&nbsp;rtc_interrupt(int&nbsp;irq,&nbsp;void&nbsp;*dev_id,&nbsp;struct&nbsp;pt_regs&nbsp;*regs)&nbsp;<BR>{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spin_lock(&amp;rtc_lock);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rtc_irq_data&nbsp;=&nbsp;CMOS_READ(RTC_INTR_FLAGS);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spin_unlock(&amp;rtc_lock);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wake_up_interruptible(&amp;rtc_wait);&nbsp;<BR>}&nbsp;<BR>so,&nbsp;the&nbsp;interrupt&nbsp;handler&nbsp;obtains&nbsp;the&nbsp;data&nbsp;by&nbsp;reading&nbsp;from&nbsp;some&nbsp;device-speci&nbsp;<BR>fic&nbsp;io&nbsp;port&nbsp;(CMOS_READ()&nbsp;macro&nbsp;turns&nbsp;into&nbsp;a&nbsp;couple&nbsp;outb/inb)&nbsp;and&nbsp;then&nbsp;wakes&nbsp;&nbsp;<BR>up&nbsp;whoever&nbsp;is&nbsp;sleeping&nbsp;on&nbsp;the&nbsp;rtc_wait&nbsp;wait&nbsp;queue.&nbsp;<BR>Now,&nbsp;the&nbsp;read(2)&nbsp;system&nbsp;call&nbsp;could&nbsp;be&nbsp;implemented&nbsp;as:&nbsp;<BR>ssize_t&nbsp;rtc_read(struct&nbsp;file&nbsp;file,&nbsp;char&nbsp;*buf,&nbsp;size_t&nbsp;count,&nbsp;loff_t&nbsp;*ppos)&nbsp;<BR>{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DECLARE_WAITQUEUE(wait,&nbsp;current);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;long&nbsp;data;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ssize_t&nbsp;retval;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add_wait_queue(&amp;rtc_wait,&nbsp;&amp;wait);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current-state&nbsp;=&nbsp;TASK_INTERRUPTIBLE;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spin_lock_irq(&amp;rtc_lock);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data&nbsp;=&nbsp;rtc_irq_data;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rtc_irq_data&nbsp;=&nbsp;0;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spin_unlock_irq(&amp;rtc_lock);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(data&nbsp;!=&nbsp;0)&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(file-f_flags&nbsp;&amp;&nbsp;O_NONBLOCK)&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;retval&nbsp;=&nbsp;-EAGAIN;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;goto&nbsp;out;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(signal_pending(current))&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;retval&nbsp;=&nbsp;-ERESTARTSYS;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;goto&nbsp;out;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;schedule();&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;while(1);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;retval&nbsp;=&nbsp;put_user(data,&nbsp;(unsigned&nbsp;long&nbsp;*)buf);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!retval)&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;retval&nbsp;=&nbsp;sizeof(unsigned&nbsp;long);&nbsp;<BR>out:&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current-state&nbsp;=&nbsp;TASK_RUNNING;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remove_wait_queue(&amp;rtc_wait,&nbsp;&amp;wait);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;retval;&nbsp;<BR>}&nbsp;<BR>What&nbsp;happens&nbsp;in&nbsp;rtc_read()&nbsp;is&nbsp;this:&nbsp;<BR>1.&nbsp;We&nbsp;declare&nbsp;a&nbsp;wait&nbsp;queue&nbsp;element&nbsp;pointing&nbsp;to&nbsp;current&nbsp;process&nbsp;context&nbsp;<BR>2.&nbsp;We&nbsp;add&nbsp;this&nbsp;element&nbsp;to&nbsp;the&nbsp;rtc_wait&nbsp;waitqueue&nbsp;<BR>3.&nbsp;We&nbsp;mark&nbsp;current&nbsp;context&nbsp;as&nbsp;TASK_INTERRUPTIBLE&nbsp;which&nbsp;means&nbsp;it&nbsp;will&nbsp;not&nbsp;be&nbsp;&nbsp;<BR>rescheduled&nbsp;after&nbsp;the&nbsp;next&nbsp;time&nbsp;it&nbsp;sleeps&nbsp;<BR>4.&nbsp;We&nbsp;check&nbsp;if&nbsp;there&nbsp;is&nbsp;no&nbsp;data&nbsp;available,&nbsp;if&nbsp;there&nbsp;is&nbsp;we&nbsp;break&nbsp;out,&nbsp;copy&nbsp;da&nbsp;<BR>ta&nbsp;to&nbsp;user&nbsp;buffer,&nbsp;mark&nbsp;ourselves&nbsp;as&nbsp;TASK_RUNNING,&nbsp;remove&nbsp;from&nbsp;the&nbsp;wait&nbsp;queu&nbsp;<BR>e&nbsp;and&nbsp;return&nbsp;<BR>5.&nbsp;If&nbsp;there&nbsp;is&nbsp;no&nbsp;data&nbsp;yet&nbsp;we&nbsp;check&nbsp;if&nbsp;user&nbsp;specified&nbsp;non-blocking&nbsp;io&nbsp;and&nbsp;if&nbsp;<BR>&nbsp;so&nbsp;we&nbsp;fail&nbsp;with&nbsp;EAGAIN&nbsp;(which&nbsp;is&nbsp;the&nbsp;same&nbsp;as&nbsp;EWOULDBLOCK)&nbsp;<BR>6.&nbsp;We&nbsp;also&nbsp;check&nbsp;if&nbsp;a&nbsp;signal&nbsp;is&nbsp;pending&nbsp;and&nbsp;if&nbsp;so&nbsp;inform&nbsp;the&nbsp;&quot;higher&nbsp;layers&quot;&nbsp;<BR>&nbsp;to&nbsp;restart&nbsp;the&nbsp;system&nbsp;call&nbsp;if&nbsp;necessary.&nbsp;By&nbsp;&quot;if&nbsp;necessary&quot;&nbsp;I&nbsp;meant&nbsp;the&nbsp;deta&nbsp;<BR>ils&nbsp;of&nbsp;signal&nbsp;disposition&nbsp;as&nbsp;specified&nbsp;in&nbsp;sigaction(2)&nbsp;system&nbsp;call&nbsp;<BR>7.&nbsp;Then&nbsp;we&nbsp;&quot;switch&nbsp;out&quot;,&nbsp;i.e.&nbsp;fall&nbsp;asleep.&nbsp;until&nbsp;woken&nbsp;up&nbsp;by&nbsp;the&nbsp;interrupt&nbsp;h&nbsp;<BR>andler.&nbsp;If&nbsp;we&nbsp;didn't&nbsp;mark&nbsp;ourselves&nbsp;as&nbsp;TASK_INTERRUPTIBLE&nbsp;then&nbsp;the&nbsp;scheduler&nbsp;<BR>&nbsp;could&nbsp;schedule&nbsp;as&nbsp;sooner&nbsp;than&nbsp;when&nbsp;the&nbsp;data&nbsp;is&nbsp;available&nbsp;and&nbsp;cause&nbsp;unneeded&nbsp;<BR>&nbsp;processing&nbsp;<BR>It&nbsp;is&nbsp;also&nbsp;worth&nbsp;pointing&nbsp;out&nbsp;that&nbsp;using&nbsp;wait&nbsp;queues&nbsp;it&nbsp;is&nbsp;rather&nbsp;easy&nbsp;to&nbsp;im&nbsp;<BR>plement&nbsp;poll(2)&nbsp;system&nbsp;call:&nbsp;<BR>static&nbsp;unsigned&nbsp;int&nbsp;rtc_poll(struct&nbsp;file&nbsp;*file,&nbsp;poll_table&nbsp;*wait)&nbsp;<BR>{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;long&nbsp;l;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;poll_wait(file,&nbsp;&amp;rtc_wait,&nbsp;wait);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spin_lock_irq(&amp;rtc_lock);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l&nbsp;=&nbsp;rtc_irq_data;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spin_unlock_irq(&amp;rtc_lock);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(l&nbsp;!=&nbsp;0)&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;POLLIN&nbsp;|&nbsp;POLLRDNORM;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;&nbsp;<BR>}&nbsp;<BR>All&nbsp;the&nbsp;work&nbsp;is&nbsp;done&nbsp;by&nbsp;device-independent&nbsp;function&nbsp;poll_wait()&nbsp;which&nbsp;does&nbsp;t&nbsp;<BR>he&nbsp;necessary&nbsp;waitqueue&nbsp;manipulations&nbsp;all&nbsp;we&nbsp;need&nbsp;is&nbsp;to&nbsp;point&nbsp;it&nbsp;to&nbsp;the&nbsp;waitq&nbsp;<BR>ueue&nbsp;which&nbsp;is&nbsp;woken&nbsp;up&nbsp;by&nbsp;our&nbsp;device-specific&nbsp;interrupt&nbsp;handler.&nbsp;<BR>2.6&nbsp;Kernel&nbsp;Timers&nbsp;<BR>Now&nbsp;let&nbsp;us&nbsp;turn&nbsp;our&nbsp;attention&nbsp;to&nbsp;kernel&nbsp;timers.&nbsp;Kernel&nbsp;timers&nbsp;are&nbsp;used&nbsp;to&nbsp;di&nbsp;<BR>spatch&nbsp;execution&nbsp;of&nbsp;a&nbsp;particular&nbsp;function&nbsp;(called&nbsp;'timer&nbsp;handler')&nbsp;at&nbsp;a&nbsp;spec&nbsp;<BR>ified&nbsp;time&nbsp;in&nbsp;the&nbsp;future.&nbsp;The&nbsp;main&nbsp;data&nbsp;structure&nbsp;is&nbsp;'struct&nbsp;timer_list'&nbsp;dec&nbsp;<BR>lared&nbsp;in&nbsp;include/linux/timer.h:&nbsp;<BR>struct&nbsp;timer_list&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;list_head&nbsp;list;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;long&nbsp;expires;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbs

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -