和设备文件对话(写和 IOCTL)
设备文件应该表现物理设备。大多物理设备既作为输出也作为输入,因此必须有某个机制使内核中的设备驱动程序得到来自进程的输出以便发送到设备。通过为输出打开设备文件并向其写而做到这个,就像写一个普通文件。在下面的例子中,这是用 device_write 实现的。
这不总是足够的。想象你有一个串行口连接到一个调制解调器(即使你有一个内置的调制解调器,从CPU的观点看它仍然是通过串行口连接到调制解调器,因此你不必责备你的想象力)。自然而然的事情是使用设备文件向调制解调器写(要么是调制解调器命令,要么是要通过电话线发送的数据)和从中读(要么是命令回应,要么是接收的数据)。然而,这留下了当你需要和串行口对话时该做什么的问题,例如以什么速率接收和发送数据。
在 Unix 中,答案是使用特殊的函数调用 ioctl ( input output control 的缩写)。每个设备可以有自己的 ioctl 命令,它可以读 ioctl (从进程向内核发送信息)和写 ioctl(返回信息给进程)(注意在这儿读写的作用又是颠倒的,因此ioctl 的读是发送消息给内核而写是从内核接收消息)或者什么也不做。 ioctl 使用三个参数调用: 合适的设备文件的文件描述符, ioctl 号及一个参数,该参数是类型长度,因此你可以使用一个模型传递任何东西。 (这是不准确的。例如你不能通过ioctl传递一个结构 -- 但你可以传递那个结构的指针)
ioctl 号用主设备号, ioctl 类型,命令和参数类型编码。这个 ioctl 号通常用一个头文件中的宏调用 (_IO, _IOR, _IOW 或 _IOWR -- 取决于类型)创建。头文件必须被使用ioctl的程序(因此它们可以生成合适的ioctl)及内核模块(因此它可以理解它) #include。 在下面的范例中,头文件是 chardev.h 而使用它的程序是 ioctl.c。
如果你想在你自己的模块中使用 ioctl ,最好接受官方的 ioctl 分配,因此如果你碰巧得到别人的ioctl或它们得到你的,你就可以知道某些事是错的。需要更多信息,请参考 `Documentation/ioctl-number.txt' 内核源代码树。