clinux-kerneloperating-systemdriver

Writing character device driver, ioctl() vs normal read/write?


I've been toying with writing a character device module for the linux kernel and I came to a bit of a confusing stop.

I see online there is talk of using ioctl() to transfer commands/data from user programs to kernel space and vice-versa. But a lot of it seems like overkill to do what is already possible with the file_operations struct

// structure containing callbacks
static struct file_operations fops = 
{
    .read = dev_read, // address of dev_read
    .open = dev_open,  // address of dev_open
    .write = dev_write, // address of dev_write 
    .release = dev_rls, // address of dev_rls
};

What benefit is there to using ioctl() instead of using function defined at dev_read() and dev_write() that simply copy chunks of data to/from user land with copy_to_user() and copy_from_user()?


Solution

  • ioctl should only be used for those operations that aren't provided by default in the kernel.

    Having to call ioctl to read or write data to your device takes away a lot of the ease of use you have when using the simple read or write calls.

    By non-standard operations I mean things like setting up automatic ASCII/EBCDIC translation in a terminal device driver, or ejecting a disk from your DVD block device, or modifying serial communications parameters (baud rate, stop bits, etc) for serial communications devices.

    By all means use ioctl to transfer commands to (or get non-data-information like current parameters or statistics from) your device driver (the alternative is to use some complicated escaping scheme in the data like the AT command set for modems or (and this is showing my age) the CTRL-D for the Apple ][ disk subsystem, and that's rarely pretty.

    Leave the data transfer to the standard calls.