<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>不敢流泪 &#187; linux kernel</title>
	<atom:link href="http://www.boluor.com/tag/linux-kernel/feed" rel="self" type="application/rss+xml" />
	<link>http://www.boluor.com</link>
	<description></description>
	<lastBuildDate>Fri, 07 Oct 2011 07:28:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>linux内核模块之间通信</title>
		<link>http://www.boluor.com/communication-between-the-kernel-module-of-linux.html</link>
		<comments>http://www.boluor.com/communication-between-the-kernel-module-of-linux.html#comments</comments>
		<pubDate>Wed, 29 Jul 2009 18:11:42 +0000</pubDate>
		<dc:creator>boluor</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[linux kernel]]></category>

		<guid isPermaLink="false">http://www.boluor.com/?p=217</guid>
		<description><![CDATA[<p>    今天师兄问，linux内核模块之间如何进行通信？我才想起我之前也有这个疑问，只是当时不需要所以就没去关心了。晚上查了些资料，终于弄明白了些。<br />
    这里的通信可以简单点理解，就是模块B如何调用A的函数，变量或者常量。为了简化，我设计一个模块A中的一个函数为printMSG，原型为int printMSG(int n);传入的参数n表示打印几遍一个固定的字符串。模块A(在helloworld基础上修改的，所以名字都没变&#8230;懒)源码：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:Courier new,verdana;"><span style="color: #339933;">#include &#60;linux/init.h&#62; </span>
<span style="color: #339933;">#include &#60;linux/module.h&#62;  </span>
<span style="color: #993333;">int</span> __init hello_init<span style="color: #009900;">&#40;</span><span style="color: #993333;">vo</span></pre></div></div><p>&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>    今天师兄问，linux内核模块之间如何进行通信？我才想起我之前也有这个疑问，只是当时不需要所以就没去关心了。晚上查了些资料，终于弄明白了些。<br />
    这里的通信可以简单点理解，就是模块B如何调用A的函数，变量或者常量。为了简化，我设计一个模块A中的一个函数为printMSG，原型为int printMSG(int n);传入的参数n表示打印几遍一个固定的字符串。模块A(在helloworld基础上修改的，所以名字都没变&#8230;懒)源码：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:Courier new,verdana;"><span style="color: #339933;">#include &lt;linux/init.h&gt; </span>
<span style="color: #339933;">#include &lt;linux/module.h&gt;  </span>
<span style="color: #993333;">int</span> __init hello_init<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> 
    printk<span style="color: #009900;">&#40;</span>KERN_ALERT <span style="color: #ff0000;">&quot;hello world
&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> 
<span style="color: #009900;">&#125;</span> 
&nbsp;
<span style="color: #993333;">int</span> printMSG<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> n<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> 
    <span style="color: #993333;">int</span> i<span style="color: #339933;">;</span> 
    <span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>i<span style="color: #339933;">&lt;</span>n<span style="color: #339933;">;</span>i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> 
        printk<span style="color: #009900;">&#40;</span>KERN_ALERT <span style="color: #ff0000;">&quot;I am boluor
&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> 
<span style="color: #009900;">&#125;</span> 
&nbsp;
<span style="color: #993333;">void</span> __exit hello_exit<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> 
    printk<span style="color: #009900;">&#40;</span>KERN_ALERT <span style="color: #ff0000;">&quot;byebye,hello world
&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
<span style="color: #009900;">&#125;</span> 
EXPORT_SYMBOL<span style="color: #009900;">&#40;</span>printMSG<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
module_init<span style="color: #009900;">&#40;</span>hello_init<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
module_exit<span style="color: #009900;">&#40;</span>hello_exit<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p><span id="more-217"></span><br />
    其中用到了EXPORT_SYMBOL宏来表明导出printMSG这个符号。还有一个EXPORT_SYMBOL_GPL宏，导出的符号具有GPL授权。内核所有的导出符号可以通过 : cat /proc/kallsyms来查看，太多了，所以最好导出到一个文件中慢慢看。在其中就可以发现printk等等我们常见的内核函数。</p>
<p>    现在我们写一个测试模块B，他将调用A中的printMSG函数。B的源码和A大致一样，这里只给出不同的地方吧。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:Courier new,verdana;"><span style="color: #000000; font-weight: bold;">extern</span> <span style="color: #993333;">int</span> printMSG<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> n<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  <span style="color: #666666; font-style: italic;">//声明printMSG来自外部文件.</span>
<span style="color: #993333;">int</span> __init test_init<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>     <span style="color: #666666; font-style: italic;">//在模块加载的时候调用.</span>
    printk<span style="color: #009900;">&#40;</span>KERN_ALERT <span style="color: #ff0000;">&quot;hello world
&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    printMSG<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>    两个模块的Makefile文件参照<a href="http://www.boluor.com/?p=86">Linux设备驱动学习笔记</a>.编译通过后，先insmod 模块A，再insmod B，就可以发现B可以插入了。查看log，通过dmesg | tail -10就可以发现B在加载的时候输出了三行”I am boluor”。<br />
    通过以上的测试，对linux所谓的LKM有了更深的认识。内核其实就是一个大的程序，当我们动态的加载进入一个模块时，他还是内核这个大程序的一部分，所以我们可以像一个工程中那样，将函数导出到内核符号表中，再将需要调用的外部的函数声明为extern关键字，就可以方便的调用了。</p>
<p>     从回来到现在，搜了很多资料，抄来抄去的，都没说明到底怎么作，问题依旧没有答案。在CSDN上看到一帖，也說得这问题，中有人说，需要使用系统调用。。。不知道怎么想的，反正测试没通过。这些还是得靠不断的去试，才会有正确的结果。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boluor.com/communication-between-the-kernel-module-of-linux.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Linux设备驱动学习笔记（一）</title>
		<link>http://www.boluor.com/note-of-linux-device-driver.html</link>
		<comments>http://www.boluor.com/note-of-linux-device-driver.html#comments</comments>
		<pubDate>Mon, 25 May 2009 17:19:02 +0000</pubDate>
		<dc:creator>boluor</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[linux kernel]]></category>

		<guid isPermaLink="false">http://www.boluor.com/?p=86</guid>
		<description><![CDATA[<p>	在CSDN上看到了fudan_abc写的linux那些事，感受颇多。觉得自己虽然不如人家那么才高八斗，不过，为了让自己不至于那么快忘记，也开始写些笔记吧。</p>
<p>这次的主要内容：<br />
<a href="#c1">1.linux设备驱动程序的作用</a><br />
<a href="#c2">2.内核模块和用户空间程序的区别</a><br />
<a href="#c3">3.Hello world程序. </a><br />
<a href="#c4">4.Makefile文件</a><br />
<a href="#c5">5.编译，加载内核模块</a><br />
<a href="#c6">6.Other tips</a><br />
<a href="#c7">7.好书和网站</a></p>
<p><a name="c1">1．linux设备驱动程序的作用</a><br />
	简单的说，驱动程序告诉了我们可以提供了那些能力，但是没有告诉我们怎么使用这些能力。按照《linux设备驱动程序》上的说法，前一部分叫做”机制”，后面的叫作”策略”。linux设备驱动程序完成来自上层软件的抽象调用，让上层不&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>	在CSDN上看到了fudan_abc写的linux那些事，感受颇多。觉得自己虽然不如人家那么才高八斗，不过，为了让自己不至于那么快忘记，也开始写些笔记吧。</p>
<p>这次的主要内容：<br />
<a href="#c1">1.linux设备驱动程序的作用</a><br />
<a href="#c2">2.内核模块和用户空间程序的区别</a><br />
<a href="#c3">3.Hello world程序. </a><br />
<a href="#c4">4.Makefile文件</a><br />
<a href="#c5">5.编译，加载内核模块</a><br />
<a href="#c6">6.Other tips</a><br />
<a href="#c7">7.好书和网站</a></p>
<p><a name="c1">1．linux设备驱动程序的作用</a><br />
	简单的说，驱动程序告诉了我们可以提供了那些能力，但是没有告诉我们怎么使用这些能力。按照《linux设备驱动程序》上的说法，前一部分叫做”机制”，后面的叫作”策略”。linux设备驱动程序完成来自上层软件的抽象调用，让上层不用去关心底层到底怎么实现。比如说音频设备驱动，提供了一个接口 playsound（）.那么上层只要去调用这个接口，就可以发音，而不必关心到底怎么让音频设备发音。<br />
<span id="more-86"></span><br />
<a name="c2">2.内核模块和用户空间的应用程序的区别</a><br />
	内核模块工作在内核态，应用程序工作在用户态。这个概念是操作系统理论的基础，不了解的，罚抄一编《操作系统》&#8230; 不同于应用程序是从头到尾处理一个任务，内核模块只是注册下自己，以便服务将来的请求。模块初始化的任务是为了将来调用模块的函数作准备，就好像是说”我在这里, 这是我能做的”。当模块退出时，就好像是在说，”我不在这里了，不要请我作任何事了”。<br />
	内核模块和应用程序的区别还有，内核模块在卸载的时候必须小心翼翼的将初始化时生成的资源给还原。虽然感觉很麻烦，但是无独有偶，这也方便了我们测试程序，不用为了修改模块后再调试而必须重启。<br />
	在用户空间写程序时，可以调用并非自己写的函数，比如printf，但是在内核中，因为没有库链接到内核中，所以绝大部分不能调用普通的头文件，当然有例外。在内核中大部分的头文件都定义在了include/linux和include/asm中。<br />
	还有一点是，如果用户空间的程序出错了，没啥事，但是内核模块出错了，至少会终结当前的进程，极有可能导致系统崩溃。</p>
<p><a name="c3">3．hello world程序</a><br />
	理论暂且放一遍&#8230;看代码.一个超级入门的程序，hello world.c。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:Courier new,verdana;"><span style="color: #339933;">#include &lt;linux/init.h&gt;</span>
<span style="color: #339933;">#include &lt;linux/module.h&gt;</span>
&nbsp;
<span style="color: #993333;">static</span> <span style="color: #993333;">int</span> __init hello_init<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	printk<span style="color: #009900;">&#40;</span>KERN_ALERT <span style="color: #ff0000;">&quot;hello world
&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">static</span> <span style="color: #993333;">void</span> __exit hello_exit<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	printk<span style="color: #009900;">&#40;</span>KERN_ALERT <span style="color: #ff0000;">&quot;byebye,hello world
&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
module_init<span style="color: #009900;">&#40;</span>hello_init<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
module_exit<span style="color: #009900;">&#40;</span>hello_exit<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>这个模块很简单，只有四个部分。<br />
我们先看最后两行。module_init和module_exit是两个宏，用来声明模块初始时调用的函数和卸载时调用的函数。参数就是对应的函数名。<br />
然后看初始化函数hello_init。函数声明为static并不是必须的。一般来说，这个设备的函数并不需要被其他的内核模块访问，声明为static就可以了。然后是__init，和__exit一样是个标志，告诉内核这些函数或者结构体只是在初始化或者退出的时候用下，其他的时候不用。hello_init和hello_exit中只用到了一个printk函数，类似printf，不过在输出时，需要先输出消息的级别，比如KERN_ALERT。<br />
到此，一个非常简单的hello world就完成了。下面编译。</p>
<p><a name="c4">4．Makefile文件</a><br />
	在编译之前讲Makefile是必须的，因为如果没有makefile的话每次编译将会非常痛苦。至于Makefile，不讲太多，给一个简单的linux2.6下的模板吧.</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:Courier new,verdana;">ifneq <span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span>KERNELRELEASE<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #009900;">&#41;</span>
	obj<span style="color: #339933;">-</span>m <span style="color: #339933;">:=</span> helloworld.<span style="color: #202020;">o</span>
&nbsp;
<span style="color: #b1b100;">else</span>
	KERNELDIR <span style="color: #339933;">:=/</span>lib<span style="color: #339933;">/</span>modules<span style="color: #339933;">/</span>$<span style="color: #009900;">&#40;</span>shell uname <span style="color: #339933;">-</span>r<span style="color: #009900;">&#41;</span><span style="color: #339933;">/</span>build
	PWD <span style="color: #339933;">:=</span> $<span style="color: #009900;">&#40;</span>shell pwd<span style="color: #009900;">&#41;</span>
&nbsp;
<span style="color: #b1b100;">default</span><span style="color: #339933;">:</span>
	$<span style="color: #009900;">&#40;</span>MAKE<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span>C $<span style="color: #009900;">&#40;</span>KERNELDIR<span style="color: #009900;">&#41;</span> M<span style="color: #339933;">=</span>$<span style="color: #009900;">&#40;</span>PWD<span style="color: #009900;">&#41;</span> modules
&nbsp;
install<span style="color: #339933;">:</span>
	$<span style="color: #009900;">&#40;</span>shell sudo insmod .<span style="color: #339933;">/</span>helloworld.<span style="color: #202020;">ko</span><span style="color: #009900;">&#41;</span>
endif</pre></div></div>

<p>	内核模块的makefile和一般C/c++程序的makefile有点不一样，因为使用了kbuild。想了解makefile和kbuild的可以看linux的Documention。</p>
<p><a name="c5">5．编译，加载内核模块</a><br />
	将makefile写好后,就可以在终端下切换到当前目录，然后make就好了。当前前提是你有的include的文件和kernel sources tree.在/usr/src/linux-2.6*下有源代码。在/usr/include/linux下有init.h和module.h。<br />
	make成功后，目录下应该生成了一个helloworld.ko，这是2.6的内核模块的后缀。之后是加载到运行的内核中。sudo make install桌这手动输入sudo insmod ./helloworld.ko也可以。还有一种加载内核模块的命令是modprobe，这个比insmod更强大，可以自动搜索依赖。<br />
	加载成功后，我们可以用lsmod来查看当前内核中的模块，或者cat /proc/modules，都可以。而如果想看到helloworld模块加载时输出的信息，在ubuntu 下可以去/var/log/kern.log文件中查看，或者使用dmesg命令。dmesg | tail -10. 如果想卸载模块，可以用rmmod命令。sudo rmmod helloworld。</p>
<p><a name="c6">6.other tips</a><br />
	Ubuntu linux的内核模块是放在/lib/modules/2.6*/kernel下的。<br />
	查看某条命令的用法可以用man command.<br />
	如果想查看某个模块的信息，可以用modinfo modname。</p>
<p><a name="c7">7．好的书籍和网站</a><br />
	想系统的学习的话，还是需要看书的，遇到问题了，可以到论坛上求助，当然现google一下还是很有必要的。<br />
	好的书籍：<br />
		《linux内核设计与实现》比较基础，个人感觉适合初学者<br />
		《linux设备驱动》如果需要作某个驱动的话，可以参考。<br />
		《linux内核*》找本介绍linux源代码的书看下，对自己理解设备驱动模型等非常有帮助。<br />
	好的论坛：<br />
		<a href="http://www.linuxforum.net">http://www.linuxforum.net</a><br />
		<a href="http://kerneltrap.org/">http://kerneltrap.org/</a><br />
	好的工具也很必要，工欲善其事，必先利其器嘛。<br />
		如果在win下的话，用source insight,很强大。linux下的话有source navigator。不过熟悉vim的可以用vim+ctags(我也在学),或者专门作源代码分析的<a href="http://lxr.linux.no/linux">lxr</a>， 。这个lxr是可以架设在本机上的，在ubuntu中文论坛上可以搜到。		</p>
<p>	书或者网站或者工具，没必要急着全部熟悉，照准一个，先看完，用好，等自己了解了一些后，再去看更需要的书吧。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.boluor.com/note-of-linux-device-driver.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

