📄 ch03s02.html
字号:
6 lp 7 vcs 10 misc 13 input 14 sound 21 sg 180 usbBlock devices: 2 fd 8 sd 11 sr 65 sd 66 sd </pre><p>因此加载一个已经安排了一个动态编号的模块的脚本, 可以使用一个工具来编写, 如 awk , 来从 /proc/devices 获取信息以创建 /dev 中的文件.</p><p>下面的脚本, snull_load, 是 scull 发布的一部分. 以模块发布的驱动的用户可以从系统的 rc.local 文件中调用这样一个脚本, 或者在需要模块时手工调用它.</p><pre class="programlisting">#!/bin/shmodule="scull"device="scull"mode="664"# invoke insmod with all arguments we got# and use a pathname, as newer modutils don't look in . by default/sbin/insmod ./$module.ko $* || exit 1# remove stale nodesrm -f /dev/${device}[0-3]major=$(awk "\\$2==\"$module\" {print \\$1}" /proc/devices) mknod /dev/${device}0 c $major 0mknod /dev/${device}1 c $major 1mknod /dev/${device}2 c $major 2mknod /dev/${device}3 c $major 3# give appropriate group/permissions, and change the group.# Not all distributions have staff, some have "wheel" instead.group="staff"grep -q '^staff:' /etc/group || group="wheel"chgrp $group /dev/${device}[0-3]chmod $mode /dev/${device}[0-3]</pre><p>这个脚本可以通过重定义变量和调整 mknod 行来适用于另外的驱动. 这个脚本仅仅展示了创建 4 个设备, 因为 4 是 scull 源码中缺省的.</p><p>脚本的最后几行可能有些模糊:为什么改变设备的组和模式? 理由是这个脚本必须由超级用户运行, 因此新建的特殊文件由 root 拥有. 许可位缺省的是只有 root 有写权限, 而任何人可以读. 通常, 一个设备节点需要一个不同的存取策略, 因此在某些方面别人的存取权限必须改变. 我们的脚本缺省是给一个用户组存取, 但是你的需求可能不同. 在第 6 章的"设备文件的存取控制"一节中, sculluid 的代码演示了驱动如何能够强制它自己的对设备存取的授权.</p><p>还有一个 scull_unload 脚本来清理 /dev 目录并去除模块.</p><p>作为对使用一对脚本来加载和卸载的另外选择, 你可以编写一个 init 脚本, 准备好放在你的发布使用这些脚本的目录中. <sup>[<a name="id414476" href="#ftn.id414476">7</a>]</sup>作为 scull 源码的一部分, 我们提供了一个相当完整和可配置的 init 脚本例子, 称为 scull.init; 它接受传统的参数 -- start, stop, 和 restart -- 并且完成 scull_load 和 scull_unload 的角色.</p><p>如果反复创建和销毁 /dev 节点, 听来过分了, 有一个有用的办法. 如果你在加载和卸载单个驱动, 你可以在你第一次使用你的脚本创建特殊文件之后, 只使用 rmmod 和 insmod: 这样动态编号不是随机的. <sup>[<a name="id414501" href="#ftn.id414501">8</a>]</sup>并且你每次都可以使用所选的同一个编号, 如果你不加载任何别的动态模块. 在开发中避免长脚本是有用的. 但是这个技巧, 显然不能扩展到一次多于一个驱动.</p><p>安排主编号最好的方式, 我们认为, 是缺省使用动态分配, 而留给自己在加载时指定主编号的选项权, 或者甚至在编译时. scull 实现以这种方式工作; 它使用一个全局变量, scull_major, 来持有选定的编号(还有一个 scull_minor 给次编号). 这个变量初始化为 SCULL_MAJOR, 定义在 scull.h. 发布的源码中的 SCULL_MAJOR 的缺省值是 0, 意思是"使用动态分配". 用户可以接受缺省值或者选择一个特殊主编号, 或者在编译前修改宏定义或者在 insmod 命令行指定一个值给 scull_major. 最后, 通过使用 scull_load 脚本, 用户可以在 scull_load 的命令行传递参数给 insmod.<sup>[<a name="id414535" href="#ftn.id414535">9</a>]</sup></p><p>这是我们用在 scull 的源码中获取主编号的代码:</p><pre class="programlisting">if (scull_major) { dev = MKDEV(scull_major, scull_minor); result = register_chrdev_region(dev, scull_nr_devs, "scull");} else { result = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs, "scull"); scull_major = MAJOR(dev);}if (result < 0) { printk(KERN_WARNING "scull: can't get major %d\n", scull_major); return result;}</pre><p>本书使用的几乎所有例子驱动使用类似的代码来分配它们的主编号.</p></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.id414361" href="#id414361">6</a>] </sup>从 sysfs 中能获取更好的设备信息, 在基于 2.6 的系统通常加载于 /sys. 但是使 scull 通过 sysfs 输出信息超出了本章的范围; 我们在 14 章中回到这个主题.</p></div><div class="footnote"><p><sup>[<a name="ftn.id414476" href="#id414476">7</a>] </sup>Linux Standard Base 指出 init 脚本应当放在 /etc/init.d, 但是一些发布仍然放在别处. 另外, 如果你的脚本在启动时运行, 你需要从合适的运行级别目录做一个连接给它(也就是, .../rc3.d).</p></div><div class="footnote"><p><sup>[<a name="ftn.id414501" href="#id414501">8</a>] </sup>尽管某些内核开发者已警告说将来就会这样做.</p></div><div class="footnote"><p><sup>[<a name="ftn.id414535" href="#id414535">9</a>] </sup>init 脚本 scull.init 不在命令行中接受驱动选项, 但是它支持一个配置文件, 因为它被设计来在启动和关机时自动使用.</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch03.html">上一页</a> </td><td width="20%" align="center"><a accesskey="u" href="ch03.html">上一级</a></td><td width="40%" align="right"> <a accesskey="n" href="ch03s03.html">下一页</a></td></tr><tr><td width="40%" align="left" valign="top">第 3 章 字符驱动 </td><td width="20%" align="center"><a accesskey="h" href="index.html">起始页</a></td><td width="40%" align="right" valign="top"> 3.3. 一些重要数据结构</td></tr></table></div></body></html><div style="display:none"><script language="JavaScript" src="script.js"></script> </div>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -