编写设备驱动程序

装入和卸载测试模块

使用命令 modload(1M)modunload(1M)modinfo(1M) 可以添加测试模块,在对驱动程序进行调试和压力测试时,这是一种非常有用的方法。正常操作中通常不需要这些命令,因为内核会自动装入需要的模块并卸载未使用的模块。moddebug 内核变量可与这些命令一起使用,以提供信息并设置控制。

使用 modload() 函数

使用 modload(1M) 可将模块强制装入内存。modload 命令可验证装入驱动程序时该驱动程序是否具有未解析的引用。装入驱动程序并表明该驱动程序一定可以连接。驱动程序成功装入时,将调用该驱动程序的 _info(9E) 入口点,但不一定调用 attach() 入口点。

使用 modinfo() 函数

使用 modinfo(1M) 可以确认驱动程序已装入。


示例 22–3 使用 modinfo 确认已装入的驱动程序


$ modinfo
 Id Loadaddr   Size Info Rev Module Name
  6 101b6000    732   -   1  obpsym (OBP symbol callbacks)
  7 101b65bd  1acd0 226   1  rpcmod (RPC syscall)
  7 101b65bd  1acd0 226   1  rpcmod (32-bit RPC syscall)
  7 101b65bd  1acd0   1   1  rpcmod (rpc interface str mod)
  8 101ce8dd  74600   0   1  ip (IP STREAMS module)
  8 101ce8dd  74600   3   1  ip (IP STREAMS device)
...
$ modinfo | grep mydriver
169 781a8d78   13fb   0   1  mydriver (Test Driver 1.5)

info 字段中的数字是为驱动程序选择的主设备号。如果提供了模块 ID,则可使用 modunload(1M) 命令来卸载模块。模块 ID 位于 modinfo 输出的左列中。

有时,发出 modunload 后驱动程序不会按预期卸载,因为该驱动程序被确定处于忙状态。由于驱动程序确实繁忙或 detach 入口点未正确实现而导致驱动程序无法执行 detach(9E) 时,会出现上述情况。

使用 modunload()

要从内存中删除所有当前未使用的模块,请使用模块 ID 0 运行 modunload(1M):


# modunload -i 0

设置 moddebug 内核变量

moddebug 内核变量可控制模块装入过程。moddebug 的可能值包括:

0x80000000

装入或卸载模块时向控制台列显消息。

0x40000000

提供更详细的错误消息。

0x20000000

装入或卸载时列显更多详细信息,如包含地址和大小。

0x00001000

不自动卸载驱动程序。系统资源变少时,系统不尝试卸载设备驱动程序。

0x00000080

不自动卸载流。系统资源变少时,系统不尝试卸载 STREAMS 模块。

0x00000010

不自动卸载任何类型的内核模块。

0x00000001

如果与 kmdb 一起运行,moddebug 会导致执行断点,并在调用每个模块的 _init() 例程之前立即返回到 kmdb。此设置还会在执行模块的 _info()_fini() 例程时生成其他调试消息。