Linux内核与驱动学习记录-字符设备驱动程序框架
 2021.07.31    |      Linux MMC子系统    |     AilsonJack    |     暂无评论    |     338 views
By: Ailson Jack
Date: 2021-07-31
个人博客: http://www.only2fire.com/
<p style="text-indent: 2em;">字符设备的驱动程序开发步骤大致都是差不多的,这里绘制了一张图来形象的反应字符设备驱动程序的关键步骤:</p><p style="text-align:center"><img src="/uploads/AilsonJack/2021.07.31/205809879737230.png" onclick="preview_image(&#39;/uploads/AilsonJack/2021.07.31/205809879737230.png&#39;)"/></p><p style="text-indent: 2em;"><span class="md-plain md-expand" style="box-sizing: border-box; color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 4; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">我们创建一个字符设备的时候,首先要得到一个设备号,分配设备号的途径有静态分配和动态分配;拿到设备的唯一 ID,我们需要实现 file_operation 并保存到 cdev 中,实现 cdev 的初始化;然后我们需要将我们所做的工作告诉内核,使用 cdev_add() 注册 cdev;最后我们还需要创建设备节点,以便我们后面调用 file_operation接口。</span><span class="md-softbreak" style="box-sizing: border-box; color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 4; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"></span><span class="md-plain md-expand" style="box-sizing: border-box; color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 4; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">注销设备时我们需释放内核中的 cdev,归还申请的设备号,删除创建的设备节点。</span></p><p class="artical_littlestyle1">1.字符设备的定义</p><p style="text-indent: 2em;">Linux 内核提供了两种方式来定义字符设备:</p><pre class="brush:cpp;toolbar:false PrismJs">//第一种方式 static&nbsp;struct&nbsp;cdev&nbsp;chrdev; //第二种方式 struct&nbsp;cdev&nbsp;*cdev_alloc(void); struct&nbsp;cdev&nbsp;*p_cdev&nbsp;=&nbsp;cdev_alloc();</pre><p style="text-indent: 2em;">第一种方式,就是我们常见的变量定义;第二种方式,是内核提供的动态分配方式,调用该函数之后,会返回一个 struct cdev 类型的指针,用于描述字符设备。<br/></p><p style="text-indent: 2em;">第二种方式定义的字符设备,可以通过cdev_del函数来释放占用的内存。</p><p class="artical_littlestyle2">2.设备号的申请和归还</p><p style="text-indent: 2em;"><strong><span style="color: rgb(0, 112, 192);">2.1.设备号的静态申请</span></strong><br/></p><p style="text-indent: 2em;">register_chrdev_region 函数用于静态地为一个字符设备申请一个或多个设备编号。</p><pre class="brush:cpp;toolbar:false PrismJs">int&nbsp;register_chrdev_region(dev_t&nbsp;from,&nbsp;unsigned&nbsp;count,&nbsp;const&nbsp;char&nbsp;*name);</pre><p style="text-indent: 2em;">参数:</p><p style="text-indent: 2em;">from:dev_t 类型的变量,用于指定字符设备的起始设备号,如果要注册的设备号已经被其他的设备注册了,那么就会导致注册失败;</p><p style="text-indent: 2em;">count:指定要申请的设备号个数, count 的值不可以太大,否则会与下一个主设备号重叠;</p><p style="text-indent: 2em;">name:用于指定该设备的名称,我们可以在/proc/devices 中看到该设备。</p><p style="text-indent: 2em;"><span style="color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 4; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">返回值:返回 0 表示申请成功,失败则返回错误码。</span></p><p style="text-indent: 2em;"><span style="color: rgb(0, 112, 192);"><strong>2.2.设备号的动态申请</strong></span></p><p style="text-indent: 2em;">使用 register_chrdev_region 函数时,都需要去查阅内核源码的 Documentation/devices.txt 文件,这就十分不方便。因此,内核又为我们提供了一种能够动态分配设备编号的方式: alloc_chrdev_region。<br/></p><p style="text-indent: 2em;">调用 alloc_chrdev_region 函数,内核会自动给我们分配一个尚未使用的主设备号。我们可以通过命令“cat /proc/devices”查询内核分配的主设备号。<br/></p><pre class="brush:cpp;toolbar:false PrismJs">int&nbsp;alloc_chrdev_region(dev_t&nbsp;*dev,&nbsp;unsigned&nbsp;baseminor,&nbsp;unsigned&nbsp;count,&nbsp;const&nbsp;char&nbsp;*name);</pre><p style="text-indent: 2em;"><span style="color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 4; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">参数:</span></p><p style="text-indent: 2em;">dev:指向 dev_t 类型数据的指针变量,用于存放分配到的设备编号的起始值;<br/></p><p style="text-indent: 2em;">baseminor:次设备号的起始值,通常情况下,设置为 0;<br/></p><p style="text-indent: 2em;">count:指定要申请的设备号个数, count 的值不可以太大,否则会与下一个主设备号重叠;<br/></p><p style="text-indent: 2em;">name:用于指定该设备的名称,我们可以在/proc/devices 中看到该设备。<br/></p><p style="text-indent: 2em;">返回值:返回 0 表示申请成功,失败则返回错误码。<br/></p><p style="text-indent: 2em;"><span style="color: rgb(0, 112, 192);"><strong>2.3.设备号的申请(静态和动态都支持)</strong></span></p><p style="text-indent: 2em;"><span style="color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 4; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">除了register_chrdev_region函数能够静态申请设备号,alloc_chrdev_region函数能够动态申请设备号之外,内核还提供了register_chrdev 函数用于分配设备号。该函数是一个内联函数,它不仅支持静态申请设备号,也支持动态申请设备号,并将主设备号返回。register_chrdev 函数原型如下:</span></p><pre class="brush:cpp;toolbar:false PrismJs">static&nbsp;inline&nbsp;int&nbsp;register_chrdev(unsigned&nbsp;int&nbsp;major,&nbsp;const&nbsp;char&nbsp;*name, &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;const&nbsp;struct&nbsp;file_operations&nbsp;*fops) { &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;__register_chrdev(major,&nbsp;0,&nbsp;256,&nbsp;name,&nbsp;fops); }</pre><p style="text-indent: 2em;">参数:<br/></p><p style="text-indent: 2em;">major:用于指定要申请的字符设备的主设备号,等价于 register_chrdev_region 函数,当设置为 0 时,内核会自动分配一个未使用的主设备号;<br/></p><p style="text-indent: 2em;">name:用于指定字符设备的名称;<br/></p><p style="text-indent: 2em;">fops:用于操作该设备的函数接口指针。<br/></p><p style="text-indent: 2em;">返回值:主设备号。<br/></p><p style="text-indent: 2em;">我们从以上代码中可以看到,使用 register_chrdev 函数向内核申请设备号,同一类字符设备(即主设备号相同),会在内核中申请了256 个,通常情况下,我们不需要用到这么多个设备,这就造成了极大的资源浪费。因此通常情况下,并不使用该函数。</p><p style="text-indent: 2em;"><span style="color: rgb(0, 112, 192);"><strong>2.4.设备号的归还</strong></span></p><p style="text-indent: 2em;"><span style="color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 4; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">当我们删除字符设备时候,我们需要把分配的设备编号交还给内核,对于使用 register_chrdev_region 函数以及 alloc_chrdev_region 函数分配得到的设备编号,可以使用 unregister_chrdev_region 函数将分配得到的设备号归还给内核。</span></p><pre class="brush:cpp;toolbar:false PrismJs">void&nbsp;unregister_chrdev_region(dev_t&nbsp;from,&nbsp;unsigned&nbsp;count);</pre><p style="text-indent: 2em;">参数:<br/></p><p style="text-indent: 2em;">from:指定需要注销的字符设备的设备编号起始值,我们一般将定义的 dev_t 变量作为实参;<br/></p><p style="text-indent: 2em;">count:指定需要注销的字符设备编号的个数,该值应与申请函数的 count 值相等,通常采用宏定义进行管理。</p><p class="artical_littlestyle3">3.字符设备的初始化</p><p style="text-indent: 2em;"><span style="color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 4; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">cdev_init()函数主要将file_operations结构体和我们的字符设备结构体相关联。</span></p><pre class="brush:cpp;toolbar:false PrismJs">void&nbsp;cdev_init(struct&nbsp;cdev&nbsp;*cdev,&nbsp;const&nbsp;struct&nbsp;file_operations&nbsp;*fops);</pre><p style="text-indent: 2em;">参数:<br/></p><p style="text-indent: 2em;">cdev:struct cdev 类型的指针变量,指向需要关联的字符设备结构体;<br/></p><p style="text-indent: 2em;">fops:file_operations 类型的结构体指针变量,一般将实现操作该设备的结构体 file_operations 结构体作为实参。</p><p class="artical_littlestyle4">4.字符设备的注册和移除</p><p style="box-sizing: border-box; line-height: inherit; margin: 0.8em 0px; white-space: pre-wrap; position: relative; color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-indent: 2em;"><span style="color: rgb(0, 112, 192);"><strong>4.1.字符设备的注册</strong></span><span class="md-plain md-expand" style="box-sizing: border-box"><br/></span></p><p style="box-sizing: border-box; line-height: inherit; margin: 0.8em 0px; white-space: pre-wrap; position: relative; color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-indent: 2em;"><span class="md-plain md-expand" style="box-sizing: border-box">cdev_add 函数用于向内核的 cdev_map 散列表添加一个新的字符设备。</span></p><pre class="brush:cpp;toolbar:false PrismJs">int&nbsp;cdev_add(struct&nbsp;cdev&nbsp;*p,&nbsp;dev_t&nbsp;dev,&nbsp;unsigned&nbsp;count);</pre><p style="box-sizing: border-box; line-height: inherit; margin: 0.8em 0px; white-space: pre-wrap; position: relative; color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-indent: 2em;">参数:</p><p style="box-sizing: border-box; line-height: inherit; margin: 0.8em 0px; white-space: pre-wrap; position: relative; color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-indent: 2em;">p:struct cdev 类型的指针,用于指定需要添加的字符设备;</p><p style="box-sizing: border-box; line-height: inherit; margin: 0.8em 0px; white-space: pre-wrap; position: relative; color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-indent: 2em;">dev:dev_t 类型变量,用于指定设备的起始编号;</p><p style="box-sizing: border-box; line-height: inherit; margin: 0.8em 0px; white-space: pre-wrap; position: relative; color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-indent: 2em;">count:指定注册多少个设备。</p><p style="box-sizing: border-box; line-height: inherit; margin: 0.8em 0px; white-space: pre-wrap; position: relative; color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-indent: 2em;">返回值:0或者错误码。<span class="md-plain md-expand" style="box-sizing: border-box"></span><br/></p><p style="text-indent: 2em;"><strong><span style="color: rgb(0, 112, 192);">4.2.字符设备的移除</span></strong></p><p style="text-indent: 2em;">从内核中移除某个字符设备,则需要调用 cdev_del 函数。从系统中删除 cdev, cdev 设备将无法再打开,但任何已经打开的 cdev 将保持不变,即使在 cdev_del 返回后,它们的 fops 仍然可以调用。</p><pre class="brush:cpp;toolbar:false PrismJs">void&nbsp;cdev_del(struct&nbsp;cdev&nbsp;*p);</pre><p style="text-indent: 2em;">参数:<br/></p><p style="text-indent: 2em;">p:将已经注册的字符设备结构体的地址作为实参传递进去,就可以从内核中移除该字符设备了。</p><p class="artical_littlestyle1">5.设备节点的创建和销毁</p><p style="text-indent: 2em;"><span style="color: rgb(0, 112, 192);"><strong>5.1.设备节点的创建</strong></span></p><p style="text-indent: 2em;"><span style="color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 4; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">可以在代码中使用device_create函数创建设备节点。</span></p><pre class="brush:cpp;toolbar:false PrismJs">struct&nbsp;device&nbsp;*device_create(struct&nbsp;class&nbsp;*class,&nbsp;struct&nbsp;device&nbsp;*parent, &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;dev_t&nbsp;devt,&nbsp;void&nbsp;*drvdata,&nbsp;const&nbsp;char&nbsp;*fmt,&nbsp;...);</pre><p style="text-indent: 2em;">参数:<br/></p><p style="text-indent: 2em;">class:指向这个设备应该注册到的 struct 类的指针;<br/></p><p style="text-indent: 2em;">parent:指向此新设备的父结构设备(如果有)的指针;<br/></p><p style="text-indent: 2em;">devt:要添加的字符设备的设备号;<br/></p><p style="text-indent: 2em;">drvdata:要添加到设备进行回调的数据;<br/></p><p style="text-indent: 2em;">fmt:输入设备名称。<br/></p><p style="text-indent: 2em;">返回值:成功时返回 struct device 结构体指针, 错误时返回 ERR_PTR()。</p><p style="text-indent: 2em;"><span style="color: rgb(0, 112, 192);"><strong>5.2.设备节点的销毁</strong></span></p><p style="text-indent: 2em;"><span style="color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;, &quot;Clear Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, &quot;Segoe UI Emoji&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 4; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">可以使用device_destroy函数来删除 device_create 函数创建的设备节点。</span></p><pre class="brush:cpp;toolbar:false PrismJs">void&nbsp;device_destroy(struct&nbsp;class&nbsp;*class,&nbsp;dev_t&nbsp;devt);</pre><p style="text-indent: 2em;">参数:<br/></p><p style="text-indent: 2em;">class:指向注册此设备的 struct 类的指针;<br/></p><p style="text-indent: 2em;">devt:以前注册设备时,使用的设备号。</p><p style="text-indent: 2em;"><span style="color: rgb(0, 112, 192);"><strong>5.3.使用mknod命令创建设备节点</strong></span></p><p style="text-indent: 2em;">除了使用代码创建设备节点,还可以使用 mknod 命令创建设备节点。<br/></p><p style="text-indent: 2em;">用法: mknod 设备名 设备类型 主设备号 次设备号<br/></p><p style="text-indent: 2em;">当类型为”p”时可不指定主设备号和次设备号,否则它们是必须指定的。如果主设备号和次设备号以”0x”或”0X”开头,它们会被视作十六进制数来解析;如果以”0”开头,则被视作八进制数;其余情况下被视作十进制数。可用的设备类型包括:<br/></p><p style="text-indent: 2em;">b:创建 (有缓冲的) 区块特殊文件;<br/></p><p style="text-indent: 2em;">c,u:创建 (没有缓冲的) 字符特殊文件;<br/></p><p style="text-indent: 2em;">p:创建先进先出 (FIFO) 特殊文件。<br/></p><p style="text-indent: 2em;">如: mkmod /dev/test c 2 0<br/></p><p style="text-indent: 2em;">创建一个字符设备/dev/test,其主设备号为 2,次设备号为 0。<br/></p><p style="text-indent: 2em;">当我们使用上述命令,创建了一个字符设备文件时,实际上就是创建了一个设备节点 inode 结构体,并且将该设备的设备编号记录在成员i_rdev,将成员 f_op 指针指向了 def_chr_fops 结构体。这就是 mknod 负责的工作内容。<br/></p><p style="text-indent: 2em;">inode 上的 file_operation 并不是自己构造的 file_operation,而是字符设备通用的 def_chr_fops,那么自己构建的 file_operation 等在应用程序调用 open 函数之后,才会绑定在文件上。</p>
欢迎关注博主的公众号呀,精彩内容随时掌握:
热情邀请仔细浏览下博客中的广告,万一有对自己有用或感兴趣的呢。◕ᴗ◕。。
如果这篇文章对你有帮助,记得点赞和关注博主就行了^_^,当然了能够赞赏博主,那就非常感谢啦!
注: 转载请注明出处,谢谢!^_^
暂无评论,要不要来个沙发
发表评论

 
Copyright © 2015~2023  说好一起走   保留所有权利   |  百度统计  蜀ICP备15004292号