mirror of https://github.com/tLDP/LDP
78 lines
5.0 KiB
Plaintext
78 lines
5.0 KiB
Plaintext
<sect1><title>Talking to Device Files (writes and IOCTLs)</title>
|
|
|
|
<indexterm><primary>ioctl</primary></indexterm>
|
|
<indexterm><primary>device files</primary><secondary>input to</secondary></indexterm>
|
|
<indexterm><primary>device files</primary><secondary>write to</secondary></indexterm>
|
|
|
|
<para>Device files are supposed to represent physical devices. Most physical devices are used for output as well as input, so
|
|
there has to be some mechanism for device drivers in the kernel to get the output to send to the device from processes. This
|
|
is done by opening the device file for output and writing to it, just like writing to a file. In the following example, this
|
|
is implemented by <function>device_write</function>.</para>
|
|
|
|
<para>This is not always enough. Imagine you had a serial port connected to a modem (even if you have an internal modem, it is
|
|
still implemented from the CPU's perspective as a serial port connected to a modem, so you don't have to tax your imagination
|
|
too hard). The natural thing to do would be to use the device file to write things to the modem (either modem commands or data
|
|
to be sent through the phone line) and read things from the modem (either responses for commands or the data received through
|
|
the phone line). However, this leaves open the question of what to do when you need to talk to the serial port itself, for
|
|
example to send the rate at which data is sent and received.</para>
|
|
|
|
<indexterm><primary>serial port</primary></indexterm>
|
|
<indexterm><primary>modem</primary></indexterm>
|
|
|
|
<para>The answer in Unix is to use a special function called <function>ioctl</function> (short for Input Output ConTroL).
|
|
Every device can have its own <function>ioctl</function> commands, which can be read <function>ioctl</function>'s (to send
|
|
information from a process to the kernel), write <function>ioctl</function>'s (to return information to a process),
|
|
<footnote><para>Notice that here the roles of read and write are reversed <emphasis>again</emphasis>, so in
|
|
<function>ioctl</function>'s read is to send information to the kernel and write is to receive information from the
|
|
kernel.</para></footnote> both or neither. The <function>ioctl</function> function is called with three parameters: the file
|
|
descriptor of the appropriate device file, the ioctl number, and a parameter, which is of type long so you can use a cast to
|
|
use it to pass anything. <footnote><para>This isn't exact. You won't be able to pass a structure, for example, through an
|
|
ioctl --- but you will be able to pass a pointer to the structure.</para></footnote></para>
|
|
|
|
<para>The ioctl number encodes the major device number, the type of the ioctl, the command, and the type of the parameter.
|
|
This ioctl number is usually created by a macro call (<varname>_IO</varname>, <varname>_IOR</varname>, <varname>_IOW</varname>
|
|
or <varname>_IOWR</varname> --- depending on the type) in a header file. This header file should then be included both by the
|
|
programs which will use <function>ioctl</function> (so they can generate the appropriate <function>ioctl</function>'s) and by
|
|
the kernel module (so it can understand it). In the example below, the header file is <filename
|
|
class="headerfile">chardev.h</filename> and the program which uses it is <function>ioctl.c</function>.</para>
|
|
|
|
<indexterm><primary>_IO</primary></indexterm>
|
|
<indexterm><primary>_IOR</primary></indexterm>
|
|
<indexterm><primary>_IOW</primary></indexterm>
|
|
<indexterm><primary>_IOWR</primary></indexterm>
|
|
|
|
<para>If you want to use <function>ioctl</function>s in your own kernel modules, it is best to receive an official
|
|
<function>ioctl</function> assignment, so if you accidentally get somebody else's <function>ioctl</function>s, or if they get
|
|
yours, you'll know something is wrong. For more information, consult the kernel source tree at
|
|
<filename>Documentation/ioctl-number.txt</filename>.</para>
|
|
|
|
<indexterm><primary>official ioctl assignment</primary></indexterm>
|
|
<indexterm><primary>ioctl</primary><secondary>official assignment</secondary></indexterm>
|
|
<indexterm><primary>source file</primary><secondary>chardev.c</secondary></indexterm>
|
|
|
|
|
|
<example><title>chardev.c</title><programlisting><inlinegraphic fileref="lkmpg-examples/07-TalkingToDeviceFiles/chardev.c" format="linespecific"/></inlinegraphic></programlisting></example>
|
|
|
|
|
|
<indexterm><primary>source file</primary><secondary><filename>chardev.h</filename></secondary></indexterm>
|
|
|
|
|
|
<example><title>chardev.h</title><programlisting><inlinegraphic fileref="lkmpg-examples/07-TalkingToDeviceFiles/chardev.h" format="linespecific"/></inlinegraphic></programlisting></example>
|
|
|
|
|
|
<indexterm><primary>defining ioctls</primary></indexterm>
|
|
<indexterm><primary>ioctl</primary><secondary>defining</secondary></indexterm>
|
|
<indexterm><primary>source file</primary><secondary><filename>ioctl.c</filename></secondary></indexterm>
|
|
|
|
|
|
<example><title>ioctl.c</title><programlisting><inlinegraphic fileref="lkmpg-examples/07-TalkingToDeviceFiles/ioctl.c" format="linespecific"/></inlinegraphic></programlisting></example>
|
|
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
<!--
|
|
vim: tw=128
|
|
-->
|