📄 kernel_timers.html
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head> <title></title> <link rel="stylesheet" media="screen" type="text/css" href="./style.css" /> <link rel="stylesheet" media="screen" type="text/css" href="./design.css" /> <link rel="stylesheet" media="print" type="text/css" href="./print.css" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body><a href=start.html>start</a></br><div class="toc"><div class="tocheader toctoggle" id="toc__header">Table of Contents</div><div id="toc__inside"><ul class="toc"><li class="clear"><ul class="toc"><li class="level2"><div class="li"><span class="li"><a href="#kernel_timers" class="toc">Kernel Timers</a></span></div><ul class="toc"><li class="level3"><div class="li"><span class="li"><a href="#all_about_jiffies" class="toc">All About Jiffies</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#stopping_timers" class="toc">Stopping Timers</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#repeating_timers" class="toc">Repeating Timers</a></span></div></li></ul></li></ul></li></ul></div></div><h2><a name="kernel_timers" id="kernel_timers">Kernel Timers</a></h2><div class="level2"><p> These will execute a function at some time in the future, They are simple to use.</p><p>The timer structure is defined in the include file <strong>linux/timer.h</strong> the important parts are shown here</p><pre class="code c"><span class="kw4">struct</span> timer_list <span class="br0">{</span> <span class="kw4">struct</span> list_head entry; <span class="kw4">unsigned</span> <span class="kw4">long</span> expires; <span class="co1">// time in jiffies to expire</span> spinlock_t lock; <span class="kw4">unsigned</span> <span class="kw4">long</span> magic; <span class="kw4">void</span> <span class="br0">(</span>*<span class="kw2">function</span><span class="br0">)</span><span class="br0">(</span><span class="kw4">unsigned</span> <span class="kw4">long</span><span class="br0">)</span>; <span class="co1">// function to run</span> <span class="kw4">unsigned</span> <span class="kw4">long</span> data; <span class="co1">// some data for the function</span> <span class="kw4">struct</span> tvec_t_base_s *base;<span class="br0">}</span>; </pre><p>The resolution of a timer is restricted to the CPU tick rate. This is limited to 1K Hz in most 2.6 kernels (2.6.13 reduced it to 250 Hz)</p><p>Higher resolution timers are avaialble as a kernel patch. These add a element to the structure called sub_expires to give greater resolution but they also need a dedicated high resolution timer.</p><p>The basic timer is simply designed to execute some time in the future. </p><p>Once kernel code includes the <strong>linux/timer.h</strong> file a timer can be simply set up as follows ( from <strong>drivers/char/vt.c</strong> )</p><pre class="code c"> <span class="co2">#include <linux/timer.h></span> <span class="kw4">static</span> <span class="kw4">struct</span> timer_list console_timer; </pre><p>It is most important to initialize the timer structure or BAD THINGS™ will happen.</p><pre class="code c"> <span class="co1">// somewhere in the set up code</span> init_timer<span class="br0">(</span>&console_timer<span class="br0">)</span>; </pre><p> Next set up a function to be called when the timer expires</p><pre class="code c"> console_timer.<span class="kw2">function</span> = blank_screen_t </pre><p> There are two functions taht can be used to trigger the timer. </p><ul><li class="level1"><div class="li"> add_timer - here you need to set up the expires time</div></li><li class="level1"><div class="li"> mod_timer - the expired time is an argument </div></li></ul><pre class="code c"> <span class="co1">// trigger the timer to expire some time in the future</span> mod_timer<span class="br0">(</span>&console_timer, jiffies + blankinterval<span class="br0">)</span>; </pre></div><!-- SECTION [1-1803] --><h3><a name="all_about_jiffies" id="all_about_jiffies">All About Jiffies</a></h3><div class="level3"><p> A Jiffie is a kernel global variable that tells you how many system timer ticks have expired since the system was booted.</p><p> It’s definition is hiding in the linker script</p><pre class="code c"> <span class="co1">// extract from **arch/blackfin/kernel/vmlinux.lds.S**</span> OUTPUT_FORMAT<span class="br0">(</span><span class="st0">"elf32-bfin"</span><span class="br0">)</span> ENTRY<span class="br0">(</span>_start<span class="br0">)</span> jiffies = jiffies_64; MEMORY ....</pre><p>You will find <strong>jiffies_64</strong> in the file <strong>include/linux/jiffies.h</strong></p><p>Things are done like this to allow jiffies to be defined at link time as either a 64 bit or a 32 bit number. For this architecture they are a 64 bit number.</p><p>Since the element in the timer_list structure is an <strong>unsigned long</strong> you can imagine that there is some clever work going on behind the scenes to make this function.</p></div><!-- SECTION [1804-2575] --><h3><a name="stopping_timers" id="stopping_timers">Stopping Timers</a></h3><div class="level3"><p> So timers are quite easy to get started. How about stopping them. Well this may give us a problem. Especially when we are using more than one CPU.</p><p>CPU 0 may decide to delete a timer at exactly the same time as CPU 1 decides to execute the timer function.</p><p>For this reason special care is taken when deleting timers on SMP systems.</p><p>For most cases the following code will delete a timer.</p><p>del_timer will return a 1 if it detects a timer in progress.</p><pre class="code c"> del_timer<span class="br0">(</span>&console_timer<span class="br0">)</span>; </pre></div><!-- SECTION [2576-3106] --><h3><a name="repeating_timers" id="repeating_timers">Repeating Timers</a></h3><div class="level3"><p> Sometimes a timer function reschedules the timer to repeat the function some time in the future.</p><p>These timers can be difficult to stop. The preferred way is to provide a condition for the mod timer function.</p><p>In the example below a variable <strong>still_going</strong> has to be <strong>true</strong> for the timer to keep rescheduling </p><pre class="code c"><span class="kw4">struct</span> completion timer_done;<span class="kw4">int</span> still_going; <span class="co1">// add this somewhere else before using the completion thing</span> init_completion<span class="br0">(</span>&timer_done<span class="br0">)</span>; <span class="kw4">void</span> timer_function <span class="br0">{</span> <span class="kw4">unsigned</span> <span class="kw4">long</span> next_time = <span class="nu0">24</span>; <span class="kw1">if</span> <span class="br0">(</span>still_going<span class="br0">)</span> <span class="br0">{</span> mod_timer<span class="br0">(</span>&console_timer, jiffies + next_time<span class="br0">)</span>; <span class="br0">}</span> <span class="kw1">else</span> <span class="br0">{</span> complete<span class="br0">(</span>&timer_done<span class="br0">)</span>; <span class="br0">}</span> <span class="br0">}</span></pre><p> In the above example one way to close down the timer could be</p><pre class="code c"> still_going = <span class="nu0">0</span>; mod_timer<span class="br0">(</span>&console_timer, jiffies + <span class="nu0">1</span><span class="br0">)</span>; wait_for_completion<span class="br0">(</span>&timer_done<span class="br0">)</span>; </pre></div><!-- SECTION [3107-] --></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -