﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-天下-随笔分类-kernel &amp; Driver</title><link>http://www.cppblog.com/aaxron/category/18045.html</link><description>记录修行的印记
</description><language>zh-cn</language><lastBuildDate>Mon, 24 Mar 2014 19:29:34 GMT</lastBuildDate><pubDate>Mon, 24 Mar 2014 19:29:34 GMT</pubDate><ttl>60</ttl><item><title>韦根驱动</title><link>http://www.cppblog.com/aaxron/archive/2014/03/21/206265.html</link><dc:creator>天下</dc:creator><author>天下</author><pubDate>Fri, 21 Mar 2014 09:33:00 GMT</pubDate><guid>http://www.cppblog.com/aaxron/archive/2014/03/21/206265.html</guid><wfw:comment>http://www.cppblog.com/aaxron/comments/206265.html</wfw:comment><comments>http://www.cppblog.com/aaxron/archive/2014/03/21/206265.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/aaxron/comments/commentRss/206265.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/aaxron/services/trackbacks/206265.html</trackback:ping><description><![CDATA[<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">types.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">module.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">init.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">poll.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">errno.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">gpio.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">interrupt.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">miscdevice.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">ioport.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">device.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">asm</span><span style="color: #000000">/</span><span style="color: #000000">io.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">asm</span><span style="color: #000000">/</span><span style="color: #000000">irq.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">mach</span><span style="color: #000000">/</span><span style="color: #000000">irqs.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">mach</span><span style="color: #000000">/</span><span style="color: #000000">regs</span><span style="color: #000000">-</span><span style="color: #000000">gpio.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /><br />#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">../ioctl_new.h</span><span style="color: #000000">"</span><span style="color: #000000"><br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;spinlock_t&nbsp;&nbsp;&nbsp;&nbsp;wiegand_lock;<br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in_cur&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in_stime&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in1_stime&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in2_stime&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;unsigned&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;wiegand_data[</span><span style="color: #000000">40</span><span style="color: #000000">];<br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;WIEGAND_TYPE&nbsp;&nbsp;&nbsp;&nbsp;wiegand_mode;<br /><br />inline&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;wiegand_delay(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;microseconds)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;(microseconds</span><span style="color: #000000">--</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;(i</span><span style="color: #000000">=</span><span style="color: #000000">0</span><span style="color: #000000">;&nbsp;i</span><span style="color: #000000">&lt;</span><span style="color: #000000">65</span><span style="color: #000000">;&nbsp;i</span><span style="color: #000000">++</span><span style="color: #000000">)&nbsp;__asm(</span><span style="color: #000000">"</span><span style="color: #000000">NOP</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;wiegand_gettickcount(</span><span style="color: #0000ff">void</span><span style="color: #000000">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;__start_time&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">second</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;timeval&nbsp;tv;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;do_gettimeofday(</span><span style="color: #000000">&amp;</span><span style="color: #000000">tv);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(__start_time&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__start_time&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;tv.tv_sec;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;((tv.tv_sec&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;__start_time)&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1000</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;tv.tv_usec&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1000</span><span style="color: #000000">);<br />}<br /><br />inline&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;wiegand_minus_interrupt(</span><span style="color: #0000ff">void</span><span style="color: #000000">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(wiegand_in&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;WGNSTAT_RECVFULL)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(wiegand_gettickcount()&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;wiegand_in_stime&nbsp;</span><span style="color: #000000">&gt;=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">100</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in_cur&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in_stime&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;wiegand_gettickcount();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_data[wiegand_in_cur</span><span style="color: #000000">++</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(wiegand_in_cur&nbsp;</span><span style="color: #000000">&gt;=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">34</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;WGNSTAT_RECVFULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(wiegand_in_cur&nbsp;</span><span style="color: #000000">&gt;=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">26</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;WGNSTAT_RECV26;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br />inline&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;wiegand_plus_interrupt(</span><span style="color: #0000ff">void</span><span style="color: #000000">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(wiegand_in&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;WGNSTAT_RECVFULL)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(wiegand_gettickcount()&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;wiegand_in_stime&nbsp;</span><span style="color: #000000">&gt;=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">100</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in_cur&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in_stime&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;wiegand_gettickcount();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_data[wiegand_in_cur</span><span style="color: #000000">++</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(wiegand_in_cur&nbsp;</span><span style="color: #000000">&gt;=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">34</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;WGNSTAT_RECVFULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(wiegand_in_cur&nbsp;</span><span style="color: #000000">&gt;=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">26</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;WGNSTAT_RECV26;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;irqreturn_t&nbsp;wiegand_minus1_interrupt(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;irq,&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">dev_id)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;spin_lock(</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_lock);<br /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;printk("wiegand_minus1_interrupt\n");</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(wiegand_gettickcount()&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;wiegand_in2_stime&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">200</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_minus_interrupt();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in1_stime&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;wiegand_in_stime;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;spin_unlock(</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_lock);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;IRQ_HANDLED;<br />}<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;irqreturn_t&nbsp;wiegand_plus1_interrupt(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;irq,&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">dev_id)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;spin_lock(</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_lock);<br /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;printk("wiegand_plus1_interrupt\n");</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(wiegand_gettickcount()&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;wiegand_in2_stime&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">200</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_plus_interrupt();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in1_stime&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;wiegand_in_stime;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;spin_unlock(</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_lock);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;IRQ_HANDLED;<br />}<br /><br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;wiegand_open(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;inode&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;inode,&nbsp;</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;filp);<br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;wiegand_release(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;inode&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;inode,</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;filp);<br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;ssize_t&nbsp;wiegand_read(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">flip,&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">buf,&nbsp;size_t&nbsp;len,&nbsp;loff_t&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">pos);<br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;ssize_t&nbsp;wiegand_write(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">flip,&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">buf,&nbsp;size_t&nbsp;len,&nbsp;loff_t&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">pos);<br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">long</span><span style="color: #000000">&nbsp;wiegand_ioctl(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">file,&nbsp;unsigned&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;cmd,&nbsp;unsigned&nbsp;</span><span style="color: #0000ff">long</span><span style="color: #000000">&nbsp;arg);<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file_operations&nbsp;wiegand_fops&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;owner:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;THIS_MODULE,<br />&nbsp;&nbsp;&nbsp;&nbsp;open:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_open,<br />&nbsp;&nbsp;&nbsp;&nbsp;release:&nbsp;&nbsp;&nbsp;&nbsp;wiegand_release,<br />&nbsp;&nbsp;&nbsp;&nbsp;read:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_read,<br />&nbsp;&nbsp;&nbsp;&nbsp;write:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_write,<br />&nbsp;&nbsp;&nbsp;&nbsp;unlocked_ioctl:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_ioctl,<br />};<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;miscdevice&nbsp;wiegand_dev&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;WIEGAND_MINOR,<br />&nbsp;&nbsp;&nbsp;&nbsp;WIEGAND_MODULE_NAME,<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_fops<br />};<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;config_wiegand_pins(</span><span style="color: #0000ff">void</span><span style="color: #000000">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;s3c2410_gpio_cfgpin(WGNIN_0,&nbsp;WGNIN_0_CON);<br />&nbsp;&nbsp;&nbsp;&nbsp;s3c2410_gpio_cfgpin(WGNIN_1,&nbsp;WGNIN_1_CON);<br />&nbsp;&nbsp;&nbsp;&nbsp;s3c2410_gpio_cfgpin(WGNOUT0,&nbsp;WGNOUT0_CON);<br />&nbsp;&nbsp;&nbsp;&nbsp;s3c2410_gpio_cfgpin(WGNOUT1,&nbsp;WGNOUT1_CON);<br /></span><span style="color: #0000ff">#if</span><span style="color: #000000">&nbsp;0</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(request_irq(WGNIN_0_IRQ_NUM,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_minus1_interrupt,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IORESOURCE_IRQ&nbsp;</span><span style="color: #000000">|</span><span style="color: #000000">&nbsp;IRQF_TRIGGER_RISING,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WIEGAND_IRQ_MINUS,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_dev)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">||</span><span style="color: #000000">&nbsp;request_irq(WGNIN_1_IRQ_NUM,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_plus1_interrupt,&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IORESOURCE_IRQ&nbsp;</span><span style="color: #000000">|</span><span style="color: #000000">&nbsp;IRQF_TRIGGER_RISING,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WIEGAND_IRQ_PLUS,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_dev))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk(</span><span style="color: #000000">"</span><span style="color: #000000">WIEGAND&nbsp;request_irq&nbsp;Fail\n</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #0000ff">#endif</span><span style="color: #000000"><br />}<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;wiegand_open(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;inode&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;inode,&nbsp;</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;filp)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;config_wiegand_pins();<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />}<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;wiegand_release(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;inode&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;inode,</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;filp)<br />{<br /></span><span style="color: #0000ff">#if</span><span style="color: #000000">&nbsp;0</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;free_irq(WGNIN_0_IRQ_NUM,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_dev);<br />&nbsp;&nbsp;&nbsp;&nbsp;free_irq(WGNIN_1_IRQ_NUM,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_dev);<br /></span><span style="color: #0000ff">#endif</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />}<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;ssize_t&nbsp;wiegand_read(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">flip,&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">buf,&nbsp;size_t&nbsp;len,&nbsp;loff_t&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">pos)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;result;<br />&nbsp;&nbsp;&nbsp;&nbsp;spin_lock(</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_lock);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(wiegand_in&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;WGNSTAT_NONE&nbsp;</span><span style="color: #000000">||</span><span style="color: #000000">&nbsp;len&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">sizeof</span><span style="color: #000000">(wiegand_data)&nbsp;</span><span style="color: #000000">||</span><span style="color: #000000">&nbsp;(wiegand_gettickcount()&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;wiegand_in_stime&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1800</span><span style="color: #000000">))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">500</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;WGNSTAT_NONE;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spin_unlock(</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_lock);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(len&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;wiegand_in_cur)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;len&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;wiegand_in_cur;<br />&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;copy_to_user(buf,&nbsp;wiegand_data,&nbsp;len);<br />&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;WGNSTAT_NONE;<br />&nbsp;&nbsp;&nbsp;&nbsp;wiegand_in_cur&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;spin_unlock(</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_lock);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;len;<br />}<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;ssize_t&nbsp;wiegand_write(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">flip,&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">buf,&nbsp;size_t&nbsp;len,&nbsp;loff_t&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">pos)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;data[</span><span style="color: #000000">40</span><span style="color: #000000">];<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(len&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">sizeof</span><span style="color: #000000">(data))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;i&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;copy_from_user(data,&nbsp;buf,&nbsp;len);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;(i</span><span style="color: #000000">=</span><span style="color: #000000">0</span><span style="color: #000000">;&nbsp;i</span><span style="color: #000000">&lt;</span><span style="color: #000000">len;&nbsp;i</span><span style="color: #000000">++</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(data[i]&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WGNOUT0_1;&nbsp;wiegand_delay(wiegand_mode.dwTpw);&nbsp;WGNOUT0_0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WGNOUT1_1;&nbsp;wiegand_delay(wiegand_mode.dwTpw);&nbsp;WGNOUT1_0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wiegand_delay(wiegand_mode.dwTpi);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;len;<br />}<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">long</span><span style="color: #000000">&nbsp;wiegand_ioctl(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">file,&nbsp;unsigned&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;cmd,&nbsp;unsigned&nbsp;</span><span style="color: #0000ff">long</span><span style="color: #000000">&nbsp;arg)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;result&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;spin_lock(</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_lock);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">switch</span><span style="color: #000000">(cmd)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">case</span><span style="color: #000000">&nbsp;WIEGAND_MODE_SET:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;copy_from_user(</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_mode,&nbsp;(</span><span style="color: #0000ff">void</span><span style="color: #000000">*</span><span style="color: #000000">)arg,&nbsp;</span><span style="color: #0000ff">sizeof</span><span style="color: #000000">(WIEGAND_TYPE));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">break</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;spin_unlock(</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_lock);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;(result&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">sizeof</span><span style="color: #000000">(WIEGAND_TYPE)&nbsp;</span><span style="color: #000000">?</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">&nbsp;:&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">);<br />}<br /><br /><br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;__init&nbsp;s3c2416_wiegand_init(</span><span style="color: #0000ff">void</span><span style="color: #000000">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;ret&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;misc_register(</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_dev);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(ret)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk(</span><span style="color: #000000">"</span><span style="color: #000000">probuck&nbsp;s3c2416&nbsp;WIEGAND&nbsp;Driver</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;WIEGAND_DRIVER_VERSION&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">Fail\n</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">goto</span><span style="color: #000000">&nbsp;exit_sb3kt_wiegand_init;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;spin_lock_init(</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_lock);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;printk(</span><span style="color: #000000">"</span><span style="color: #000000">probuck&nbsp;s3c2416&nbsp;WIEGAND&nbsp;Driver</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;WIEGAND_DRIVER_VERSION&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">\n</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />exit_sb3kt_wiegand_init:<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;ret;<br />}<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;__exit&nbsp;s3c2416_wiegand_cleanup(</span><span style="color: #0000ff">void</span><span style="color: #000000">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;misc_deregister(</span><span style="color: #000000">&amp;</span><span style="color: #000000">wiegand_dev);<br />}<br /><br />module_init(s3c2416_wiegand_init);<br />module_exit(s3c2416_wiegand_cleanup);<br />MODULE_LICENSE(</span><span style="color: #000000">"</span><span style="color: #000000">GPL</span><span style="color: #000000">"</span><span style="color: #000000">);<br /><br />MODULE_DESCRIPTION(</span><span style="color: #000000">"</span><span style="color: #000000">s3c2416&nbsp;WIEGAND&nbsp;Driver</span><span style="color: #000000">"</span><span style="color: #000000">);<br />MODULE_SUPPORTED_DEVICE(</span><span style="color: #000000">"</span><span style="color: #000000">s3c2416&nbsp;WIEGAND</span><span style="color: #000000">"</span><span style="color: #000000">);<br /><br /></span></div><img src ="http://www.cppblog.com/aaxron/aggbug/206265.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/aaxron/" target="_blank">天下</a> 2014-03-21 17:33 <a href="http://www.cppblog.com/aaxron/archive/2014/03/21/206265.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux内核的同步机制(2)信号量（semaphore）</title><link>http://www.cppblog.com/aaxron/archive/2013/04/12/199387.html</link><dc:creator>天下</dc:creator><author>天下</author><pubDate>Fri, 12 Apr 2013 10:22:00 GMT</pubDate><guid>http://www.cppblog.com/aaxron/archive/2013/04/12/199387.html</guid><wfw:comment>http://www.cppblog.com/aaxron/comments/199387.html</wfw:comment><comments>http://www.cppblog.com/aaxron/archive/2013/04/12/199387.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/aaxron/comments/commentRss/199387.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/aaxron/services/trackbacks/199387.html</trackback:ping><description><![CDATA[<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->Linux内核的同步机制(2)信号量（semaphore）<br /><br />　　信号量在创建时需要设置一个初始值，表示同时可以有几个任务可以访问该信号量保护的共享资源，初始值为1就变成互斥锁（Mutex），即同时只能有一个任务可以访问信号量保护的共享资源。<br /><br />　　一个任务要想访问共享资源，首先必须得到信号量，获取信号量的操作将把信号量的值减1，若当前信号量的值为负数，表明无法获得信号量，该任务必须挂起在该信号量的等待队列等待该信号量可用；若当前信号量的值为非负数，表示可以获得信号量，因而可以立刻访问被该信号量保护的共享资源。<br /><br />　　当任务访问完被信号量保护的共享资源后，必须释放信号量，释放信号量通过把信号量的值加1实现，如果信号量的值为非正数，表明有任务等待当前信号量，因此它也唤醒所有等待该信号量的任务。<br /><br />信号量的API有：<br />DECLARE_MUTEX(name)<br />该宏声明一个信号量name并初始化它的值为1，即声明一个互斥锁。<br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">在Linux2.6.26中没找到该宏</span><span style="color: #008000; "><br /></span>DECLARE_MUTEX_LOCKED(name)<br />该宏声明一个互斥锁name，但把它的初始值设置为0，即锁在创建时就处在已锁状态。因此对于这种锁，一般是先释放后获得。<br /><br /><span style="color: #0000FF; ">void</span>&nbsp;sema_init&nbsp;(<span style="color: #0000FF; ">struct</span>&nbsp;semaphore&nbsp;*sem,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;val);<br />该函用于数初始化设置信号量的初值，它设置信号量sem的值为val。<br /><br /><span style="color: #0000FF; ">void</span>&nbsp;init_MUTEX&nbsp;(<span style="color: #0000FF; ">struct</span>&nbsp;semaphore&nbsp;*sem);<br />该函数用于初始化一个互斥锁，即它把信号量sem的值设置为1。<br /><br /><span style="color: #0000FF; ">void</span>&nbsp;init_MUTEX_LOCKED&nbsp;(<span style="color: #0000FF; ">struct</span>&nbsp;semaphore&nbsp;*sem);<br />该函数也用于初始化一个互斥锁，但它把信号量sem的值设置为0，即一开始就处在已锁状态。<br /><br /><span style="color: #0000FF; ">void</span>&nbsp;down(<span style="color: #0000FF; ">struct</span>&nbsp;semaphore&nbsp;*&nbsp;sem);<br />该函数用于获得信号量sem，它会导致睡眠，因此不能在中断上下文（包括IRQ上下文和softirq上下文）使用该函数。该函数将把sem的值减1，如果信号量sem的值非负，就直接返回，否则调用者将被挂起，直到别的任务释放该信号量才能继续运行。<br /><br /><span style="color: #0000FF; ">int</span>&nbsp;down_interruptible(<span style="color: #0000FF; ">struct</span>&nbsp;semaphore&nbsp;*&nbsp;sem);<br />该函数功能与down类似，不同之处为，down不会被信号（signal）打断，但down_interruptible能被信号打断，因此该函数有返回值来区分是正常返回还是被信号中断，如果返回0，表示获得信号量正常返回，如果被信号打断，返回-EINTR。<br /><br /><span style="color: #0000FF; ">int</span>&nbsp;down_trylock(<span style="color: #0000FF; ">struct</span>&nbsp;semaphore&nbsp;*&nbsp;sem);<br />该函数试着获得信号量sem，如果能够立刻获得，它就获得该信号量并返回0，否则，表示不能获得信号量sem，返回值为非0值。因此，它不会导致调用者睡眠，可以在中断上下文使用。<br /><br /><span style="color: #0000FF; ">void</span>&nbsp;up(<span style="color: #0000FF; ">struct</span>&nbsp;semaphore&nbsp;*&nbsp;sem);<br />该函数释放信号量sem，即把sem的值加1，如果sem的值为非正数，表明有任务等待该信号量，因此唤醒这些等待者。&nbsp;<br /><br />头文件:<br />#include&nbsp;&lt;linux/semaphore.h&gt;<br /><span style="color: #008000; ">/*</span><span style="color: #008000; "><br />&nbsp;*&nbsp;Copyright&nbsp;(c)&nbsp;2008&nbsp;Intel&nbsp;Corporation<br />&nbsp;*&nbsp;Author:&nbsp;Matthew&nbsp;Wilcox&nbsp;&lt;willy@linux.intel.com&gt;<br />&nbsp;*<br />&nbsp;*&nbsp;Distributed&nbsp;under&nbsp;the&nbsp;terms&nbsp;of&nbsp;the&nbsp;GNU&nbsp;GPL,&nbsp;version&nbsp;2<br />&nbsp;*<br />&nbsp;*&nbsp;Please&nbsp;see&nbsp;kernel/semaphore.c&nbsp;for&nbsp;documentation&nbsp;of&nbsp;these&nbsp;functions<br />&nbsp;</span><span style="color: #008000; ">*/</span><br />#ifndef&nbsp;__LINUX_SEMAPHORE_H<br /><span style="color: #0000FF; ">#define</span>&nbsp;__LINUX_SEMAPHORE_H<br /><br />#include&nbsp;&lt;linux/list.h&gt;<br />#include&nbsp;&lt;linux/spinlock.h&gt;<br /><br /><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;Please&nbsp;don't&nbsp;access&nbsp;any&nbsp;members&nbsp;of&nbsp;this&nbsp;structure&nbsp;directly&nbsp;</span><span style="color: #008000; ">*/</span><br /><span style="color: #0000FF; ">struct</span>&nbsp;semaphore&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;spinlock_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">lock</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">struct</span>&nbsp;list_head&nbsp;&nbsp;&nbsp;&nbsp;wait_list;<br />};<br /><br /><span style="color: #0000FF; ">#define</span>&nbsp;__SEMAPHORE_INITIALIZER(name,&nbsp;n)&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;.<span style="color: #0000FF; ">lock</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;__SPIN_LOCK_UNLOCKED((name).<span style="color: #0000FF; ">lock</span>),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;.count&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;n,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;.wait_list&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;LIST_HEAD_INIT((name).wait_list),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br />}<br /><br /><span style="color: #0000FF; ">#define</span>&nbsp;__DECLARE_SEMAPHORE_GENERIC(name,&nbsp;count)&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">struct</span>&nbsp;semaphore&nbsp;name&nbsp;=&nbsp;__SEMAPHORE_INITIALIZER(name,&nbsp;count)<br /><br /><span style="color: #0000FF; ">#define</span>&nbsp;DECLARE_MUTEX(name)&nbsp;&nbsp;&nbsp;&nbsp;__DECLARE_SEMAPHORE_GENERIC(name,&nbsp;1)<br /><br /><span style="color: #0000FF; ">static</span>&nbsp;inline&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;sema_init(<span style="color: #0000FF; ">struct</span>&nbsp;semaphore&nbsp;*sem,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;val)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">struct</span>&nbsp;lock_class_key&nbsp;__key;<br />&nbsp;&nbsp;&nbsp;&nbsp;*sem&nbsp;=&nbsp;(<span style="color: #0000FF; ">struct</span>&nbsp;semaphore)&nbsp;__SEMAPHORE_INITIALIZER(*sem,&nbsp;val);<br />&nbsp;&nbsp;&nbsp;&nbsp;lockdep_init_map(&amp;sem-&gt;<span style="color: #0000FF; ">lock</span>.dep_map,&nbsp;"semaphore-&gt;lock",&nbsp;&amp;__key,&nbsp;0);<br />}<br /><br /><span style="color: #0000FF; ">#define</span>&nbsp;init_MUTEX(sem)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sema_init(sem,&nbsp;1)<br /><span style="color: #0000FF; ">#define</span>&nbsp;init_MUTEX_LOCKED(sem)&nbsp;&nbsp;&nbsp;&nbsp;sema_init(sem,&nbsp;0)<br /><br /><span style="color: #0000FF; ">extern</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;down(<span style="color: #0000FF; ">struct</span>&nbsp;semaphore&nbsp;*sem);<br /><span style="color: #0000FF; ">extern</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;__must_check&nbsp;down_interruptible(<span style="color: #0000FF; ">struct</span>&nbsp;semaphore&nbsp;*sem);<br /><span style="color: #0000FF; ">extern</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;__must_check&nbsp;down_killable(<span style="color: #0000FF; ">struct</span>&nbsp;semaphore&nbsp;*sem);<br /><span style="color: #0000FF; ">extern</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;__must_check&nbsp;down_trylock(<span style="color: #0000FF; ">struct</span>&nbsp;semaphore&nbsp;*sem);<br /><span style="color: #0000FF; ">extern</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;__must_check&nbsp;down_timeout(<span style="color: #0000FF; ">struct</span>&nbsp;semaphore&nbsp;*sem,&nbsp;<span style="color: #0000FF; ">long</span>&nbsp;jiffies);<br /><span style="color: #0000FF; ">extern</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;up(<span style="color: #0000FF; ">struct</span>&nbsp;semaphore&nbsp;*sem);<br /><br /><span style="color: #0000FF; ">#endif</span>&nbsp;/*&nbsp;__LINUX_SEMAPHORE_H&nbsp;*/</div><img src ="http://www.cppblog.com/aaxron/aggbug/199387.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/aaxron/" target="_blank">天下</a> 2013-04-12 18:22 <a href="http://www.cppblog.com/aaxron/archive/2013/04/12/199387.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux内核的同步机制(1)自旋锁（spinlock）</title><link>http://www.cppblog.com/aaxron/archive/2013/04/12/199386.html</link><dc:creator>天下</dc:creator><author>天下</author><pubDate>Fri, 12 Apr 2013 10:21:00 GMT</pubDate><guid>http://www.cppblog.com/aaxron/archive/2013/04/12/199386.html</guid><wfw:comment>http://www.cppblog.com/aaxron/comments/199386.html</wfw:comment><comments>http://www.cppblog.com/aaxron/archive/2013/04/12/199386.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/aaxron/comments/commentRss/199386.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/aaxron/services/trackbacks/199386.html</trackback:ping><description><![CDATA[<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->Linux内核的同步机制(1)、自旋锁（spinlock）<br /><br />　　自旋锁与互斥锁有点类似，只是自旋锁不会引起调用者睡眠，如果自旋锁已经被别的执行单元保持，调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁，"自旋"一词就是因此而得名。<br /><br />　　由于自旋锁使用者一般保持锁时间非常短，因此选择自旋而不是睡眠是非常必要的，自旋锁的效率远高于互斥锁。<br /><br />　　信号量和读写信号量适合于保持时间较长的情况，它们会导致调用者睡眠，因此只能在进程上下文使用（_trylock的变种能够在中断上下文使用），而自旋锁适合于保持时间非常短的情况，它可以在任何上下文使用。<br /><br />　　如果被保护的共享资源只在进程上下文访问，使用信号量保护该共享资源非常合适，如果对共巷资源的访问时间非常短，自旋锁也可以。但是如果被保护的共享资源需要在中断上下文访问（包括底半部即中断处理句柄和顶半部即软中断），就必须使用自旋锁。<br /><br />　　自旋锁保持期间是抢占失效的，而信号量和读写信号量保持期间是可以被抢占的。自旋锁只有在内核可抢占或SMP的情况下才真正需要，在单CPU且不可抢占的内核下，自旋锁的所有操作都是空操作。<br /><br />　　跟互斥锁一样，一个执行单元要想访问被自旋锁保护的共享资源，必须先得到锁，在访问完共享资源后，必须释放锁。如果在获取自旋锁时，没有任何执行单元保持该锁，那么将立即得到锁；如果在获取自旋锁时锁已经有保持者，那么获取锁操作将自旋在那里，直到该自旋锁的保持者释放了锁。<br /><br />　　无论是互斥锁，还是自旋锁，在任何时刻，最多只能有一个保持者，也就说，在任何时刻最多只能有一个执行单元获得锁。<br /><br />自旋锁的API有：<br /><br />spin_lock_init(x)<br />该宏用于初始化自旋锁x。自旋锁在真正使用前必须先初始化。该宏用于动态初始化。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />DEFINE_SPINLOCK(x)<br />该宏声明一个自旋锁x并初始化它。该宏在2.6.11中第一次被定义，在先前的内核中并没有该宏。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />SPIN_LOCK_UNLOCKED<br />该宏用于静态初始化一个自旋锁。<br /><br />DEFINE_SPINLOCK(x)等同于spinlock_t&nbsp;x&nbsp;=&nbsp;SPIN_LOCK_UNLOCKED<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />spin_is_locked(x)<br />该宏用于判断自旋锁x是否已经被某执行单元保持（即被锁），如果是，返回真，否则返回假。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />spin_unlock_wait(x)<br />该宏用于等待自旋锁x变得没有被任何执行单元保持，如果没有任何执行单元保持该自旋锁，该宏立即返回，否则将循环在那里，直到该自旋锁被保持者释放。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />spin_trylock(<span style="color: #0000FF; ">lock</span>)<br />该宏尽力获得自旋锁lock，如果能立即获得锁，它获得锁并返回真，否则不能立即获得锁，立即返回假。它不会自旋等待lock被释放。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />spin_lock(<span style="color: #0000FF; ">lock</span>)<br />该宏用于获得自旋锁lock，如果能够立即获得锁，它就马上返回，否则，它将自旋在那里，直到该自旋锁的保持者释放，这时，它获得锁并返回。总之，只有它获得锁才返回。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />spin_lock_irqsave(<span style="color: #0000FF; ">lock</span>,&nbsp;flags)<br />该宏获得自旋锁的同时把标志寄存器的值保存到变量flags中并失效本地中断。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />spin_lock_irq(<span style="color: #0000FF; ">lock</span>)<br />该宏类似于spin_lock_irqsave，只是该宏不保存标志寄存器的值。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />spin_lock_bh(<span style="color: #0000FF; ">lock</span>)<br />该宏在得到自旋锁的同时失效本地软中断。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />spin_unlock(<span style="color: #0000FF; ">lock</span>)<br />该宏释放自旋锁lock，它与spin_trylock或spin_lock配对使用。如果spin_trylock返回假，表明没有获得自旋锁，因此不必使用spin_unlock释放。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />spin_unlock_irqrestore(<span style="color: #0000FF; ">lock</span>,&nbsp;flags)<br />该宏释放自旋锁lock的同时，也恢复标志寄存器的值为变量flags保存的值。它与spin_lock_irqsave配对使用。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />spin_unlock_irq(<span style="color: #0000FF; ">lock</span>)<br />该宏释放自旋锁lock的同时，也使能本地中断。它与spin_lock_irq配对应用。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />spin_unlock_bh(<span style="color: #0000FF; ">lock</span>)<br />该宏释放自旋锁lock的同时，也使能本地的软中断。它与spin_lock_bh配对使用。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />spin_trylock_irqsave(<span style="color: #0000FF; ">lock</span>,&nbsp;flags)<br />该宏如果获得自旋锁lock，它也将保存标志寄存器的值到变量flags中，并且失效本地中断，如果没有获得锁，它什么也不做。<br />　　因此如果能够立即获得锁，它等同于spin_lock_irqsave，如果不能获得锁，它等同于spin_trylock。如果该宏获得自旋锁lock，那需要使用spin_unlock_irqrestore来释放。<br /><br />spin_trylock_irq(<span style="color: #0000FF; ">lock</span>)<br />该宏类似于spin_trylock_irqsave，只是该宏不保存标志寄存器。如果该宏获得自旋锁lock，需要使用spin_unlock_irq来释放。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />spin_trylock_bh(<span style="color: #0000FF; ">lock</span>)<br />该宏如果获得了自旋锁，它也将失效本地软中断。如果得不到锁，它什么也不做。因此，如果得到了锁，它等同于spin_lock_bh，如果得不到锁，它等同于spin_trylock。如果该宏得到了自旋锁，需要使用spin_unlock_bh来释放。<br /><br />spin_can_lock(<span style="color: #0000FF; ">lock</span>)<br />该宏用于判断自旋锁lock是否能够被锁，它实际是spin_is_locked取反。如果lock没有被锁，它返回真，否则，返回假。该宏在2.6.11中第一次被定义，在先前的内核中并没有该宏。&nbsp;<br /><br />　　获得自旋锁和释放自旋锁有好几个版本，因此让读者知道在什么样的情况下使用什么版本的获得和释放锁的宏是非常必要的。&nbsp;<br /><br />　　如果被保护的共享资源只在进程上下文访问和软中断上下文访问，那么当在进程上下文访问共享资源时，可能被软中断打断，从而可能进入软中断上下文来对被保护的共享资源访问，因此对于这种情况，对共享资源的访问必须使用spin_lock_bh和spin_unlock_bh来保护。&nbsp;<br /><br />　　当然使用spin_lock_irq和spin_unlock_irq以及spin_lock_irqsave和spin_unlock_irqrestore也可以，它们失效了本地硬中断，失效硬中断隐式地也失效了软中断。但是使用spin_lock_bh和spin_unlock_bh是最恰当的，它比其他两个快。&nbsp;<br /><br />　　如果被保护的共享资源只在进程上下文和tasklet或timer上下文访问，那么应该使用与上面情况相同的获得和释放锁的宏，因为tasklet和timer是用软中断实现的。&nbsp;<br /><br />　　如果被保护的共享资源只在一个tasklet或timer上下文访问，那么不需要任何自旋锁保护，因为同一个tasklet或timer只能在一个CPU上运行，即使是在SMP环境下也是如此。实际上tasklet在调用tasklet_schedule标记其需要被调度时已经把该tasklet绑定到当前CPU，因此同一个tasklet决不可能同时在其他CPU上运行。&nbsp;<br /><br />　　timer也是在其被使用add_timer添加到timer队列中时已经被帮定到当前CPU，所以同一个timer绝不可能运行在其他CPU上。当然同一个tasklet有两个实例同时运行在同一个CPU就更不可能了。&nbsp;<br /><br />　　如果被保护的共享资源只在两个或多个tasklet或timer上下文访问，那么对共享资源的访问仅需要用spin_lock和spin_unlock来保护，不必使用_bh版本，因为当tasklet或timer运行时，不可能有其他tasklet或timer在当前CPU上运行。&nbsp;<br /><br />　　如果被保护的共享资源只在一个软中断（tasklet和timer除外）上下文访问，那么这个共享资源需要用spin_lock和spin_unlock来保护，因为同样的软中断可以同时在不同的CPU上运行。&nbsp;<br /><br />　　如果被保护的共享资源在两个或多个软中断上下文访问，那么这个共享资源当然更需要用spin_lock和spin_unlock来保护，不同的软中断能够同时在不同的CPU上运行。&nbsp;<br /><br />　　如果被保护的共享资源在软中断（包括tasklet和timer）或进程上下文和硬中断上下文访问，那么在软中断或进程上下文访问期间，可能被硬中断打断，从而进入硬中断上下文对共享资源进行访问，因此，在进程或软中断上下文需要使用spin_lock_irq和spin_unlock_irq来保护对共享资源的访问。&nbsp;<br /><br />　　而在中断处理句柄中使用什么版本，需依情况而定，如果只有一个中断处理句柄访问该共享资源，那么在中断处理句柄中仅需要spin_lock和spin_unlock来保护对共享资源的访问就可以了。&nbsp;<br /><br />　　因为在执行中断处理句柄期间，不可能被同一CPU上的软中断或进程打断。但是如果有不同的中断处理句柄访问该共享资源，那么需要在中断处理句柄中使用spin_lock_irq和spin_unlock_irq来保护对共享资源的访问。&nbsp;<br /><br />　　在使用spin_lock_irq和spin_unlock_irq的情况下，完全可以用spin_lock_irqsave和spin_unlock_irqrestore取代，那具体应该使用哪一个也需要依情况而定，如果可以确信在对共享资源访问前中断是使能的，那么使用spin_lock_irq更好一些。&nbsp;<br /><br />　　因为它比spin_lock_irqsave要快一些，但是如果你不能确定是否中断使能，那么使用spin_lock_irqsave和spin_unlock_irqrestore更好，因为它将恢复访问共享资源前的中断标志而不是直接使能中断。&nbsp;<br /><br />　　当然，有些情况下需要在访问共享资源时必须中断失效，而访问完后必须中断使能，这样的情形使用spin_lock_irq和spin_unlock_irq最好。&nbsp;<br /><br />　　需要特别提醒读者，spin_lock用于阻止在不同CPU上的执行单元对共享资源的同时访问以及不同进程上下文互相抢占导致的对共享资源的非同步访问，而中断失效和软中断失效却是为了阻止在同一CPU上软中断或中断对共享资源的非同步访问。&nbsp;&nbsp;&nbsp;&nbsp;<br />　　<br /><br />#include&nbsp;&lt;linux/spinlock.h&gt;<br /><br />头文件:<br />#include&lt;linux/spinlock_types.h&gt;<br /><br />#ifndef&nbsp;__LINUX_SPINLOCK_TYPES_H<br /><span style="color: #0000FF; ">#define</span>&nbsp;__LINUX_SPINLOCK_TYPES_H<br /><br /><span style="color: #008000; ">/*</span><span style="color: #008000; "><br />&nbsp;*&nbsp;include/linux/spinlock_types.h&nbsp;-&nbsp;generic&nbsp;spinlock&nbsp;type&nbsp;definitions<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;initializers<br />&nbsp;*<br />&nbsp;*&nbsp;portions&nbsp;Copyright&nbsp;2005,&nbsp;Red&nbsp;Hat,&nbsp;Inc.,&nbsp;Ingo&nbsp;Molnar<br />&nbsp;*&nbsp;Released&nbsp;under&nbsp;the&nbsp;General&nbsp;Public&nbsp;License&nbsp;(GPL).<br />&nbsp;</span><span style="color: #008000; ">*/</span><br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">对称多处理器</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">#if</span>&nbsp;defined(CONFIG_SMP)<br />&nbsp;&nbsp;&nbsp;&nbsp;#include&nbsp;&lt;asm/spinlock_types.h&gt;<br /><span style="color: #0000FF; ">#else</span><br />&nbsp;&nbsp;&nbsp;&nbsp;#include&nbsp;&lt;linux/spinlock_types_up.h&gt;<br /><span style="color: #0000FF; ">#endif</span><br /><br />#include&nbsp;&lt;linux/lockdep.h&gt;<br /><br />typedef&nbsp;<span style="color: #0000FF; ">struct</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;raw_spinlock_t&nbsp;raw_lock;<br />#ifdef&nbsp;CONFIG_GENERIC_LOCKBREAK<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;break_lock;<br /><span style="color: #0000FF; ">#endif</span><br />}&nbsp;spinlock_t;<br /><br /><span style="color: #0000FF; ">#define</span>&nbsp;SPINLOCK_MAGIC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0xdead4ead<br /><br />typedef&nbsp;<span style="color: #0000FF; ">struct</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;raw_rwlock_t&nbsp;raw_lock;<br />#ifdef&nbsp;CONFIG_GENERIC_LOCKBREAK<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;break_lock;<br /><span style="color: #0000FF; ">#endif</span><br />}&nbsp;rwlock_t;<br /><br /><span style="color: #0000FF; ">#define</span>&nbsp;RWLOCK_MAGIC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0xdeaf1eed<br /><br /><span style="color: #0000FF; ">#define</span>&nbsp;SPINLOCK_OWNER_INIT&nbsp;&nbsp;&nbsp;&nbsp;((void&nbsp;*)-1L)<br /><br />#&nbsp;define&nbsp;__SPIN_LOCK_UNLOCKED(lockname)&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;(spinlock_t)&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;.raw_lock&nbsp;=&nbsp;__RAW_SPIN_LOCK_UNLOCKED,&nbsp;&nbsp;&nbsp;&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SPIN_DEP_MAP_INIT(lockname)&nbsp;}<br /><span style="color: #0000FF; ">#define</span>&nbsp;__RW_LOCK_UNLOCKED(lockname)&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;(rwlock_t)&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;.raw_lock&nbsp;=&nbsp;__RAW_RW_LOCK_UNLOCKED,&nbsp;&nbsp;&nbsp;&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RW_DEP_MAP_INIT(lockname)&nbsp;}<br /><br /><span style="color: #008000; ">/*</span><span style="color: #008000; "><br />&nbsp;*&nbsp;SPIN_LOCK_UNLOCKED&nbsp;and&nbsp;RW_LOCK_UNLOCKED&nbsp;defeat&nbsp;lockdep&nbsp;state&nbsp;tracking&nbsp;and<br />&nbsp;*&nbsp;are&nbsp;hence&nbsp;deprecated.<br />&nbsp;*&nbsp;Please&nbsp;use&nbsp;DEFINE_SPINLOCK()/DEFINE_RWLOCK()&nbsp;or<br />&nbsp;*&nbsp;__SPIN_LOCK_UNLOCKED()/__RW_LOCK_UNLOCKED()&nbsp;as&nbsp;appropriate.<br />&nbsp;</span><span style="color: #008000; ">*/</span><br /><span style="color: #0000FF; ">#define</span>&nbsp;SPIN_LOCK_UNLOCKED&nbsp;&nbsp;&nbsp;&nbsp;__SPIN_LOCK_UNLOCKED(old_style_spin_init)<br /><span style="color: #0000FF; ">#define</span>&nbsp;RW_LOCK_UNLOCKED&nbsp;&nbsp;&nbsp;&nbsp;__RW_LOCK_UNLOCKED(old_style_rw_init)<br /><br /><span style="color: #0000FF; ">#define</span>&nbsp;DEFINE_SPINLOCK(x)&nbsp;&nbsp;&nbsp;&nbsp;spinlock_t&nbsp;x&nbsp;=&nbsp;__SPIN_LOCK_UNLOCKED(x)<br /><span style="color: #0000FF; ">#define</span>&nbsp;DEFINE_RWLOCK(x)&nbsp;&nbsp;&nbsp;&nbsp;rwlock_t&nbsp;x&nbsp;=&nbsp;__RW_LOCK_UNLOCKED(x)<br /><br /><span style="color: #0000FF; ">#endif</span>&nbsp;/*&nbsp;__LINUX_SPINLOCK_TYPES_H&nbsp;*/<br />　　</div><img src ="http://www.cppblog.com/aaxron/aggbug/199386.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/aaxron/" target="_blank">天下</a> 2013-04-12 18:21 <a href="http://www.cppblog.com/aaxron/archive/2013/04/12/199386.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[原]linux中断处理(2)下半部机制:tasklet</title><link>http://www.cppblog.com/aaxron/archive/2013/04/10/199306.html</link><dc:creator>天下</dc:creator><author>天下</author><pubDate>Wed, 10 Apr 2013 07:29:00 GMT</pubDate><guid>http://www.cppblog.com/aaxron/archive/2013/04/10/199306.html</guid><wfw:comment>http://www.cppblog.com/aaxron/comments/199306.html</wfw:comment><comments>http://www.cppblog.com/aaxron/archive/2013/04/10/199306.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/aaxron/comments/commentRss/199306.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/aaxron/services/trackbacks/199306.html</trackback:ping><description><![CDATA[<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->[原]linux中断处理(2)下半部机制:tasklet<br />1.softirq&nbsp;<br />适用于性能敏感的子系统<br /><br />2.tasklet<br />建立在softirq之上,使用更简单<br />softirq的不同实例可运行在不同的处理器上,而tasklet则不允许<br />必须使用define&nbsp;DECLARE_TASKLET&nbsp;声明tasklet<br /><span style="color: #0000FF; ">#define</span>&nbsp;DECLARE_TASKLET(name,&nbsp;func,&nbsp;data)&nbsp;\<br /><span style="color: #0000FF; ">struct</span>&nbsp;tasklet_struct&nbsp;name&nbsp;=&nbsp;{&nbsp;NULL,&nbsp;0,&nbsp;ATOMIC_INIT(0),&nbsp;func,&nbsp;data&nbsp;}<br /><br /><span style="color: #0000FF; ">void</span>&nbsp;short_do_tasklet(unsigned&nbsp;<span style="color: #0000FF; ">long</span>);<br />DECLARE_TASKLET(short_do_tasklet,short_tasklet,0);<br /><br />3.&nbsp;工作队列(work&nbsp;queue)<br /><span style="color: #0000FF; ">struct</span>&nbsp;work_struct&nbsp;my_work;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">定义一个工作队列</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">void</span>&nbsp;my_work_func(unsigned&nbsp;<span style="color: #0000FF; ">long</span>);&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">定义一个处理函数</span><span style="color: #008000; "><br /></span><br /><br /><br />头文件<br />#include&nbsp;&lt;linux/interrupt.h&gt;<br /><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;Tasklets&nbsp;---&nbsp;multithreaded&nbsp;analogue&nbsp;of&nbsp;BHs.<br /><br />Main&nbsp;feature&nbsp;differing&nbsp;them&nbsp;of&nbsp;generic&nbsp;softirqs:&nbsp;tasklet<br />is&nbsp;running&nbsp;only&nbsp;on&nbsp;one&nbsp;CPU&nbsp;simultaneously.<br /><br />Main&nbsp;feature&nbsp;differing&nbsp;them&nbsp;of&nbsp;BHs:&nbsp;different&nbsp;tasklets<br />may&nbsp;be&nbsp;run&nbsp;simultaneously&nbsp;on&nbsp;different&nbsp;CPUs.<br /><br />Properties:<br />*&nbsp;If&nbsp;tasklet_schedule()&nbsp;is&nbsp;called,&nbsp;then&nbsp;tasklet&nbsp;is&nbsp;guaranteed<br />to&nbsp;be&nbsp;executed&nbsp;on&nbsp;some&nbsp;cpu&nbsp;at&nbsp;least&nbsp;once&nbsp;after&nbsp;this.<br />*&nbsp;If&nbsp;the&nbsp;tasklet&nbsp;is&nbsp;already&nbsp;scheduled,&nbsp;but&nbsp;its&nbsp;excecution&nbsp;is&nbsp;still&nbsp;not<br />started,&nbsp;it&nbsp;will&nbsp;be&nbsp;executed&nbsp;only&nbsp;once.<br />*&nbsp;If&nbsp;this&nbsp;tasklet&nbsp;is&nbsp;already&nbsp;running&nbsp;on&nbsp;another&nbsp;CPU&nbsp;(or&nbsp;schedule&nbsp;is&nbsp;called<br />from&nbsp;tasklet&nbsp;itself),&nbsp;it&nbsp;is&nbsp;rescheduled&nbsp;for&nbsp;later.<br />*&nbsp;Tasklet&nbsp;is&nbsp;strictly&nbsp;serialized&nbsp;wrt&nbsp;itself,&nbsp;but&nbsp;not<br />wrt&nbsp;another&nbsp;tasklets.&nbsp;If&nbsp;client&nbsp;needs&nbsp;some&nbsp;intertask&nbsp;synchronization,<br />he&nbsp;makes&nbsp;it&nbsp;with&nbsp;spinlocks.<br /></span><span style="color: #008000; ">*/</span><br /><br /><span style="color: #0000FF; ">struct</span>&nbsp;tasklet_struct<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">struct</span>&nbsp;tasklet_struct&nbsp;*next;<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">long</span>&nbsp;state;<br />&nbsp;&nbsp;&nbsp;&nbsp;atomic_t&nbsp;count;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;(*func)(unsigned&nbsp;<span style="color: #0000FF; ">long</span>);<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">long</span>&nbsp;data;<br />};<br /><br /><span style="color: #0000FF; ">#define</span>&nbsp;DECLARE_TASKLET(name,&nbsp;func,&nbsp;data)&nbsp;\<br /><span style="color: #0000FF; ">struct</span>&nbsp;tasklet_struct&nbsp;name&nbsp;=&nbsp;{&nbsp;NULL,&nbsp;0,&nbsp;ATOMIC_INIT(0),&nbsp;func,&nbsp;data&nbsp;}<br /><br /><br />使用示例:<br /><span style="color: #0000FF; ">static</span>&nbsp;atomic_t&nbsp;fpstatues;<br /><span style="color: #0000FF; ">static</span>&nbsp;atomic_t&nbsp;has_image&nbsp;=&nbsp;{0};<br /><br /><span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;gc0303_vsync_do_tasklet(<span style="color: #0000FF; ">ulong</span>&nbsp;data)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">ulong</span>&nbsp;curr&nbsp;=&nbsp;gettickcount();<br />&nbsp;&nbsp;&nbsp;&nbsp;debug("curr:%lu",curr);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(atomic_read(&amp;fpstatues)==0)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s3c2410_dma_ctrl(DMACH_XD0,&nbsp;S3C2410_DMAOP_FLUSH);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gc0303_dma_buf.dma_addr&nbsp;=&nbsp;img_phys;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gc0303_dma_buf.size&nbsp;=&nbsp;bmp_w*bmp_h;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s3c2410_dma_enqueue(DMACH_XD0,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: #0000FF; ">void</span>&nbsp;*)&amp;gc0303_dma_buf,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gc0303_dma_buf.dma_addr,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gc0303_dma_buf.size);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;atomic_set(&amp;fpstatues,1);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br />DECLARE_TASKLET(gc0303_vsync_tasklet,gc0303_vsync_do_tasklet,0);<br /><br /><span style="color: #0000FF; ">static</span>&nbsp;irqreturn_t&nbsp;gc0303_vsync_handler(<span style="color: #0000FF; ">int</span>&nbsp;irq,<span style="color: #0000FF; ">void</span>*&nbsp;dev_id)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(atomic_read(&amp;fpstatues)==1)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s3c2410_dma_ctrl(DMACH_XD0,&nbsp;S3C2410_DMAOP_START);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">调度gc0303_vsync_tasklet</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;tasklet_schedule(&amp;gc0303_vsync_tasklet);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;IRQ_HANDLED;<br />}<br /><br /><br /><br /><br /><br /><br />tasklet是作为中断下半部的一个很好的选择，它在性能和易用性之间有着很好的平衡。较之于softirq，tasklet不需要考虑SMP下的并行问题，而又比workqueues有着更好的性能。<br />tasklet通常作为硬中断的下半部来使用，在硬中断中调用tasklet_schedule(t)。每次硬中断都会触发一次tasklet_schedule(t)，但是每次中断它只会向其中的一个CPU注册，而不是所有的CPU。完成注册后的tasklet由tasklet_action()来执行，在SMP环境下，它保证同一时刻，同一个tasklet只有一个副本在运行，这样就避免了使用softirq所要考虑的互斥的问题。再者，tasklet在执行tasklet-&gt;func()前，再一次允许tasklet可调度（注册），但是在该tasklet已有一个副本在其他CPU上运行的情况下，它只能退后执行。总之，同一个硬中断引起的一个tasklet_schedule()动作只会使一个tasklet被注册，而不同中断引起的tasklet则可能在不同的时刻被注册而多次被执行。<br /><br />tasklet的互斥。由于同一个tasklet不能有多个副本同时运行，所以不需要在多CPU之间互斥。在tasklet运行的过程中，它会被硬中断打断（这也是软中断的优点），所以如果tasklet和其他中断之间的互斥有可能存在。<br />中断服务程序一般都是在中断请求关闭的条件下执行的,以避免嵌套而使中断控制复杂化。但是，中断是一个随机事件，它随时会到来，如果关中断的时间太长，CPU就不能及时响应其他的中断请求，从而造成中断的丢失。因此，Linux内核的目标就是尽可能快的处理完中断请求，尽其所能把更多的处理向后推迟。例如，假设一个数据块已经达到了网线，当中断控制器接受到这个中断请求信号时，Linux内核只是简单地标志数据到来了，然后让处理器恢复到它以前运行的状态，其余的处理稍后再进行（如把数据移入一个缓冲区，接受数据的进程就可以在缓冲区找到数据）。因此，内核把中断处理分为两部分：上半部（tophalf）和下半部（bottomhalf），上半部（就是中断服务程序）内核立即执行，而下半部（就是一些内核函数）留着稍后处理，<br /><br />首先，一个快速的&#8220;上半部&#8221;来处理硬件发出的请求，它必须在一个新的中断产生之前终止。通常，除了在设备和一些内存缓冲区（如果你的设备用到了DMA，就不止这些）之间移动或传送数据，确定硬件是否处于健全的状态之外，这一部分做的工作很少。<br /><br />下半部运行时是允许中断请求的，而上半部运行时是关中断的，这是二者之间的主要区别。<br /><br />但是，内核到底什时候执行下半部，以何种方式组织下半部？这就是我们要讨论的下半部实现机制，这种机制在内核的演变过程中不断得到改进，在以前的内核中，这个机制叫做bottomhalf(简称bh)，在2.4以后的版本中有了新的发展和改进，改进的目标使下半部可以在多处理机上并行执行，并有助于驱动程序的开发者进行驱动程序的开发。下面主要介绍常用的小任务(Tasklet)机制及2.6内核中的工作队列机制。<br /><br />这里的小任务是指对要推迟执行的函数进行组织的一种机制。其数据结构为tasklet_struct，每个结构代表一个独立的小任务，其定义如下：<br />structtasklet_struct&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;structtasklet_struct&nbsp;*next;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/*</span><span style="color: #008000; ">指向链表中的下一个结构</span><span style="color: #008000; ">*/</span><br />&nbsp;&nbsp;&nbsp;&nbsp;unsignedlong&nbsp;state;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;小任务的状态</span><span style="color: #008000; ">*/</span><br />&nbsp;&nbsp;&nbsp;&nbsp;atomic_t&nbsp;count;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;引用计数器</span><span style="color: #008000; ">*/</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>(*func)&nbsp;(unsigned&nbsp;<span style="color: #0000FF; ">long</span>);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;要调用的函数</span><span style="color: #008000; ">*/</span><br />&nbsp;&nbsp;&nbsp;&nbsp;unsignedlong&nbsp;data;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;传递给函数的参数</span><span style="color: #008000; ">*/</span><br />}；<br />结构中的func域就是下半部中要推迟执行的函数，data是它唯一的参数。<br />state域的取值为TASKLET_STATE_SCHED或TASKLET_STATE_RUN。TASKLET_STATE_SCHED表示小任务已被调度，正准备投入运行，TASKLET_STATE_RUN表示小任务正在运行。TASKLET_STATE_RUN只有在多处理器系统上才使用，单处理器系统什么时候都清楚一个小任务是不是正在运行（它要么就是当前正在执行的代码，要么不是）。<br />count&nbsp;域是小任务的引用计数器。如果它不为0，则小任务被禁止，不允许执行；只有当它为零，小任务才被激活，并且在被设置为挂起时，小任务才能够执行。<br />1.&nbsp;声明和使用小任务大多数情况下，为了控制一个寻常的硬件设备，小任务机制是实现下半部的最佳选择。小任务可以动态创建，使用方便，执行起来也比较快。<br />我们既可以静态地创建小任务，也可以动态地创建它。选择那种方式取决于到底是想要对小任务进行直接引用还是一个间接引用。如果准备静态地创建一个小任务（也就是对它直接引用），使用下面两个宏中的一个：<br />DECLARE_TASKLET(name,func,&nbsp;data)<br />DECLARE_TASKLET_DISABLED(name,func,&nbsp;data)<br />这两个宏都能根据给定的名字静态地创建一个tasklet_struct结构。当该小任务被调度以后，给定的函数func会被执行，它的参数由data给出。这两个宏之间的区别在于引用计数器的初始值设置不同。第一个宏把创建的小任务的引用计数器设置为0，因此，该小任务处于激活状态。另一个把引用计数器设置为1，所以该小任务处于禁止状态。例如：<br />DECLARE_TASKLET(my_tasklet,my_tasklet_handler,&nbsp;dev);<br />这行代码其实等价于<br /><span style="color: #0000FF; ">struct</span>&nbsp;tasklet_struct&nbsp;my_tasklet&nbsp;=&nbsp;{&nbsp;NULL,&nbsp;0,&nbsp;ATOMIC_INIT(0),tasklet_handler,dev};<br />这样就创建了一个名为my_tasklet的小任务，其处理程序为tasklet_handler，并且已被激活。当处理程序被调用的时候，dev就会被传递给它。<br />2.&nbsp;&nbsp;编写自己的小任务处理程序小任务处理程序必须符合如下的函数类型：<br /><span style="color: #0000FF; ">void</span>&nbsp;tasklet_handler(unsigned&nbsp;<span style="color: #0000FF; ">long</span>&nbsp;data)<br />由于小任务不能睡眠，因此不能在小任务中使用信号量或者其它产生阻塞的函数。但是小任务运行时可以响应中断。<br />3.&nbsp;调度自己的小任务通过调用tasklet_schedule()函数并传递给它相应的tasklt_struct指针，该小任务就会被调度以便适当的时候执行：<br />tasklet_schedule(&amp;my_tasklet);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/*</span><span style="color: #008000; ">把my_tasklet标记为挂起&nbsp;</span><span style="color: #008000; ">*/</span><br />在小任务被调度以后，只要有机会它就会尽可能早的运行。在它还没有得到运行机会之前，如果一个相同的小任务又被调度了，那么它仍然只会运行一次。<br />可以调用tasklet_disable()函数来禁止某个指定的小任务。如果该小任务当前正在执行，这个函数会等到它执行完毕再返回。调用tasklet_enable()函数可以激活一个小任务，如果希望把以DECLARE_TASKLET_DISABLED（）创建的小任务激活，也得调用这个函数，如：<br />tasklet_disable(&amp;my_tasklet);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/*</span><span style="color: #008000; ">小任务现在被禁止,这个小任务不能运行</span><span style="color: #008000; ">*/</span><br />tasklet_enable(&amp;my_tasklet);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;&nbsp;小任务现在被激活</span><span style="color: #008000; ">*/</span><br />也可以调用tasklet_kill()函数从挂起的队列中去掉一个小任务。该函数的参数是一个指向某个小任务的tasklet_struct的长指针。在小任务重新调度它自身的时候，从挂起的队列中移去已调度的小任务会很有用。这个函数首先等待该小任务执行完毕，然后再将它移去。<br />4.tasklet的简单用法<br />下面是tasklet的一个简单应用,以模块的形成加载。<br /><br />#include&nbsp;&lt;linux/module.h&gt;<br />#include&nbsp;&lt;linux/init.h&gt;<br />#include&nbsp;&lt;linux/fs.h&gt;<br />#include&nbsp;&lt;linux/kdev_t.h&gt;<br />#include&nbsp;&lt;linux/cdev.h&gt;<br />#include&nbsp;&lt;linux/kernel.h&gt;<br />#include&nbsp;&lt;linux/interrupt.h&gt;<br /><br /><span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">struct</span>&nbsp;tasklet_struct&nbsp;my_tasklet;<br /><br /><span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;tasklet_handler&nbsp;(unsigned&nbsp;<span style="color: #0000FF; ">long</span>&nbsp;d&nbsp;ata)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;printk("tasklet_handler&nbsp;is&nbsp;running.\n");<br />}<br /><br /><span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;__init&nbsp;test_init(<span style="color: #0000FF; ">void</span>)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;tasklet_init(&amp;my_tasklet,tasklet_handler,0);<br />&nbsp;&nbsp;&nbsp;&nbsp;tasklet_schedule(&amp;my_tasklet);<br />&nbsp;&nbsp;&nbsp;&nbsp;return0;<br />}<br /><br /><span style="color: #0000FF; ">static</span>&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;__exit&nbsp;test_exit(<span style="color: #0000FF; ">void</span>)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;tasklet_kill(&amp;tasklet);<br />&nbsp;&nbsp;&nbsp;&nbsp;printk("test_exit&nbsp;is&nbsp;running.\n");<br />}<br />MODULE_LICENSE("GPL");<br />module_init(test_init);<br />module_exit(test_exit);<br /><br />从这个例子可以看出，所谓的小任务机制是为下半部函数的执行提供了一种执行机制，也就是说，推迟处理的事情是由tasklet_handler实现，何时执行，经由小任务机制封装后交给内核去处理。</div><img src ="http://www.cppblog.com/aaxron/aggbug/199306.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/aaxron/" target="_blank">天下</a> 2013-04-10 15:29 <a href="http://www.cppblog.com/aaxron/archive/2013/04/10/199306.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[原]linux中断处理(1)上半部机制</title><link>http://www.cppblog.com/aaxron/archive/2013/04/03/199066.html</link><dc:creator>天下</dc:creator><author>天下</author><pubDate>Wed, 03 Apr 2013 03:54:00 GMT</pubDate><guid>http://www.cppblog.com/aaxron/archive/2013/04/03/199066.html</guid><wfw:comment>http://www.cppblog.com/aaxron/comments/199066.html</wfw:comment><comments>http://www.cppblog.com/aaxron/archive/2013/04/03/199066.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/aaxron/comments/commentRss/199066.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/aaxron/services/trackbacks/199066.html</trackback:ping><description><![CDATA[<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->linux中断处理(1)上半部机制<br />应用程序通过/dev/目录中的设备结点操作设备,通过/sys目录中的收集设备信息.<br />查看中断:<br />cat&nbsp;/proc/interrupts<br /><br />查看中断统计:<br />cat&nbsp;/proc/stat<br /><br />1、头文件&nbsp;<br />#include&nbsp;&lt;linux/interrupt.h&gt;<br />#include&nbsp;&lt;asm/arch/irqs.h&gt;<br />2、申明中断处理程序&nbsp;<br /><span style="color: #0000FF; ">static</span>&nbsp;spinlock_t&nbsp;&nbsp;&nbsp;&nbsp;wiegand_lock;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;使用之前必须初始化,spin_lock_init(&amp;wiegand_lock);</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">static</span>&nbsp;irqreturn_t&nbsp;wiegand_minus1_interrupt(<span style="color: #0000FF; ">int</span>&nbsp;irq,&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;*dev_id)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;spin_lock(&amp;wiegand_lock);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">do&nbsp;something&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">wiegand_minus_interrupt();</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;spin_unlock(&amp;wiegand_lock);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;IRQ_HANDLED;<br />}<br /><br />3.注册中断&nbsp;request_irq()<br />2.6&nbsp;内核&nbsp;函数原型如下：<br /><span style="color: #0000FF; ">extern</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;__must_check&nbsp;request_irq(unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;irq,&nbsp;irq_handler_t&nbsp;handler,&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">long</span>&nbsp;flags,&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;*name,&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;*dev_id);&nbsp;<br />第1个参数:中断号,是要申请的中断号<br />第2个参数:中断处理函数&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><br />第3个参数:中断触发标志<br />&nbsp;&nbsp;&nbsp;&nbsp;IRQF_DISABLED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;快中断(禁止其他中断)<br />&nbsp;&nbsp;&nbsp;&nbsp;IRQF_TRIGGER_RISING&nbsp;&nbsp;&nbsp;&nbsp;设备在中断线上产生一个上升沿时,发出中断.(说明在中断之前,设备一直将中断线保持在一个电平上)<br />&nbsp;&nbsp;&nbsp;&nbsp;IRQF_TRIGGER_FALLING&nbsp;&nbsp;&nbsp;&nbsp;下降沿触发<br />&nbsp;&nbsp;&nbsp;&nbsp;IRQF_TRIGGER_HIGH&nbsp;&nbsp;&nbsp;&nbsp;高电平触发中断<br />&nbsp;&nbsp;&nbsp;&nbsp;IRQF_TRIGGER_LOW&nbsp;&nbsp;&nbsp;&nbsp;低电平触发中断<br />&nbsp;&nbsp;&nbsp;&nbsp;IRQF_TRIGGER_RANDOM&nbsp;&nbsp;&nbsp;&nbsp;为系统随机发生器提供支持<br />&nbsp;&nbsp;&nbsp;&nbsp;IRQF_TRIGGER_SHARED&nbsp;&nbsp;&nbsp;&nbsp;(表示共享相同的中断号,多个设备共享)<br /><span style="color: #008000; ">/*</span><span style="color: #008000; "><br />&nbsp;*&nbsp;linux/interrupt.h<br />&nbsp;*&nbsp;These&nbsp;correspond&nbsp;to&nbsp;the&nbsp;IORESOURCE_IRQ_*&nbsp;defines&nbsp;in<br />&nbsp;*&nbsp;linux/ioport.h&nbsp;to&nbsp;select&nbsp;the&nbsp;interrupt&nbsp;line&nbsp;behaviour.&nbsp;&nbsp;When<br />&nbsp;*&nbsp;requesting&nbsp;an&nbsp;interrupt&nbsp;without&nbsp;specifying&nbsp;a&nbsp;IRQF_TRIGGER,&nbsp;the<br />&nbsp;*&nbsp;setting&nbsp;should&nbsp;be&nbsp;assumed&nbsp;to&nbsp;be&nbsp;"as&nbsp;already&nbsp;configured",&nbsp;which<br />&nbsp;*&nbsp;may&nbsp;be&nbsp;as&nbsp;per&nbsp;machine&nbsp;or&nbsp;firmware&nbsp;initialisation.<br />&nbsp;</span><span style="color: #008000; ">*/</span><br /><span style="color: #0000FF; ">#define</span>&nbsp;IRQF_TRIGGER_NONE&nbsp;&nbsp;&nbsp;&nbsp;0x00000000<br /><span style="color: #0000FF; ">#define</span>&nbsp;IRQF_TRIGGER_RISING&nbsp;&nbsp;&nbsp;&nbsp;0x00000001<br /><span style="color: #0000FF; ">#define</span>&nbsp;IRQF_TRIGGER_FALLING&nbsp;&nbsp;&nbsp;&nbsp;0x00000002<br /><span style="color: #0000FF; ">#define</span>&nbsp;IRQF_TRIGGER_HIGH&nbsp;&nbsp;&nbsp;&nbsp;0x00000004<br /><span style="color: #0000FF; ">#define</span>&nbsp;IRQF_TRIGGER_LOW&nbsp;&nbsp;&nbsp;&nbsp;0x00000008<br /><span style="color: #0000FF; ">#define</span>&nbsp;IRQF_TRIGGER_MASK&nbsp;&nbsp;&nbsp;&nbsp;(IRQF_TRIGGER_HIGH&nbsp;|&nbsp;IRQF_TRIGGER_LOW&nbsp;|&nbsp;\<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IRQF_TRIGGER_RISING&nbsp;|&nbsp;IRQF_TRIGGER_FALLING)<br /><span style="color: #0000FF; ">#define</span>&nbsp;IRQF_TRIGGER_PROBE&nbsp;&nbsp;&nbsp;&nbsp;0x00000010<br /><br />typedef&nbsp;irqreturn_t&nbsp;(*irq_handler_t)(<span style="color: #0000FF; ">int</span>,&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;*);<br /><br />第4个参数:中断的标识,中断的标识与/proc/interrupts对应<br />第5个参数:传入中断处理程序的参数，可以为NULL，在注册共享中断时，此参数不能为NULL，作为共享中断时的中断区别参数。<br /><br />返回值:如果中断处理成功,返回IREQ_HANDLED,否则,返回IRQ_NONE<br /><span style="color: #008000; ">/*</span><span style="color: #008000; ">&nbsp;irqreturn.h&nbsp;</span><span style="color: #008000; ">*/</span><br />typedef&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;irqreturn_t;<br /><span style="color: #0000FF; ">#define</span>&nbsp;IRQ_NONE&nbsp;&nbsp;&nbsp;&nbsp;(0)<br /><span style="color: #0000FF; ">#define</span>&nbsp;IRQ_HANDLED&nbsp;&nbsp;&nbsp;&nbsp;(1)<br /><span style="color: #0000FF; ">#define</span>&nbsp;IRQ_RETVAL(x)&nbsp;&nbsp;&nbsp;&nbsp;((x)&nbsp;!=&nbsp;0)<br /><br />中断上下文<br /><br />中断上下文注意事项:<br />1)中断上下文代码绝不可以停止运行。不能做任何可能发生休眠的操作,在从中断处理函数中调用一个内核API之前,应该仔细分手它,以确保其内部不会触发阻塞等待!<br /><br />2)为了在中断处理函数中保护临界区,不能使用互斥体,因为它们也许导致睡眠,应该使用自旋锁代替互斥体.<br /><br />3)中断处理函数不能与用户空间直接交互数据.<br />调度器工作于进程之间,如果中断处理函数睡眠并被调度出去.无法调度回来!<br /><br />4)中断处理函数一方面需要快速地为其他进程让出处理器,另一方面又需要完成它的工作,为了规避这种冲突,中断处理函数通常将工作分成两个部分.顶半部设一个标志以宣称它已经服务了该中断,而重大的工作负载都被丢给了底半部,底半部的执行被延后.在其执行环境中,所有的中断都是使能的.<br /><br />4.释放中断<br /><span style="color: #0000FF; ">extern</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;free_irq(<span style="color: #0000FF; ">int</span>&nbsp;irq,<span style="color: #0000FF; ">void</span>&nbsp;*dev_id)<br /><br />5、启动用禁用中断<br /><span style="color: #0000FF; ">extern</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;disable_irq_nosync(unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;irq);<br /><span style="color: #0000FF; ">extern</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;disable_irq(unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;irq);<br /><span style="color: #0000FF; ">extern</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;enable_irq(unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;irq);</div><img src ="http://www.cppblog.com/aaxron/aggbug/199066.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/aaxron/" target="_blank">天下</a> 2013-04-03 11:54 <a href="http://www.cppblog.com/aaxron/archive/2013/04/03/199066.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>驱动学习笔记(1)</title><link>http://www.cppblog.com/aaxron/archive/2012/12/04/195955.html</link><dc:creator>天下</dc:creator><author>天下</author><pubDate>Tue, 04 Dec 2012 00:59:00 GMT</pubDate><guid>http://www.cppblog.com/aaxron/archive/2012/12/04/195955.html</guid><wfw:comment>http://www.cppblog.com/aaxron/comments/195955.html</wfw:comment><comments>http://www.cppblog.com/aaxron/archive/2012/12/04/195955.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/aaxron/comments/commentRss/195955.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/aaxron/services/trackbacks/195955.html</trackback:ping><description><![CDATA[<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000"><br />内核符号列表:<br /><br />cat&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">proc</span><span style="color: #000000">/</span><span style="color: #000000">kallsyms<br />cat&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">proc</span><span style="color: #000000">/</span><span style="color: #000000">iomem<br /><br />导出内核符号:<br />EXPORT_SYMBOL(sym)<br /></span><span style="color: #000000">1</span><span style="color: #000000">、缺省情况下，Linux2.6内核中默认不导出所有的符号,即在2.6的内核中没有这个宏EXPORT_NO_SYMBOLS<br /></span><span style="color: #000000">2</span><span style="color: #000000">、如果想要自己指定导出哪些变量或函数，先在Makefile中使用</span><span style="color: #000000">-</span><span style="color: #000000">DEXPORT_SYMTAB，然后在源文件中使用EXPORT_SYMBOL(xxx);导出之<br /><br />echo&nbsp;</span><span style="color: #000000">8</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">proc</span><span style="color: #000000">/</span><span style="color: #000000">sys</span><span style="color: #000000">/</span><span style="color: #000000">kernel</span><span style="color: #000000">/</span><span style="color: #000000">printk<br /><br />查看中断:<br />cat&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">proc</span><span style="color: #000000">/</span><span style="color: #000000">interrupts<br /><br />下半部机制<br /></span><span style="color: #000000">1</span><span style="color: #000000">.tasklet<br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;DECLARE_TASKLET(name,&nbsp;func,&nbsp;data)&nbsp;\</span><span style="color: #000000"><br /></span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;tasklet_struct&nbsp;name&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;{&nbsp;NULL,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;ATOMIC_INIT(</span><span style="color: #000000">0</span><span style="color: #000000">),&nbsp;func,&nbsp;data&nbsp;}<br /><br /></span><span style="color: #000000">2</span><span style="color: #000000">.&nbsp;工作队列<br /></span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;work_struct&nbsp;my_work;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">定义一个工作队列</span><span style="color: #008000"><br /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;my_work_func(unsigned&nbsp;</span><span style="color: #0000ff">long</span><span style="color: #000000">);&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">定义一个处理函数</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />在中断处理函数,tasklet和内核定时器等非进程上下文不能阻塞.<br /></span></div><img src ="http://www.cppblog.com/aaxron/aggbug/195955.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/aaxron/" target="_blank">天下</a> 2012-12-04 08:59 <a href="http://www.cppblog.com/aaxron/archive/2012/12/04/195955.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>s3c2410的dma操作的一般步骤</title><link>http://www.cppblog.com/aaxron/archive/2012/12/04/195954.html</link><dc:creator>天下</dc:creator><author>天下</author><pubDate>Tue, 04 Dec 2012 00:58:00 GMT</pubDate><guid>http://www.cppblog.com/aaxron/archive/2012/12/04/195954.html</guid><wfw:comment>http://www.cppblog.com/aaxron/comments/195954.html</wfw:comment><comments>http://www.cppblog.com/aaxron/archive/2012/12/04/195954.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/aaxron/comments/commentRss/195954.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/aaxron/services/trackbacks/195954.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->s3c2410的dma操作的一般步骤一般的，在s3c2440中，要想进行dma传输，需要一下七个步骤：一：/*&nbsp;s3c2410_request_dma&nbsp;*&nbsp;*&nbsp;ge...&nbsp;&nbsp;<a href='http://www.cppblog.com/aaxron/archive/2012/12/04/195954.html'>阅读全文</a><img src ="http://www.cppblog.com/aaxron/aggbug/195954.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/aaxron/" target="_blank">天下</a> 2012-12-04 08:58 <a href="http://www.cppblog.com/aaxron/archive/2012/12/04/195954.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux设备驱动程序学习笔记:(1) 字符设备驱动入门1</title><link>http://www.cppblog.com/aaxron/archive/2012/11/08/194881.html</link><dc:creator>天下</dc:creator><author>天下</author><pubDate>Thu, 08 Nov 2012 08:04:00 GMT</pubDate><guid>http://www.cppblog.com/aaxron/archive/2012/11/08/194881.html</guid><wfw:comment>http://www.cppblog.com/aaxron/comments/194881.html</wfw:comment><comments>http://www.cppblog.com/aaxron/archive/2012/11/08/194881.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/aaxron/comments/commentRss/194881.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/aaxron/services/trackbacks/194881.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<p>&nbsp;</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000">//</span><span style="color: #008000">这是一个最简单的字符设备驱动,入门专用.<br /></span><span style="color: #008000">//</span><span style="color: #008000">scull1.h</span><span style="color: #008000"><br /></span><span style="color: #000000">#ifndef&nbsp;_SCULL1_H<br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;_SCULL1_H</span><span style="color: #000000"><br /><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">init.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">module.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">kernel.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">types.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">fs.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">version.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">asm</span><span style="color: #000000">/</span><span style="color: #000000">uaccess.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">cdev.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">mm.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">errno.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /><br /><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;SCULL_MAJOR&nbsp;0</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;SCULL_SIZE&nbsp;&nbsp;&nbsp;&nbsp;0x1000</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;SCULL_CMD_CLEAR&nbsp;&nbsp;&nbsp;&nbsp;0x01</span><span style="color: #000000"><br /><br /><br /></span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;scull_dev{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;cdev&nbsp;cDev;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;mem[SCULL_SIZE];<br />};<br /><br /><br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;scull_open(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;inode</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;inode,</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;filp);<br /><br />ssize_t&nbsp;scull_read(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">filp,&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;__user&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">buf,&nbsp;size_t&nbsp;count,loff_t&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">f_pos);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><br />ssize_t&nbsp;scull_write(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">filp,&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;__user&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">buf,&nbsp;size_t&nbsp;count,loff_t&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">f_pos);<br /><br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;scull_release(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;inode</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;inode,</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;filp);<br /><br /></span><span style="color: #0000ff">#endif</span><span style="color: #000000"><br /><br /><br /><br /><br /><br /><br /></span><span style="color: #008000">//</span><span style="color: #008000">scull1.c</span><span style="color: #008000"><br /></span><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">scull1.h</span><span style="color: #000000">"</span><span style="color: #000000"><br /><br />MODULE_LICENSE(</span><span style="color: #000000">"</span><span style="color: #000000">Dual&nbsp;BSD/GPL</span><span style="color: #000000">"</span><span style="color: #000000">);<br />MODULE_AUTHOR(</span><span style="color: #000000">"</span><span style="color: #000000">Aaron.xu</span><span style="color: #000000">"</span><span style="color: #000000">);<br />MODULE_DESCRIPTION(</span><span style="color: #000000">"</span><span style="color: #000000">hello&nbsp;driver&nbsp;test</span><span style="color: #000000">"</span><span style="color: #000000">);<br />MODULE_VERSION(</span><span style="color: #000000">"</span><span style="color: #000000">0.1</span><span style="color: #000000">"</span><span style="color: #000000">);<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;scull_major&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;SCULL_MAJOR;<br /></span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;scull_dev&nbsp;mydev;<br /><br /></span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file_operations&nbsp;scull_fops&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;.owner&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;THIS_MODULE,<br />&nbsp;&nbsp;&nbsp;&nbsp;.open&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;scull_open,<br />&nbsp;&nbsp;&nbsp;&nbsp;.release&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;scull_release,<br />&nbsp;&nbsp;&nbsp;&nbsp;.read&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;scull_read,<br />&nbsp;&nbsp;&nbsp;&nbsp;.write&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;scull_write,<br />};<br /><br /><br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;scull_setup_cdev(</span><span style="color: #0000ff">void</span><span style="color: #000000">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;err;<br />&nbsp;&nbsp;&nbsp;&nbsp;dev_t&nbsp;devid&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;MKDEV(scull_major,</span><span style="color: #000000">0</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;cdev_init(</span><span style="color: #000000">&amp;</span><span style="color: #000000">mydev.cDev,</span><span style="color: #000000">&amp;</span><span style="color: #000000">scull_fops);<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;printk(KERN_INFO&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">&amp;mydev.cDev.ops:%p&nbsp;\n</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">&amp;</span><span style="color: #000000">mydev.cDev.ops);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;mydev.cDev.owner&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;THIS_MODULE;<br />&nbsp;&nbsp;&nbsp;&nbsp;mydev.cDev.ops&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">scull_fops;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;printk(KERN_INFO&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">&amp;mydev.cDev.ops:%p&nbsp;\n</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">&amp;</span><span style="color: #000000">mydev.cDev.ops);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;err&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;cdev_add(</span><span style="color: #000000">&amp;</span><span style="color: #000000">mydev.cDev,devid,</span><span style="color: #000000">1</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(err</span><span style="color: #000000">!=</span><span style="color: #000000">0</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk(KERN_ERR&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">cdev_add&nbsp;Error,err:%d&nbsp;\n</span><span style="color: #000000">"</span><span style="color: #000000">,err);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;scull_init(</span><span style="color: #0000ff">void</span><span style="color: #000000">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;err;<br />&nbsp;&nbsp;&nbsp;&nbsp;dev_t&nbsp;devid&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;MKDEV(scull_major,</span><span style="color: #000000">0</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(scull_major)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;register_chrdev_region(devid,</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">scull1</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;alloc_chrdev_region(</span><span style="color: #000000">&amp;</span><span style="color: #000000">devid,</span><span style="color: #000000">0</span><span style="color: #000000">,</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">scull1</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scull_major&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;MAJOR(devid);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(err&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">0</span><span style="color: #000000">&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk(KERN_ERR&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">register&nbsp;chrdev&nbsp;region&nbsp;error,err:%d&nbsp;\n</span><span style="color: #000000">"</span><span style="color: #000000">,err);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;err;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;scull_setup_cdev();<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />}<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;scull_exit(</span><span style="color: #0000ff">void</span><span style="color: #000000">)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;cdev_del(</span><span style="color: #000000">&amp;</span><span style="color: #000000">mydev.cDev);<br />&nbsp;&nbsp;&nbsp;&nbsp;unregister_chrdev_region(MKDEV(scull_major,</span><span style="color: #000000">0</span><span style="color: #000000">),</span><span style="color: #000000">1</span><span style="color: #000000">);<br />}<br /><br /><br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;scull_open(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;inode</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;inode,</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;filp)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;filp</span><span style="color: #000000">-&gt;</span><span style="color: #000000">private_data&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">mydev;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />}<br /><br />ssize_t&nbsp;scull_read(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">filp,&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;__user&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">buf,&nbsp;size_t&nbsp;count,loff_t&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">f_pos)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;</span><span style="color: #0000ff">long</span><span style="color: #000000">&nbsp;pos&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">f_pos;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;err&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;ret&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;scull_dev</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;p_mydev&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;filp</span><span style="color: #000000">-&gt;</span><span style="color: #000000">private_data;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(pos&nbsp;</span><span style="color: #000000">&gt;=</span><span style="color: #000000">&nbsp;SCULL_SIZE)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(count&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;(SCULL_SIZE&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;pos)&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;SCULL_SIZE&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;pos;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;err&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;copy_to_user(buf,p_mydev</span><span style="color: #000000">-&gt;</span><span style="color: #000000">mem</span><span style="color: #000000">+</span><span style="color: #000000">pos,count);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(err&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">0</span><span style="color: #000000">&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">EFAULT;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">f_pos&nbsp;</span><span style="color: #000000">+=</span><span style="color: #000000">&nbsp;count;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;count;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk(KERN_INFO&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">read&nbsp;%d&nbsp;byte(s)&nbsp;from&nbsp;%lu&nbsp;\n</span><span style="color: #000000">"</span><span style="color: #000000">,ret,pos);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;ret;<br />}<br /><br />ssize_t&nbsp;scull_write(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">filp,&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;__user&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">buf,&nbsp;size_t&nbsp;count,loff_t&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">f_pos)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;</span><span style="color: #0000ff">long</span><span style="color: #000000">&nbsp;pos&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">f_pos;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;err&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;ret&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;scull_dev</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;p_mydev&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;filp</span><span style="color: #000000">-&gt;</span><span style="color: #000000">private_data;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(pos&nbsp;</span><span style="color: #000000">&gt;=</span><span style="color: #000000">&nbsp;SCULL_SIZE)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(count&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;(SCULL_SIZE&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;pos)&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;SCULL_SIZE&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;pos;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;err&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;copy_from_user(p_mydev</span><span style="color: #000000">-&gt;</span><span style="color: #000000">mem</span><span style="color: #000000">+</span><span style="color: #000000">pos,buf,count);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(err&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">0</span><span style="color: #000000">&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">EFAULT;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">f_pos&nbsp;</span><span style="color: #000000">+=</span><span style="color: #000000">&nbsp;count;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;count;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk(KERN_INFO&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">write&nbsp;%d&nbsp;byte(s)&nbsp;from&nbsp;%lu&nbsp;\n</span><span style="color: #000000">"</span><span style="color: #000000">,ret,pos);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;ret;<br />}<br /><br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;scull_release(</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;inode</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;inode,</span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;file</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;filp)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />}<br /><br /><br />module_init(scull_init);<br />module_exit(scull_exit);<br /><br /><br /><br /></span><span style="color: #008000">//</span><span style="color: #008000">Makefile</span><span style="color: #008000"><br /></span><span style="color: #000000">obj</span><span style="color: #000000">-</span><span style="color: #000000">m&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">+=</span><span style="color: #000000">scull1.o<br />KERNELDIR&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">usr</span><span style="color: #000000">/</span><span style="color: #000000">src</span><span style="color: #000000">/</span><span style="color: #000000">linux</span><span style="color: #000000">-</span><span style="color: #000000">headers</span><span style="color: #000000">-</span><span style="color: #000000">2.6</span><span style="color: #000000">.</span><span style="color: #000000">32</span><span style="color: #000000">-</span><span style="color: #000000">5</span><span style="color: #000000">-</span><span style="color: #000000">686</span><span style="color: #000000"><br />PWD&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #000000">=</span><span style="color: #000000">$(shell&nbsp;pwd)<br />.PHONY:&nbsp;test&nbsp;clean&nbsp;all<br />all:<br />&nbsp;&nbsp;&nbsp;&nbsp;$(MAKE)&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">C&nbsp;$(KERNELDIR)&nbsp;M</span><span style="color: #000000">=</span><span style="color: #000000">$(PWD)&nbsp;modules<br />clean:<br />&nbsp;&nbsp;&nbsp;&nbsp;rm&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">rf&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">.o&nbsp;</span><span style="color: #000000">*~</span><span style="color: #000000">&nbsp;core&nbsp;.depend&nbsp;.</span><span style="color: #000000">*</span><span style="color: #000000">.cmd&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">.ko&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">.mod.c&nbsp;.tmp_versionsm&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">.order&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">.symvers&nbsp;.tmp_versions<br /><br />test:<br />&nbsp;&nbsp;&nbsp;&nbsp;insmod&nbsp;.</span><span style="color: #000000">/</span><span style="color: #000000">scull1.ko<br />&nbsp;&nbsp;&nbsp;&nbsp;rmmod&nbsp;scull1<br />&nbsp;&nbsp;&nbsp;&nbsp;dmesg&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">c<br /><br /><br /><br /></span><span style="color: #008000">//</span><span style="color: #008000">创建设备节点</span><span style="color: #008000"><br /></span><span style="color: #000000">make_dev_node<br />#</span><span style="color: #000000">!/</span><span style="color: #000000">bin</span><span style="color: #000000">/</span><span style="color: #000000">bash<br />DEVICE</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">scull1</span><span style="color: #000000">"</span><span style="color: #000000"><br />MAJOR</span><span style="color: #000000">=</span><span style="color: #000000">`awk&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">\\$2==\</span><span style="color: #000000">"</span><span style="color: #000000">$DEVICE\</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;{print&nbsp;\\$1}</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">proc</span><span style="color: #000000">/</span><span style="color: #000000">devices`<br />cmd</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">mknod&nbsp;/dev/$DEVICE&nbsp;c&nbsp;$MAJOR&nbsp;0</span><span style="color: #000000">"</span><span style="color: #000000"><br />echo&nbsp;$cmd<br />`$cmd`<br /></span></div>
<p>&nbsp;</p><img src ="http://www.cppblog.com/aaxron/aggbug/194881.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/aaxron/" target="_blank">天下</a> 2012-11-08 16:04 <a href="http://www.cppblog.com/aaxron/archive/2012/11/08/194881.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>module_param()说明</title><link>http://www.cppblog.com/aaxron/archive/2012/11/06/194716.html</link><dc:creator>天下</dc:creator><author>天下</author><pubDate>Tue, 06 Nov 2012 07:54:00 GMT</pubDate><guid>http://www.cppblog.com/aaxron/archive/2012/11/06/194716.html</guid><wfw:comment>http://www.cppblog.com/aaxron/comments/194716.html</wfw:comment><comments>http://www.cppblog.com/aaxron/archive/2012/11/06/194716.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/aaxron/comments/commentRss/194716.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/aaxron/services/trackbacks/194716.html</trackback:ping><description><![CDATA[<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">module_param()说明<br />在用户态下编程可以通过main()的来传递命令行参数，而编写一个内核模块则通过module_param()&nbsp;<br />module_param宏是Linux&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">.6内核中新增的，该宏被定义在include</span><span style="color: #000000">/</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">moduleparam.h文件中，具体定义如下：<br /><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;module_param(name,&nbsp;type,&nbsp;perm)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;module_param_named(name,&nbsp;name,&nbsp;type,&nbsp;perm)<br /><br />其中使用了&nbsp;</span><span style="color: #000000">3</span><span style="color: #000000">&nbsp;个参数:要传递的参数变量名,&nbsp;变量的数据类型,&nbsp;以及访问参数的权限。<br /><br />perm参数的作用是什么？<br /><br />最后的&nbsp;module_param&nbsp;字段是一个权限值,表示此参数在sysfs文件系统中所对应的文件节点的属性。你应当使用&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">stat.h</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;中定义的值.&nbsp;这个值控制谁可以存取这些模块参数在&nbsp;sysfs&nbsp;中的表示.当perm为0时，表示此参数不存在&nbsp;sysfs文件系统下对应的文件节点。&nbsp;否则,&nbsp;模块被加载后，在</span><span style="color: #000000">/</span><span style="color: #000000">sys</span><span style="color: #000000">/</span><span style="color: #000000">module</span><span style="color: #000000">/</span><span style="color: #000000">&nbsp;目录下将出现以此模块名命名的目录,&nbsp;带有给定的权限.。<br />权限在include</span><span style="color: #000000">/</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">stat.h中有定义<br />比如：<br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;S_IRWXU&nbsp;00700</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;S_IRUSR&nbsp;00400</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;S_IWUSR&nbsp;00200</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;S_IXUSR&nbsp;00100</span><span style="color: #000000"><br /><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;S_IRWXG&nbsp;00070</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;S_IRGRP&nbsp;00040</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;S_IWGRP&nbsp;00020</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;S_IXGRP&nbsp;00010</span><span style="color: #000000"><br /><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;S_IRWXO&nbsp;00007</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;S_IROTH&nbsp;00004</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;S_IWOTH&nbsp;00002</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;S_IXOTH&nbsp;00001</span><span style="color: #000000"><br /><br />使用&nbsp;S_IRUGO&nbsp;作为参数可以被所有人读取,&nbsp;但是不能改变;&nbsp;S_IRUGO</span><span style="color: #000000">|</span><span style="color: #000000">S_IWUSR&nbsp;允许&nbsp;root&nbsp;来改变参数.&nbsp;注意,&nbsp;如果一个参数被&nbsp;sysfs&nbsp;修改,&nbsp;你的模块看到的参数值也改变了,&nbsp;但是你的模块没有任何其他的通知.&nbsp;你应当不要使模块参数可写,&nbsp;除非你准备好检测这个改变并且因而作出反应.<br /><br /></span><span style="color: #000000">&gt;&gt;&gt;</span><span style="color: #000000">&nbsp;<br /><br />这个宏定义应当放在任何函数之外,&nbsp;典型地是出现在源文件的前面.定义如：<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">whom&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">world</span><span style="color: #000000">"</span><span style="color: #000000">;<br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;howmany&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">;<br />module_param(howmany,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">,&nbsp;S_IRUGO);<br />module_param(whom,&nbsp;charp,&nbsp;S_IRUGO);<br /><br />模块参数支持许多类型:<br /></span><span style="color: #0000ff">bool</span><span style="color: #000000">&nbsp;<br /></span><span style="color: #0000ff">invbool&nbsp;</span><span style="color: #000000"><br />一个布尔型(&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">&nbsp;或者&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">)值(相关的变量应当是&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;类型).&nbsp;invbool&nbsp;类型颠倒了值,&nbsp;所以真值变成&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">,&nbsp;反之亦然.&nbsp;<br /><br /></span><span style="color: #0000ff">charp&nbsp;</span><span style="color: #000000">：一个字符指针值.&nbsp;内存为用户提供的字串分配,&nbsp;指针因此设置.&nbsp;<br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;<br /></span><span style="color: #0000ff">long</span><span style="color: #000000">&nbsp;<br /></span><span style="color: #0000ff">short</span><span style="color: #000000">&nbsp;<br /></span><span style="color: #0000ff">uint</span><span style="color: #000000">&nbsp;<br /></span><span style="color: #0000ff">ulong</span><span style="color: #000000">&nbsp;<br /></span><span style="color: #0000ff">ushort</span><span style="color: #000000">&nbsp;<br />基本的变长整型值.&nbsp;以&nbsp;u&nbsp;开头的是无符号值.&nbsp;<br /><br />数组参数,&nbsp;用逗号间隔的列表提供的值,&nbsp;模块加载者也支持.&nbsp;声明一个数组参数,&nbsp;使用:&nbsp;<br />module_param_array(name,type,num,perm);&nbsp;<br /><br />这里&nbsp;name&nbsp;是你的数组的名子(也是参数名),&nbsp;<br />type&nbsp;是数组元素的类型,&nbsp;<br />num&nbsp;是一个整型变量,&nbsp;<br />perm&nbsp;是通常的权限值.&nbsp;<br /><br />如果数组参数在加载时设置,&nbsp;num&nbsp;被设置成提供的数的个数.&nbsp;模块加载者拒绝比数组能放下的多的值.&nbsp;<br /><br />测试模块，源程序hello.c内容如下：&nbsp;<br /><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">init.h</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;<br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">module.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">linux</span><span style="color: #000000">/</span><span style="color: #000000">moduleparam.h</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><br />MODULE_LICENSE(</span><span style="color: #000000">"</span><span style="color: #000000">Dual&nbsp;BSD/GPL</span><span style="color: #000000">"</span><span style="color: #000000">);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">who</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">world</span><span style="color: #000000">"</span><span style="color: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;times&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />module_param(times,</span><span style="color: #0000ff">int</span><span style="color: #000000">,S_IRUSR);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />module_param(who,charp,S_IRUSR);&nbsp;&nbsp;&nbsp;<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;hello_init(</span><span style="color: #0000ff">void</span><span style="color: #000000">)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">(i</span><span style="color: #000000">=</span><span style="color: #000000">0</span><span style="color: #000000">;i</span><span style="color: #000000">&lt;</span><span style="color: #000000">times;i</span><span style="color: #000000">++</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk(KERN_ALERT&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">(%d)&nbsp;hello,&nbsp;%s!\n</span><span style="color: #000000">"</span><span style="color: #000000">,i,who);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />}<br /><br /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;hello_exit(</span><span style="color: #0000ff">void</span><span style="color: #000000">)&nbsp;<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;printk(KERN_ALERT</span><span style="color: #000000">"</span><span style="color: #000000">Goodbye,&nbsp;%s!\n</span><span style="color: #000000">"</span><span style="color: #000000">,who);<br />}<br /><br />module_init(hello_init);<br />module_exit(hello_exit);<br /><br />编译生成可执行文件hello<br /><br />插入:&nbsp;<br />#&nbsp;insmod&nbsp;hello.ko&nbsp;who</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">world</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;times</span><span style="color: #000000">=</span><span style="color: #000000">5</span><span style="color: #000000">&nbsp;<br /><br />出现5次</span><span style="color: #000000">"</span><span style="color: #000000">hello,world!</span><span style="color: #000000">"</span><span style="color: #000000">：&nbsp;<br /><br />#（</span><span style="color: #000000">1</span><span style="color: #000000">）hello,world</span><span style="color: #000000">!</span><span style="color: #000000">&nbsp;<br />#（</span><span style="color: #000000">2</span><span style="color: #000000">）hello,world</span><span style="color: #000000">!</span><span style="color: #000000">&nbsp;<br />#（</span><span style="color: #000000">3</span><span style="color: #000000">）hello,world</span><span style="color: #000000">!</span><span style="color: #000000">&nbsp;<br />#（</span><span style="color: #000000">4</span><span style="color: #000000">）hello,world</span><span style="color: #000000">!</span><span style="color: #000000">&nbsp;<br />#（</span><span style="color: #000000">5</span><span style="color: #000000">）hello,world</span><span style="color: #000000">!</span><span style="color: #000000">&nbsp;<br /><br />卸载：&nbsp;<br />#&nbsp;rmmod&nbsp;hello&nbsp;<br /><br />出现：&nbsp;<br />#Goodbye,world</span><span style="color: #000000">!</span><span style="color: #000000"><br /></span></div><img src ="http://www.cppblog.com/aaxron/aggbug/194716.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/aaxron/" target="_blank">天下</a> 2012-11-06 15:54 <a href="http://www.cppblog.com/aaxron/archive/2012/11/06/194716.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入理解linux内核第三版(定时测试)</title><link>http://www.cppblog.com/aaxron/archive/2012/08/03/186172.html</link><dc:creator>天下</dc:creator><author>天下</author><pubDate>Fri, 03 Aug 2012 08:40:00 GMT</pubDate><guid>http://www.cppblog.com/aaxron/archive/2012/08/03/186172.html</guid><wfw:comment>http://www.cppblog.com/aaxron/comments/186172.html</wfw:comment><comments>http://www.cppblog.com/aaxron/archive/2012/08/03/186172.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/aaxron/comments/commentRss/186172.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/aaxron/services/trackbacks/186172.html</trackback:ping><description><![CDATA[<img alt="" src="http://www.cppblog.com/images/cppblog_com/aaxron/kernel/rtc.JPG" /><br /><br /><img alt="" src="http://www.cppblog.com/images/cppblog_com/aaxron/kernel/tsc.JPG" height="339" width="794" /><br /><br /><br /><img alt="" src="http://www.cppblog.com/images/cppblog_com/aaxron/kernel/pit.JPG" height="638" width="793" /><img src ="http://www.cppblog.com/aaxron/aggbug/186172.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/aaxron/" target="_blank">天下</a> 2012-08-03 16:40 <a href="http://www.cppblog.com/aaxron/archive/2012/08/03/186172.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux设备驱动程序:gnu make 扩展语法</title><link>http://www.cppblog.com/aaxron/archive/2012/03/16/168055.html</link><dc:creator>天下</dc:creator><author>天下</author><pubDate>Fri, 16 Mar 2012 03:11:00 GMT</pubDate><guid>http://www.cppblog.com/aaxron/archive/2012/03/16/168055.html</guid><wfw:comment>http://www.cppblog.com/aaxron/comments/168055.html</wfw:comment><comments>http://www.cppblog.com/aaxron/archive/2012/03/16/168055.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/aaxron/comments/commentRss/168055.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/aaxron/services/trackbacks/168055.html</trackback:ping><description><![CDATA[<div><span style="font-size: 10pt;">要点:</span><br /><span style="font-size: 10pt;">在用户空间驱动程序</span><br /><span style="font-size: 10pt;">insmod</span><br /><span style="font-size: 10pt;">modprobe</span><br /><span style="font-size: 10pt;">rmmod</span><br /><br /><br /><span style="font-size: 10pt;">一些宏:</span><br /><span style="font-size: 10pt;">LINUX_VERSION_CODE</span><br /><span style="font-size: 10pt;">整数宏</span><br /><br /><br /><span style="font-size: 10pt;">GNU make 扩展语法</span><br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; font-size: 10pt;">obj</span><span style="color: #000000; font-size: 10pt;">-</span><span style="color: #000000; font-size: 10pt;">m&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; font-size: 10pt;">+=</span><span style="color: #000000; font-size: 10pt;">hello.o<br /></span><span style="color: #000000; font-size: 10pt;">KERNELDIR&nbsp;&nbsp;&nbsp;:</span><span style="color: #000000; font-size: 10pt;">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000; font-size: 10pt;">/</span><span style="color: #000000; font-size: 10pt;">usr</span><span style="color: #000000; font-size: 10pt;">/</span><span style="color: #000000; font-size: 10pt;">src</span><span style="color: #000000; font-size: 10pt;">/</span><span style="color: #000000; font-size: 10pt;">linux</span><span style="color: #000000; font-size: 10pt;">-</span><span style="color: #000000; font-size: 10pt;">headers</span><span style="color: #000000; font-size: 10pt;">-</span><span style="color: #000000; font-size: 10pt;">2.6</span><span style="color: #000000; font-size: 10pt;">.</span><span style="color: #000000; font-size: 10pt;">32</span><span style="color: #000000; font-size: 10pt;">-</span><span style="color: #000000; font-size: 10pt;">5</span><span style="color: #000000; font-size: 10pt;">-</span><span style="color: #000000; font-size: 10pt;">686</span><span style="color: #000000;"><br /></span><span style="color: #000000; font-size: 10pt;">PWD&nbsp;:</span><span style="color: #000000; font-size: 10pt;">=</span><span style="color: #000000; font-size: 10pt;">$(shell&nbsp;pwd)<br /></span><span style="color: #000000; font-size: 10pt;">.PHONY:&nbsp;test&nbsp;clean&nbsp;all<br /></span><span style="color: #000000; font-size: 10pt;">all:<br /></span><span style="color: #000000; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;$(MAKE)&nbsp;</span><span style="color: #000000; font-size: 10pt;">-</span><span style="color: #000000; font-size: 10pt;">C&nbsp;$(KERNELDIR)&nbsp;M</span><span style="color: #000000; font-size: 10pt;">=</span><span style="color: #000000; font-size: 10pt;">$(PWD)&nbsp;modules<br /></span><span style="color: #000000; font-size: 10pt;">clean:<br /></span><span style="color: #000000; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;rm&nbsp;</span><span style="color: #000000; font-size: 10pt;">-</span><span style="color: #000000; font-size: 10pt;">rf&nbsp;</span><span style="color: #000000; font-size: 10pt;">*</span><span style="color: #000000; font-size: 10pt;">.o&nbsp;</span><span style="color: #000000; font-size: 10pt;">*~</span><span style="color: #000000; font-size: 10pt;">&nbsp;core&nbsp;.depend&nbsp;.</span><span style="color: #000000; font-size: 10pt;">*</span><span style="color: #000000; font-size: 10pt;">.cmd&nbsp;</span><span style="color: #000000; font-size: 10pt;">*</span><span style="color: #000000; font-size: 10pt;">.ko&nbsp;</span><span style="color: #000000; font-size: 10pt;">*</span><span style="color: #000000; font-size: 10pt;">.mod.c&nbsp;.tmp_versionsm&nbsp;</span><span style="color: #000000; font-size: 10pt;">*</span><span style="color: #000000; font-size: 10pt;">.order&nbsp;</span><span style="color: #000000; font-size: 10pt;">*</span><span style="color: #000000; font-size: 10pt;">.symvers&nbsp;.tmp_versions<br /><br /></span><span style="color: #000000; font-size: 10pt;">test:<br /></span><span style="color: #000000; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;insmod&nbsp;.</span><span style="color: #000000; font-size: 10pt;">/</span><span style="color: #000000; font-size: 10pt;">hello.ko<br /></span><span style="color: #000000; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;rmmod&nbsp;hello<br /></span><span style="color: #000000; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;dmesg&nbsp;</span><span style="color: #000000; font-size: 10pt;">-</span><span style="color: #000000; font-size: 10pt;">c</span></div><br /><span style="font-size: 10pt;">obj-m</span><br /><span style="font-size: 10pt;">由内核构造系统使用的makefilet符号,用来确定在当前目录中应构造哪些模块.</span><br /><span style="font-size: 10pt;">即m:指定把对象编译为模块</span><br /><br /><span style="font-size: 10pt;">obj-y</span><br /><span style="font-size: 10pt;">指定把对象编译进内核中</span><br /><br /><span style="font-size: 10pt;">如果我们要构造的模块为module.ko,并由file1.c和file2.c则正确的makefile可如下编写:</span><br /><span style="font-size: 10pt;">obj-m :=module.o</span><br /><span style="font-size: 10pt;">module-objs :=file1.o file2.o</span><br /><br /><span style="font-size: 10pt;">为了让上面的makefile可以工作,必须在大的内核构造系统环境中调用它们,所以上述命令首先要改变-C指定的目录,即:</span><br /><span style="font-size: 10pt;">&nbsp;$(MAKE)&nbsp;</span><span style="color: #000000; font-size: 10pt;">-</span><span style="color: #000000; font-size: 10pt;">C&nbsp;$(KERNELDIR)</span><br /><span style="font-size: 10pt;">然后指定M变量目录,即让makefile在构造modules目标之前返回到模块源代码的目录,既当前目录 M=$(PWD),最后modules目标指向obj-m变量中设定的模块.</span><br />
<p><font color="#000000" face="Verdana"><br /><span style="font-size: 10pt;">M不是一个编译选项，而是一个变量，从顶层makefile文件里可以找到它的定义 </span><br /><span style="font-size: 10pt;">文件在</span><br /><span style="font-size: 10pt;">/usr/src/linux-headers-2.6.32-5-common/Makefile</span></font></p>
<p><font color="#000000" face="Verdana"><span style="font-size: 10pt;">69 ifeq ("$(origin M)", "command line")</span><br /><span style="font-size: 10pt;">70&nbsp;&nbsp; KBUILD_EXTMOD := $(M)</span><br /><span style="font-size: 10pt;">71 endif</span></font></p><p><br /><font color="#000000" face="Verdana"><span style="font-size: 10pt;"></span></font></p><p><font color="#000000" face="Verdana"><span style="font-size: 10pt;">-C 用于指定内核源代码的目录</span></font></p><p><font color="#000000" face="Verdana"><span style="font-size: 10pt;">-M 用于module所在的目录<br /></span></font></p>
<p><font color="#000000" face="Verdana"></font>&nbsp;</p><div>如果一个模块包括了多个.c文件(如 file1.c , file2.c),则应该以如下方式编写Makefile<br />obj-m := modulename.o<br />module-objs := file1.o file2.o<br /></div><br /></div><img src ="http://www.cppblog.com/aaxron/aggbug/168055.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/aaxron/" target="_blank">天下</a> 2012-03-16 11:11 <a href="http://www.cppblog.com/aaxron/archive/2012/03/16/168055.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>中断及中断处理过程</title><link>http://www.cppblog.com/aaxron/archive/2011/11/16/160280.html</link><dc:creator>天下</dc:creator><author>天下</author><pubDate>Wed, 16 Nov 2011 09:25:00 GMT</pubDate><guid>http://www.cppblog.com/aaxron/archive/2011/11/16/160280.html</guid><wfw:comment>http://www.cppblog.com/aaxron/comments/160280.html</wfw:comment><comments>http://www.cppblog.com/aaxron/archive/2011/11/16/160280.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/aaxron/comments/commentRss/160280.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/aaxron/services/trackbacks/160280.html</trackback:ping><description><![CDATA[<div><div><div>中断及中断处理过程</div></div><div>1. 中断和异常的概念区别</div><div>&nbsp; &nbsp;Intel的官方文档里将中断和异常理解为两种中断当前程序执行的不同机制。这是中断和异常的共同点。不同点在于：</div><div>&nbsp; &nbsp;中断(interrupt)是异步的事件，典型的比如由I/O设备触发；异常(exception)是同步的事件，典型的比如处理器执行某条指令时发现出错了等等。</div><div>&nbsp; &nbsp;中断又可以分为可屏蔽中断和非可屏蔽中断，异常又分为故障、陷阱和异常中止3种，它们的具体区别很多书籍和官方文档都解释的比较清楚这里不再赘述。</div><div>关于它们的区别有两点是需要注意的：</div><div>1）平常所说的屏蔽中断是不包括异常的，即异常不会因为CPU的IF位被清（关中断，指令：cli）而受影响，比如缺页异常，即使关了中断也会触发CPU的处理。</div><div>2）通常说的int 80h这种系统调用使用的中断方式实际上硬件上是理解为异常处理的，因此也不会被屏蔽掉，这也很好理解，int 80h这种中断方式是程序里主动触发的，对于CPU来说属于同步事件，因此也就属于异常的范畴。</div><div></div><div>2. 中断（异常）处理过程</div><div>&nbsp; &nbsp;需要明确的一点是CPU对于中断和异常的具体处理机制本质上是完全一致的，即：</div><div>当CPU收到中断或者异常的信号时，它会暂停执行当前的程序或任务，通过一定的机制跳转到负责处理这个信号的相关处理程序中，在完成对这个信号的处理后再跳回到刚才被打断的程序或任务中。这里只描述保护模式下的处理过程，搞清楚了保护模式下的处理过程（更复杂），实模式下的处理机制也就容易理解了。</div><div></div><div>具体的处理过程如下：</div><div>0）中断响应的事前准备：</div><div>系统要想能够应对各种不同的中断信号，总的来看就是需要知道每种信号应该由哪个中断服务程序负责以及这些中断服务程序具体是如何工作的。系统只有事前对这两件事都知道得很清楚，才能正确地响应各种中断信号和异常。</div><div>[a]系统将所有的中断信号统一进行了编号（一共256个：0～255），这个号称为中断向量，具体哪个中断向量表示哪种中断有的是规定好的，也有的是在给定范围内自行设定的。 &nbsp;</div><div>中断向量和中断服务程序的对应关系主要是由IDT（中断向量表）负责。操作系统在IDT中设置好各种中断向量对应的中断描述符（一共有三类中断门描述符：任务门、中断门和陷阱门），留待CPU查询使用。而IDT本身的位置是由idtr保存的，当然这个地址也是由OS填充的。</div><div></div><div>[b]中断服务程序具体负责处理中断（异常）的代码是由软件，也就是操作系统实现的，这部分代码属于操作系统内核代码。也就是说从CPU检测中断信号到加载中断服务程序以及从中断服务程序中恢复执行被暂停的程序，这个流程基本上是硬件确定下来的，而具体的中断向量和服务程序的对应关系设置和中断服务程序的内容是由操作系统确定的。</div><div></div><div>1）CPU检查是否有中断/异常信号</div><div>&nbsp; &nbsp;CPU在执行完当前程序的每一条指令后，都会去确认在执行刚才的指令过程中中断控制器（如：8259A）是否发送中断请求过来，如果有那么CPU就会在相应的时钟脉冲到来时从总线上读取中断请求对应的中断向量[2]。</div><div>对于异常和系统调用那样的软中断，因为中断向量是直接给出的，所以和通过IRQ（中断请求）线发送的硬件中断请求不同，不会再专门去取其对应的中断向量。</div><div></div><div>2）根据中断向量到IDT表中取得处理这个向量的中断程序的段选择符</div><div>&nbsp; &nbsp;CPU根据得到的中断向量到IDT表里找到该向量对应的中断描述符，中断描述符里保存着中断服务程序的段选择符。</div><div></div><div>3）根据取得的段选择符到GDT中找相应的段描述符</div><div>&nbsp; &nbsp;CPU使用IDT查到的中断服务程序的段选择符从GDT中取得相应的段描述符，段描述符里保存了中断服务程序的段基址和属性信息，此时CPU就得到了中断服务程序的起始地址。</div><div>&nbsp; &nbsp;这里，CPU会根据当前cs寄存器里的CPL和GDT的段描述符的DPL，以确保中断服务程序是高于当前程序的，如果这次中断是编程异常（如：int 80h系统调用），那么还要检查CPL和IDT表中中断描述符的DPL，以保证当前程序有权限使用中断服务程序，这可以避免用户应用程序访问特殊的陷阱门和中断门[3]。</div><div></div><div></div><div>4）CPU根据特权级的判断设定即将运行的中断服务程序要使用的栈的地址</div><div>&nbsp; &nbsp;CPU会根据CPL和中断服务程序段描述符的DPL信息确认是否发生了特权级的转换，比如当前程序正运行在用户态，而中断程序是运行在内核态的，则意味着发生了特权级的转换，这时CPU会从当前程序的TSS信息（该信息在内存中的首地址存在TR寄存器中）里取得该程序的内核栈地址，即包括ss和esp的值，并立即将系统当前使用的栈切换成新的栈。这个栈就是即将运行的中断服务程序要使用的栈。紧接着就将当前程序使用的ss,esp压到新栈中保存起来。</div><div></div><div>6）保护当前程序的现场</div><div>&nbsp; &nbsp;CPU开始利用栈保护被暂停执行的程序的现场：依次压入当前程序使用的eflags，cs，eip，errorCode（如果是有错误码的异常）信息。</div><div>官方文档[1]给出的栈变化的示意图如下：</div><div></div><div></div><div>7）跳转到中断服务程序的第一条指令开始执行</div><div>&nbsp; &nbsp;CPU利用中断服务程序的段描述符将其第一条指令的地址加载到cs和eip寄存器中，开始执行中断服务程序。这意味着先前的程序被暂停执行，中断服务程序正式开始工作。</div><div></div><div>8）中断服务程序处理完毕，恢复执行先前中断的程序</div><div>&nbsp; &nbsp;在每个中断服务程序的最后，必须有中断完成返回先前程序的指令，这就是iret（或iretd）。程序执行这条返回指令时，会从栈里弹出先前保存的被暂停程序的现场信息，即eflags,cs,eip重新开始执行。<br /><img src="http://www.cppblog.com/images/cppblog_com/aaxron/中断.png" alt="" /></div></div><div></div><img src ="http://www.cppblog.com/aaxron/aggbug/160280.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/aaxron/" target="_blank">天下</a> 2011-11-16 17:25 <a href="http://www.cppblog.com/aaxron/archive/2011/11/16/160280.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Debian 6 驱动开发环境搭建</title><link>http://www.cppblog.com/aaxron/archive/2011/11/01/159454.html</link><dc:creator>天下</dc:creator><author>天下</author><pubDate>Tue, 01 Nov 2011 06:24:00 GMT</pubDate><guid>http://www.cppblog.com/aaxron/archive/2011/11/01/159454.html</guid><wfw:comment>http://www.cppblog.com/aaxron/comments/159454.html</wfw:comment><comments>http://www.cppblog.com/aaxron/archive/2011/11/01/159454.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/aaxron/comments/commentRss/159454.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/aaxron/services/trackbacks/159454.html</trackback:ping><description><![CDATA[<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">Debian&nbsp;</span><span style="color: #800000; ">6</span><span style="color: #000000; ">&nbsp;驱动开发环境搭建<br /></span><span style="color: #800000; ">1</span><span style="color: #000000; ">.</span><span style="color: #000000; ">安装相关工具<br />apt</span><span style="color: #000000; ">-</span><span style="color: #000000; ">get&nbsp;install&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">y&nbsp;gcc&nbsp;g</span><span style="color: #000000; ">++</span><span style="color: #000000; ">&nbsp;gdb&nbsp;make&nbsp;build</span><span style="color: #000000; ">-</span><span style="color: #000000; ">essential<br /><br /></span><span style="color: #800000; ">2</span><span style="color: #000000; ">.</span><span style="color: #000000; ">查看系统版本</span><span style="color: #000000; ">,</span><span style="color: #000000; ">并安装内核头文件<br />root@</span><span style="color: #800000; ">192.168</span><span style="color: #000000; ">.</span><span style="color: #800000; ">20.128</span><span style="color: #000000; ">:~/</span><span style="color: #000000; ">&nbsp;</span><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;uname&nbsp;-r</span><span style="color: #008000; "><br /></span><span style="color: #800000; ">2.6</span><span style="color: #000000; ">.</span><span style="color: #800000; ">32</span><span style="color: #000000; ">-</span><span style="color: #800000; ">5</span><span style="color: #000000; ">-</span><span style="color: #800000; ">686</span><span style="color: #000000; "><br />apt</span><span style="color: #000000; ">-</span><span style="color: #000000; ">cache&nbsp;search&nbsp;linux</span><span style="color: #000000; ">-</span><span style="color: #000000; ">headers</span><span style="color: #000000; ">-</span><span style="color: #800000; ">2.6</span><span style="color: #000000; ">.</span><span style="color: #800000; ">32</span><span style="color: #000000; ">-</span><span style="color: #800000; ">5</span><span style="color: #000000; ">-</span><span style="color: #800000; ">686</span><span style="color: #000000; "><br />apt</span><span style="color: #000000; ">-</span><span style="color: #000000; ">get&nbsp;install&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">y&nbsp;linux</span><span style="color: #000000; ">-</span><span style="color: #000000; ">headers</span><span style="color: #000000; ">-</span><span style="color: #800000; ">2.6</span><span style="color: #000000; ">.</span><span style="color: #800000; ">32</span><span style="color: #000000; ">-</span><span style="color: #800000; ">5</span><span style="color: #000000; ">-</span><span style="color: #800000; ">686</span><span style="color: #000000; "><br /><br /></span><span style="color: #800000; ">3</span><span style="color: #000000; ">.</span><span style="color: #000000; ">查看内核头文件位置<br />看下会安装到哪</span><span style="color: #000000; ">:</span><span style="color: #000000; "><br />apt</span><span style="color: #000000; ">-</span><span style="color: #000000; ">cache&nbsp;show&nbsp;linux</span><span style="color: #000000; ">-</span><span style="color: #000000; ">headers</span><span style="color: #000000; ">-</span><span style="color: #800000; ">2.6</span><span style="color: #000000; ">.</span><span style="color: #800000; ">32</span><span style="color: #000000; ">-</span><span style="color: #800000; ">5</span><span style="color: #000000; ">-</span><span style="color: #800000; ">686</span><span style="color: #000000; "><br /><br />有这么句</span><span style="color: #000000; ">:</span><span style="color: #000000; "><br />These&nbsp;files&nbsp;are&nbsp;going&nbsp;to&nbsp;be&nbsp;installed&nbsp;into<br /></span><span style="color: #000000; ">/</span><span style="color: #000000; ">usr</span><span style="color: #000000; ">/</span><span style="color: #000000; ">src</span><span style="color: #000000; ">/</span><span style="color: #000000; ">linux</span><span style="color: #000000; ">-</span><span style="color: #000000; ">headers</span><span style="color: #000000; ">-</span><span style="color: #800000; ">2.6</span><span style="color: #000000; ">.</span><span style="color: #800000; ">32</span><span style="color: #000000; ">-</span><span style="color: #800000; ">5</span><span style="color: #000000; ">-</span><span style="color: #800000; ">686</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&nbsp;and&nbsp;can&nbsp;be&nbsp;used&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;building&nbsp;modules<br /><br />就是这里啦</span><span style="color: #000000; ">.</span><span style="color: #000000; "><br /></span><span style="color: #000000; ">/</span><span style="color: #000000; ">usr</span><span style="color: #000000; ">/</span><span style="color: #000000; ">src</span><span style="color: #000000; ">/</span><span style="color: #000000; ">linux</span><span style="color: #000000; ">-</span><span style="color: #000000; ">headers</span><span style="color: #000000; ">-</span><span style="color: #800000; ">2.6</span><span style="color: #000000; ">.</span><span style="color: #800000; ">32</span><span style="color: #000000; ">-</span><span style="color: #800000; ">5</span><span style="color: #000000; ">-</span><span style="color: #800000; ">686</span><span style="color: #000000; "><br /><br /></span><span style="color: #800000; ">4</span><span style="color: #000000; ">.</span><span style="color: #000000; ">好了</span><span style="color: #000000; ">,</span><span style="color: #000000; ">接下来写测试例子</span><span style="color: #000000; ">:</span><span style="color: #000000; ">hello</span><span style="color: #000000; ">,</span><span style="color: #000000; ">抄了http</span><span style="color: #000000; ">://</span><span style="color: #000000; ">bbs</span><span style="color: #000000; ">.</span><span style="color: #000000; ">chinaunix</span><span style="color: #000000; ">.</span><span style="color: #000000; ">net</span><span style="color: #000000; ">/</span><span style="color: #000000; ">thread</span><span style="color: #000000; ">-</span><span style="color: #800000; ">3570849</span><span style="color: #000000; ">-</span><span style="color: #800000; ">1</span><span style="color: #000000; ">-</span><span style="color: #800000; ">1</span><span style="color: #000000; ">.</span><span style="color: #000000; ">html<br />上的代码</span><span style="color: #000000; ">:</span><span style="color: #000000; "><br />文件1</span><span style="color: #000000; ">:</span><span style="color: #000000; ">hello</span><span style="color: #000000; ">.</span><span style="color: #000000; ">c<br /></span><span style="color: #008000; ">#</span><span style="color: #008000; ">include&nbsp;&lt;linux/init.h&gt;<br />#include&nbsp;&lt;linux/module.h&gt;</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">MODULE_LICENSE(</span><span style="color: #000000; font-weight: bold; ">"</span><span style="color: #000000; font-weight: bold; ">GPL</span><span style="color: #000000; font-weight: bold; ">"</span><span style="color: #000000; ">);<br /><br />static&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;hello_init(void)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;printk(KERN_ALERT&nbsp;</span><span style="color: #000000; font-weight: bold; ">"</span><span style="color: #000000; font-weight: bold; ">Hello,&nbsp;world\n</span><span style="color: #000000; font-weight: bold; ">"</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800000; ">0</span><span style="color: #000000; ">;<br />}<br /><br />static&nbsp;void&nbsp;hello_exit(void)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;printk(KERN_ALERT&nbsp;</span><span style="color: #000000; font-weight: bold; ">"</span><span style="color: #000000; font-weight: bold; ">Goodbye,&nbsp;cruel&nbsp;world\n</span><span style="color: #000000; font-weight: bold; ">"</span><span style="color: #000000; ">);<br />}<br /><br />module_init(hello_init);<br />module_exit(hello_exit);<br /><br />文件2</span><span style="color: #000000; ">:</span><span style="color: #000000; ">Makefile</span><span style="color: #000000; ">:</span><span style="color: #000000; "><br />obj</span><span style="color: #000000; ">-</span><span style="color: #000000; ">m&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">+=</span><span style="color: #000000; ">hello</span><span style="color: #000000; ">.</span><span style="color: #000000; ">o<br />KERNELDIR&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">:=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">usr</span><span style="color: #000000; ">/</span><span style="color: #000000; ">src</span><span style="color: #000000; ">/</span><span style="color: #000000; ">linux</span><span style="color: #000000; ">-</span><span style="color: #000000; ">headers</span><span style="color: #000000; ">-</span><span style="color: #800000; ">2.6</span><span style="color: #000000; ">.</span><span style="color: #800000; ">32</span><span style="color: #000000; ">-</span><span style="color: #800000; ">5</span><span style="color: #000000; ">-</span><span style="color: #800000; ">686</span><span style="color: #000000; "><br />PWD&nbsp;</span><span style="color: #000000; ">:=</span><span style="color: #000000; ">$(shell&nbsp;pwd)<br /></span><span style="color: #000000; ">.</span><span style="color: #000000; ">PHONY</span><span style="color: #000000; ">:</span><span style="color: #000000; ">&nbsp;test&nbsp;clean&nbsp;all<br />all</span><span style="color: #000000; ">:</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;$(MAKE)&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">C&nbsp;$(KERNELDIR)&nbsp;M</span><span style="color: #000000; ">=</span><span style="color: #000000; ">$(PWD)&nbsp;modules<br />clean</span><span style="color: #000000; ">:</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;rm&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">rf&nbsp;</span><span style="color: #000000; ">*.</span><span style="color: #000000; ">o&nbsp;</span><span style="color: #000000; ">*~</span><span style="color: #000000; ">&nbsp;core&nbsp;</span><span style="color: #000000; ">.</span><span style="color: #000000; ">depend&nbsp;</span><span style="color: #000000; ">.*.</span><span style="color: #000000; ">cmd&nbsp;</span><span style="color: #000000; ">*.</span><span style="color: #000000; ">ko&nbsp;</span><span style="color: #000000; ">*.</span><span style="color: #000000; ">mod</span><span style="color: #000000; ">.</span><span style="color: #000000; ">c&nbsp;</span><span style="color: #000000; ">.</span><span style="color: #000000; ">tmp_versionsm&nbsp;</span><span style="color: #000000; ">*.</span><span style="color: #000000; ">order&nbsp;</span><span style="color: #000000; ">*.</span><span style="color: #000000; ">symvers<br /><br />test</span><span style="color: #000000; ">:</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;insmod&nbsp;</span><span style="color: #000000; ">./</span><span style="color: #000000; ">hello</span><span style="color: #000000; ">.</span><span style="color: #000000; ">ko<br />&nbsp;&nbsp;&nbsp;&nbsp;rmmod&nbsp;hello<br />&nbsp;&nbsp;&nbsp;&nbsp;dmesg&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">c<br />&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #800000; ">5</span><span style="color: #000000; ">.</span><span style="color: #000000; ">好了</span><span style="color: #000000; ">,</span><span style="color: #000000; ">现在测试开始</span><span style="color: #000000; ">,</span><span style="color: #000000; ">成功的话</span><span style="color: #000000; ">,</span><span style="color: #000000; ">就可以看到下面的文字了</span><span style="color: #000000; ">.</span><span style="color: #000000; "><br />如果有问题的话</span><span style="color: #000000; ">,</span><span style="color: #000000; ">向google大神请教吧</span><span style="color: #000000; ">.</span><span style="color: #000000; ">另外要看<br />root@</span><span style="color: #800000; ">192.168</span><span style="color: #000000; ">.</span><span style="color: #800000; ">20.128</span><span style="color: #000000; ">:~/</span><span style="color: #000000; ">cpp&nbsp;</span><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;make&nbsp;</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">make&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">C&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">usr</span><span style="color: #000000; ">/</span><span style="color: #000000; ">src</span><span style="color: #000000; ">/</span><span style="color: #000000; ">linux</span><span style="color: #000000; ">-</span><span style="color: #000000; ">headers</span><span style="color: #000000; ">-</span><span style="color: #800000; ">2.6</span><span style="color: #000000; ">.</span><span style="color: #800000; ">32</span><span style="color: #000000; ">-</span><span style="color: #800000; ">5</span><span style="color: #000000; ">-</span><span style="color: #800000; ">686</span><span style="color: #000000; ">&nbsp;M</span><span style="color: #000000; ">=/</span><span style="color: #000000; ">root</span><span style="color: #000000; ">/</span><span style="color: #000000; ">cpp&nbsp;modules<br />make[</span><span style="color: #800000; ">1</span><span style="color: #000000; ">]</span><span style="color: #000000; ">:</span><span style="color: #000000; ">&nbsp;Entering&nbsp;directory&nbsp;`</span><span style="color: #000000; ">/</span><span style="color: #000000; ">usr</span><span style="color: #000000; ">/</span><span style="color: #000000; ">src</span><span style="color: #000000; ">/</span><span style="color: #000000; ">linux</span><span style="color: #000000; ">-</span><span style="color: #000000; ">headers</span><span style="color: #000000; ">-</span><span style="color: #800000; ">2.6</span><span style="color: #000000; ">.</span><span style="color: #800000; ">32</span><span style="color: #000000; ">-</span><span style="color: #800000; ">5</span><span style="color: #000000; ">-</span><span style="color: #800000; ">686</span><span style="color: #000000; font-weight: bold; ">'</span><span style="color: #000000; font-weight: bold; "><br />&nbsp;&nbsp;CC&nbsp;[M]&nbsp;&nbsp;/root/cpp/hello.o<br />&nbsp;&nbsp;Building&nbsp;modules,&nbsp;stage&nbsp;2.<br />&nbsp;&nbsp;MODPOST&nbsp;1&nbsp;modules<br />&nbsp;&nbsp;CC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/root/cpp/hello.mod.o<br />&nbsp;&nbsp;LD&nbsp;[M]&nbsp;&nbsp;/root/cpp/hello.ko<br />make[1]:&nbsp;Leaving&nbsp;directory&nbsp;`/usr/src/linux-headers-2.6.32-5-686</span><span style="color: #000000; font-weight: bold; ">'</span><span style="color: #000000; "><br />root@</span><span style="color: #800000; ">192.168</span><span style="color: #000000; ">.</span><span style="color: #800000; ">20.128</span><span style="color: #000000; ">:~/</span><span style="color: #000000; ">cpp&nbsp;</span><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;make&nbsp;test</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">insmod&nbsp;</span><span style="color: #000000; ">./</span><span style="color: #000000; ">hello</span><span style="color: #000000; ">.</span><span style="color: #000000; ">ko<br />rmmod&nbsp;hello<br />dmesg&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">c<br />[&nbsp;&nbsp;</span><span style="color: #800000; ">673.500413</span><span style="color: #000000; ">]&nbsp;Hello</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&nbsp;world<br />[&nbsp;&nbsp;</span><span style="color: #800000; ">673.504907</span><span style="color: #000000; ">]&nbsp;Goodbye</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&nbsp;cruel&nbsp;world<br />root@</span><span style="color: #800000; ">192.168</span><span style="color: #000000; ">.</span><span style="color: #800000; ">20.128</span><span style="color: #000000; ">:~/</span><span style="color: #000000; ">cpp&nbsp;</span><span style="color: #008000; ">#<br /></span><span style="color: #000000; "><br /><br /></span><span style="color: #800000; ">6</span><span style="color: #000000; ">.</span><span style="color: #000000; ">最后</span><span style="color: #000000; ">.</span><span style="color: #000000; ">安装开发帮助文档<br />apt</span><span style="color: #000000; ">-</span><span style="color: #000000; ">get&nbsp;install&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">y&nbsp;manpages</span><span style="color: #000000; ">-</span><span style="color: #000000; ">kernel</span><span style="color: #000000; ">-</span><span style="color: #000000; ">dev&nbsp;linux</span><span style="color: #000000; ">-</span><span style="color: #000000; ">manual<br />man&nbsp;</span><span style="color: #800000; ">9</span><span style="color: #000000; ">&nbsp;printk<br />man&nbsp;</span><span style="color: #800000; ">9</span><span style="color: #000000; ">&nbsp;module_init<br /><br />参考资料</span><span style="color: #000000; ">:</span><span style="color: #000000; ">&nbsp;<br />http</span><span style="color: #000000; ">://</span><span style="color: #000000; ">bbs</span><span style="color: #000000; ">.</span><span style="color: #000000; ">chinaunix</span><span style="color: #000000; ">.</span><span style="color: #000000; ">net</span><span style="color: #000000; ">/</span><span style="color: #000000; ">thread</span><span style="color: #000000; ">-</span><span style="color: #800000; ">3570849</span><span style="color: #000000; ">-</span><span style="color: #800000; ">1</span><span style="color: #000000; ">-</span><span style="color: #800000; ">1</span><span style="color: #000000; ">.</span><span style="color: #000000; ">html</span></div> <img src ="http://www.cppblog.com/aaxron/aggbug/159454.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/aaxron/" target="_blank">天下</a> 2011-11-01 14:24 <a href="http://www.cppblog.com/aaxron/archive/2011/11/01/159454.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>