linux 驱动编写之虚拟字符设备的编写实例详解
<p><strong> linux 驱动编写</strong></p>
<p>
<strong>前言:</strong></p>
<p>
昨天我们说了一些简单模块编写方法,但是终归没有涉及到设备的编写内容,今天我们就可以了解一下相关方面的内容,并且用一个实例来说明在Linux上面设备是如何编写的。虽然我不是专门做linux驱动的,却也经常收到一些朋友们的来信。在信件中,很多做驱动的朋友对自己的工作不是很满意,认为自己的工作就是把代码拷贝来拷贝去,或者说是改来改去,没有什么技术含量。有这种想法的朋友不在少数,我想这主要还是因为他们对自己的工作缺少了解导致。如果有可能,我们可以问问自己这样几个问题:</p>
<p>
(1)我真的搞懂设备的开发驱动流程了吗?我是否可以从0开始,编写一个独立的驱动代码呢?<br>
(2)我真的了解设备的初始化、关闭、运行的流程吗?<br>
(3)当前的设备驱动流程是否合理,有没有可以改进的地方?<br>
(4)对于内核开发中涉及的api调用,我自己是否真正了解、是否明白它们在使用上有什么区别?<br>
(5)如果我要驱动的设备只是在一个前后台系统中运行,在没有框架帮助的情况下,我是否有信心把它启动和运行起来?</p>
<p>
当然,上面的内容只是我个人的想法,也不一定都正确。但是,知其然,更要知其所以然,熟悉了当前开发流程的优缺点才能真正掌握和了解驱动开发的本质。这听上去有些玄乎,其实也很简单,就是要有一种刨根问底、不断改进的精神,这样才能做好自己的工作。因为我们是在pc linux上学习驱动的,因此暂时没有真实的外接设备可以使用,但是这丝毫不影响我们学习的热情。通过定时器、进程,我们可以仿真出真实设备的各种需求,所以对于系统来说,它是无所谓真设备、假设备的,基本的处理流程对它来说都是一样的。只要大家一步一步做下去,肯定可以了解linux驱动设备的开发工程的。</p>
<p>
下面,为了说明问题,我们可以编写一段简单的char设备驱动代码,文件名为char.c,</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightercpp" id="highlighter_823744">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
<div class="line number5 index4 alt2">
5</div>
<div class="line number6 index5 alt1">
6</div>
<div class="line number7 index6 alt2">
7</div>
<div class="line number8 index7 alt1">
8</div>
<div class="line number9 index8 alt2">
9</div>
<div class="line number10 index9 alt1">
10</div>
<div class="line number11 index10 alt2">
11</div>
<div class="line number12 index11 alt1">
12</div>
<div class="line number13 index12 alt2">
13</div>
<div class="line number14 index13 alt1">
14</div>
<div class="line number15 index14 alt2">
15</div>
<div class="line number16 index15 alt1">
16</div>
<div class="line number17 index16 alt2">
17</div>
<div class="line number18 index17 alt1">
18</div>
<div class="line number19 index18 alt2">
19</div>
<div class="line number20 index19 alt1">
20</div>
<div class="line number21 index20 alt2">
21</div>
<div class="line number22 index21 alt1">
22</div>
<div class="line number23 index22 alt2">
23</div>
<div class="line number24 index23 alt1">
24</div>
<div class="line number25 index24 alt2">
25</div>
<div class="line number26 index25 alt1">
26</div>
<div class="line number27 index26 alt2">
27</div>
<div class="line number28 index27 alt1">
28</div>
<div class="line number29 index28 alt2">
29</div>
<div class="line number30 index29 alt1">
30</div>
<div class="line number31 index30 alt2">
31</div>
<div class="line number32 index31 alt1">
32</div>
<div class="line number33 index32 alt2">
33</div>
<div class="line number34 index33 alt1">
34</div>
<div class="line number35 index34 alt2">
35</div>
<div class="line number36 index35 alt1">
36</div>
<div class="line number37 index36 alt2">
37</div>
<div class="line number38 index37 alt1">
38</div>
<div class="line number39 index38 alt2">
39</div>
<div class="line number40 index39 alt1">
40</div>
<div class="line number41 index40 alt2">
41</div>
<div class="line number42 index41 alt1">
42</div>
<div class="line number43 index42 alt2">
43</div>
<div class="line number44 index43 alt1">
44</div>
<div class="line number45 index44 alt2">
45</div>
<div class="line number46 index45 alt1">
46</div>
<div class="line number47 index46 alt2">
47</div>
<div class="line number48 index47 alt1">
48</div>
<div class="line number49 index48 alt2">
49</div>
<div class="line number50 index49 alt1">
50</div>
<div class="line number51 index50 alt2">
51</div>
<div class="line number52 index51 alt1">
52</div>
<div class="line number53 index52 alt2">
53</div>
<div class="line number54 index53 alt1">
54</div>
<div class="line number55 index54 alt2">
55</div>
<div class="line number56 index55 alt1">
56</div>
<div class="line number57 index56 alt2">
57</div>
<div class="line number58 index57 alt1">
58</div>
<div class="line number59 index58 alt2">
59</div>
<div class="line number60 index59 alt1">
60</div>
<div class="line number61 index60 alt2">
61</div>
<div class="line number62 index61 alt1">
62</div>
<div class="line number63 index62 alt2">
63</div>
<div class="line number64 index63 alt1">
64</div>
<div class="line number65 index64 alt2">
65</div>
<div class="line number66 index65 alt1">
66</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="cpp preprocessor">#include <linux/module.h> </code>
</div>
<div class="line number2 index1 alt1">
<code class="cpp preprocessor">#include <linux/kernel.h> </code>
</div>
<div class="line number3 index2 alt2">
<code class="cpp preprocessor">#include <linux/fs.h> </code>
</div>
<div class="line number4 index3 alt1">
<code class="cpp preprocessor">#include <linux/cdev.h> </code>
</div>
<div class="line number5 index4 alt2">
<code class="cpp spaces"> </code>
</div>
<div class="line number6 index5 alt1">
<code class="cpp keyword bold">static</code> <code class="cpp keyword bold">struct</code> <code class="cpp plain">cdev chr_dev; </code>
</div>
<div class="line number7 index6 alt2">
<code class="cpp keyword bold">static</code> <code class="cpp plain">dev_t ndev; </code>
</div>
<div class="line number8 index7 alt1">
<code class="cpp spaces"> </code>
</div>
<div class="line number9 index8 alt2">
<code class="cpp keyword bold">static</code> <code class="cpp color1 bold">int</code> <code class="cpp plain">chr_open(</code><code class="cpp keyword bold">struct</code> <code class="cpp plain">inode* nd, </code><code class="cpp keyword bold">struct</code> <code class="cpp plain">file* filp) </code>
</div>
<div class="line number10 index9 alt1">
<code class="cpp plain">{ </code>
</div>
<div class="line number11 index10 alt2">
<code class="cpp spaces"> </code><code class="cpp color1 bold">int</code> <code class="cpp plain">major ; </code>
</div>
<div class="line number12 index11 alt1">
<code class="cpp spaces"> </code><code class="cpp color1 bold">int</code> <code class="cpp plain">minor; </code>
</div>
<div class="line number13 index12 alt2">
<code class="cpp spaces"> </code>
</div>
<div class="line number14 index13 alt1">
<code class="cpp spaces"> </code><code class="cpp plain">major = MAJOR(nd->i_rdev); </code>
</div>
<div class="line number15 index14 alt2">
<code class="cpp spaces"> </code><code class="cpp plain">minor = MINOR(nd->i_rdev); </code>
</div>
<div class="line number16 index15 alt1">
<code class="cpp spaces"> </code>
</div>
<div class="line number17 index16 alt2">
<code class="cpp spaces"> </code><code class="cpp plain">printk(</code><code class="cpp string">"chr_open, major = %d, minor = %d\n"</code><code class="cpp plain">, major, minor); </code>
</div>
<div class="line number18 index17 alt1">
<code class="cpp spaces"> </code><code class="cpp keyword bold">return</code> <code class="cpp plain">0; </code>
</div>
<div class="line number19 index18 alt2">
<code class="cpp plain">} </code>
</div>
<div class="line number20 index19 alt1">
<code class="cpp spaces"> </code>
</div>
<div class="line number21 index20 alt2">
<code class="cpp keyword bold">static</code> <code class="cpp plain">ssize_t chr_read(</code><code class="cpp keyword bold">struct</code> <code class="cpp plain">file* filp, </code><code class="cpp color1 bold">char</code> <code class="cpp plain">__user* u, </code><code class="cpp color1 bold">size_t</code> <code class="cpp plain">sz, loff_t* off) </code>
</div>
<div class="line number22 index21 alt1">
<code class="cpp plain">{ </code>
</div>
<div class="line number23 index22 alt2">
<code class="cpp spaces"> </code><code class="cpp plain">printk(</code><code class="cpp string">"chr_read process!\n"</code><code class="cpp plain">); </code>
</div>
<div class="line number24 index23 alt1">
<code class="cpp spaces"> </code><code class="cpp keyword bold">return</code> <code class="cpp plain">0; </code>
</div>
<div class="line number25 index24 alt2">
<code class="cpp plain">} </code>
</div>
<div class="line number26 index25 alt1">
<code class="cpp spaces"> </code>
</div>
<div class="line number27 index26 alt2">
<code class="cpp keyword bold">struct</code> <code class="cpp plain">file_operations chr_ops = { </code>
</div>
<div class="line number28 index27 alt1">
<code class="cpp spaces"> </code><code class="cpp plain">.owner = THIS_MODULE, </code>
</div>
<div class="line number29 index28 alt2">
<code class="cpp spaces"> </code><code class="cpp plain">.open = chr_open, </code>
</div>
<div class="line number30 index29 alt1">
<code class="cpp spaces"> </code><code class="cpp plain">.read = chr_read </code>
</div>
<div class="line number31 index30 alt2">
<code class="cpp plain">}; </code>
</div>
<div class="line number32 index31 alt1">
<code class="cpp spaces"> </code>
</div>
<div class="line number33 index32 alt2">
<code class="cpp keyword bold">static</code> <code class="cpp color1 bold">int</code> <code class="cpp plain">demo_init(</code><code class="cpp keyword bold">void</code><code class="cpp plain">) </code>
</div>
<div class="line number34 index33 alt1">
<code class="cpp plain">{ </code>
</div>
<div class="line number35 index34 alt2">
<code class="cpp spaces"> </code><code class="cpp color1 bold">int</code> <code class="cpp plain">ret; </code>
</div>
<div class="line number36 index35 alt1">
<code class="cpp spaces"> </code>
</div>
<div class="line number37 index36 alt2">
<code class="cpp spaces"> </code><code class="cpp plain">cdev_init(&chr_dev, &chr_ops); </code>
</div>
<div class="line number38 index37 alt1">
<code class="cpp spaces"> </code><code class="cpp plain">ret = alloc_chrdev_region(&ndev, 0, 1, </code><code class="cpp string">"chr_dev"</code><code class="cpp plain">); </code>
</div>
<div class="line number39 index38 alt2">
<code class="cpp spaces"> </code><code class="cpp keyword bold">if</code><code class="cpp plain">(ret < 0 ) </code>
</div>
<div class="line number40 index39 alt1">
<code class="cpp spaces"> </code><code class="cpp plain">{ </code>
</div>
<div class="line number41 index40 alt2">
<code class="cpp spaces"> </code><code class="cpp keyword bold">return</code> <code class="cpp plain">ret; </code>
</div>
<div class="line number42 index41 alt1">
<code class="cpp spaces"> </code><code class="cpp plain">} </code>
</div>
<div class="line number43 index42 alt2">
<code class="cpp spaces"> </code>
</div>
<div class="line number44 index43 alt1">
<code class="cpp spaces"> </code><code class="cpp plain">printk(</code><code class="cpp string">"demo_init(): major = %d, minor = %d\n"</code><code class="cpp plain">, MAJOR(ndev), MINOR(ndev)); </code>
</div>
<div class="line number45 index44 alt2">
<code class="cpp spaces"> </code><code class="cpp plain">ret = cdev_add(&chr_dev, ndev, 1); </code>
</div>
<div class="line number46 index45 alt1">
<code class="cpp spaces"> </code><code class="cpp keyword bold">if</code><code class="cpp plain">(ret < 0) </code>
</div>
<div class="line number47 index46 alt2">
<code class="cpp spaces"> </code><code class="cpp plain">{ </code>
</div>
<div class="line number48 index47 alt1">
<code class="cpp spaces"> </code><code class="cpp keyword bold">return</code> <code class="cpp plain">ret; </code>
</div>
<div class="line number49 index48 alt2">
<code class="cpp spaces"> </code><code class="cpp plain">} </code>
</div>
<div class="line number50 index49 alt1">
<code class="cpp spaces"> </code>
</div>
<div class="line number51 index50 alt2">
<code class="cpp spaces"> </code><code class="cpp keyword bold">return</code> <code class="cpp plain">0; </code>
</div>
<div class="line number52 index51 alt1">
<code class="cpp plain">} </code>
</div>
<div class="line number53 index52 alt2">
<code class="cpp spaces"> </code>
</div>
<div class="line number54 index53 alt1">
<code class="cpp keyword bold">static</code> <code class="cpp keyword bold">void</code> <code class="cpp plain">demo_exit(</code><code class="cpp keyword bold">void</code><code class="cpp plain">) </code>
</div>
<div class="line number55 index54 alt2">
<code class="cpp plain">{ </code>
</div>
<div class="line number56 index55 alt1">
<code class="cpp spaces"> </code><code class="cpp plain">printk(</code><code class="cpp string">"demo_exit process!\n"</code><code class="cpp plain">); </code>
</div>
<div class="line number57 index56 alt2">
<code class="cpp spaces"> </code><code class="cpp plain">cdev_del(&chr_dev); </code>
</div>
<div class="line number58 index57 alt1">
<code class="cpp spaces"> </code><code class="cpp plain">unregister_chrdev_region(ndev, 1); </code>
</div>
<div class="line number59 index58 alt2">
<code class="cpp plain">} </code>
</div>
<div class="line number60 index59 alt1">
<code class="cpp spaces"> </code>
</div>
<div class="line number61 index60 alt2">
<code class="cpp plain">module_init(demo_init); </code>
</div>
<div class="line number62 index61 alt1">
<code class="cpp plain">module_exit(demo_exit); </code>
</div>
<div class="line number63 index62 alt2">
<code class="cpp spaces"> </code>
</div>
<div class="line number64 index63 alt1">
<code class="cpp plain">MODULE_LICENSE(</code><code class="cpp string">"GPL"</code><code class="cpp plain">); </code>
</div>
<div class="line number65 index64 alt2">
<code class="cpp plain">MODULE_AUTHOR(</code><code class="cpp string">"feixiaoxing@163.com"</code><code class="cpp plain">); </code>
</div>
<div class="line number66 index65 alt1">
<code class="cpp plain">MODULE_DESCRIPTION(</code><code class="cpp string">"A simple device example!"</code><code class="cpp plain">); </code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
在module_init中的函数是模块加载时处理的函数,而模块卸载的函数则是在module_exit中。每一个设备都要对应一个基本的设备数据,当然为了使得这个设备注册在整个系统当中,我们还需要分配一个设备节点,alloc_chrdev_region就完成这样一个功能。等到cdev_add的时候,整个设备注册的过程就全部完成了,就是这么简单。当然为了编写这个文件,我们还需要编写一个Makefile文件,</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightercpp" id="highlighter_533652">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
<div class="line number5 index4 alt2">
5</div>
<div class="line number6 index5 alt1">
6</div>
<div class="line number7 index6 alt2">
7</div>
<div class="line number8 index7 alt1">
8</div>
<div class="line number9 index8 alt2">
9</div>
<div class="line number10 index9 alt1">
10</div>
<div class="line number11 index10 alt2">
11</div>
<div class="line number12 index11 alt1">
12</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="cpp plain">ifneq ($(KERNELRELEASE),) </code>
</div>
<div class="line number2 index1 alt1">
<code class="cpp plain">obj-m := </code><code class="cpp color1 bold">char</code><code class="cpp plain">.o </code>
</div>
<div class="line number3 index2 alt2">
<code class="cpp spaces"> </code>
</div>
<div class="line number4 index3 alt1">
<code class="cpp keyword bold">else</code>
</div>
<div class="line number5 index4 alt2">
<code class="cpp plain">PWD := $(shell pwd) </code>
</div>
<div class="line number6 index5 alt1">
<code class="cpp plain">KVER := $(shell uname -r) </code>
</div>
<div class="line number7 index6 alt2">
<code class="cpp plain">KDIR := /lib/modules/$(KVER)/build </code>
</div>
<div class="line number8 index7 alt1">
<code class="cpp plain">all: </code>
</div>
<div class="line number9 index8 alt2">
<code class="cpp spaces"> </code><code class="cpp plain">$(MAKE) -C $(KDIR) M=$(PWD) modules </code>
</div>
<div class="line number10 index9 alt1">
<code class="cpp plain">clean: </code>
</div>
<div class="line number11 index10 alt2">
<code class="cpp spaces"> </code><code class="cpp plain">rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions modules.* Module.* </code>
</div>
<div class="line number12 index11 alt1">
<code class="cpp plain">endif </code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
这个Makefile文件和我们之前编写的makefile基本上没有区别,唯一的区别就是文件名称改成了char.o,仅此而已。为了编写模块,我们直接输入make即可。这时候,char.ko文件就可以生成了。然后,模块需要被注册在系统当中,insmod char.ko是少不了的。如果此时,我们还不确信是否模块已经加入到系统当中,完全可以通过输入lsmod | grep char进行查找和验证。为了创建设备节点,我们需要知道设备为我们创建的major、minor数值是多少,所以dmesg | tail 查找一下数值。在我hp的机器上,这两个数值分别是249和0,所以下面可以利用它们直接创建设备节点了,输入mknod /dev/chr_dev c 249 0即可,此时可以输入ls /dev/chr_dev验证一下。那么,按照这种方法,真的可以访问这个虚拟设备了吗,我们可以编写一段简单的代码验证一下,</p>
<div class="jb51code">
<div>
<div class="syntaxhighlightercpp" id="highlighter_249019">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
<div class="line number5 index4 alt2">
5</div>
<div class="line number6 index5 alt1">
6</div>
<div class="line number7 index6 alt2">
7</div>
<div class="line number8 index7 alt1">
8</div>
<div class="line number9 index8 alt2">
9</div>
<div class="line number10 index9 alt1">
10</div>
<div class="line number11 index10 alt2">
11</div>
<div class="line number12 index11 alt1">
12</div>
<div class="line number13 index12 alt2">
13</div>
<div class="line number14 index13 alt1">
14</div>
<div class="line number15 index14 alt2">
15</div>
<div class="line number16 index15 alt1">
16</div>
<div class="line number17 index16 alt2">
17</div>
<div class="line number18 index17 alt1">
18</div>
<div class="line number19 index18 alt2">
19</div>
<div class="line number20 index19 alt1">
20</div>
<div class="line number21 index20 alt2">
21</div>
<div class="line number22 index21 alt1">
22</div>
<div class="line number23 index22 alt2">
23</div>
<div class="line number24 index23 alt1">
24</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="cpp preprocessor">#include <stdio.h> </code>
</div>
<div class="line number2 index1 alt1">
<code class="cpp preprocessor">#include <fcntl.h> </code>
</div>
<div class="line number3 index2 alt2">
<code class="cpp preprocessor">#include <unistd.h> </code>
</div>
<div class="line number4 index3 alt1">
<code class="cpp spaces"> </code>
</div>
<div class="line number5 index4 alt2">
<code class="cpp preprocessor">#define CHAR_DEV_NAME "/dev/chr_dev" </code>
</div>
<div class="line number6 index5 alt1">
<code class="cpp spaces"> </code>
</div>
<div class="line number7 index6 alt2">
<code class="cpp color1 bold">int</code> <code class="cpp plain">main() </code>
</div>
<div class="line number8 index7 alt1">
<code class="cpp plain">{ </code>
</div>
<div class="line number9 index8 alt2">
<code class="cpp spaces"> </code><code class="cpp color1 bold">int</code> <code class="cpp plain">ret; </code>
</div>
<div class="line number10 index9 alt1">
<code class="cpp spaces"> </code><code class="cpp color1 bold">int</code> <code class="cpp plain">fd; </code>
</div>
<div class="line number11 index10 alt2">
<code class="cpp spaces"> </code><code class="cpp color1 bold">char</code> <code class="cpp plain">buf; </code>
</div>
<div class="line number12 index11 alt1">
<code class="cpp spaces"> </code>
</div>
<div class="line number13 index12 alt2">
<code class="cpp spaces"> </code><code class="cpp plain">fd = open(CHAR_DEV_NAME, O_RDONLY | O_NDELAY); </code>
</div>
<div class="line number14 index13 alt1">
<code class="cpp spaces"> </code><code class="cpp keyword bold">if</code><code class="cpp plain">(fd < 0) </code>
</div>
<div class="line number15 index14 alt2">
<code class="cpp spaces"> </code><code class="cpp plain">{ </code>
</div>
<div class="line number16 index15 alt1">
<code class="cpp spaces"> </code><code class="cpp functions bold">printf</code><code class="cpp plain">(</code><code class="cpp string">"open failed!\n"</code><code class="cpp plain">); </code>
</div>
<div class="line number17 index16 alt2">
<code class="cpp spaces"> </code><code class="cpp keyword bold">return</code> <code class="cpp plain">-1; </code>
</div>
<div class="line number18 index17 alt1">
<code class="cpp spaces"> </code><code class="cpp plain">} </code>
</div>
<div class="line number19 index18 alt2">
<code class="cpp spaces"> </code>
</div>
<div class="line number20 index19 alt1">
<code class="cpp spaces"> </code><code class="cpp plain">read(fd, buf, 32); </code>
</div>
<div class="line number21 index20 alt2">
<code class="cpp spaces"> </code><code class="cpp plain">close(fd); </code>
</div>
<div class="line number22 index21 alt1">
<code class="cpp spaces"> </code>
</div>
<div class="line number23 index22 alt2">
<code class="cpp spaces"> </code><code class="cpp keyword bold">return</code> <code class="cpp plain">0; </code>
</div>
<div class="line number24 index23 alt1">
<code class="cpp plain">} </code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<div class="codetool" id="codetool">
<div class="code_n">
<textarea></textarea>
</div>
</div>
</div>
<p>
代码的内容非常简单,就是利用CHAR_DEV_NAME直接打开设备,读写设备。当然。首先还是需要对这个文件进行编译,文件名为test.c,输入gcc test.c -o test,其次就是运行这个文件,直接输入./test即可。如果没有问题的话,那么说明我们的代码是ok的,但是我们还是没有看到任何内容。没关系,我们还是通过dmesg这个命令查看内核中是否存在相关的打印内容,直接输入dmesg | tail即可。此时如果没有意外的话,我们就可以看到之前在chr_open和chr_read中留下的printk打印,这说明我们的代码完全是ok的。</p>
<p>
上面的代码只是一段小例子,真实的内容要比这复杂一下。不过既然我们都已经入门了,那么后面的内容其实也没有什么好怕的了。最后有两个事情补充一下:(1)如果大家在创建节点后想删除设备节点,直接rm -rf /dev/chr_dev即可;(2)上面这段代码的原型来自于《深入linux设备驱动程序内核机制》这本书,稍作修改,如果大家对内核机制的内容感兴趣,可以参考这本书的内容。</p>
<p>
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!</p>
頁:
[1]