[linux] IOCTL Linux device driver

Can anyone explain me,

  1. What is IOCTL?
  2. What is it used for?
  3. How can I use it?
  4. Why can't I define new function that does the same work as IOCTL?

This question is related to linux linux-kernel driver linux-device-driver ioctl

The answer is


The ioctl function is useful for implementing a device driver to set the configuration on the device. e.g. a printer that has configuration options to check and set the font family, font size etc. ioctl could be used to get the current font as well as set the font to a new one. A user application uses ioctl to send a code to a printer telling it to return the current font or to set the font to a new one.

int ioctl(int fd, int request, ...)
  1. fd is file descriptor, the one returned by open;
  2. request is request code. e.g GETFONT will get the current font from the printer, SETFONT will set the font on the printer;
  3. the third argument is void *. Depending on the second argument, the third may or may not be present, e.g. if the second argument is SETFONT, the third argument can be the font name such as "Arial";

int request is not just a macro. A user application is required to generate a request code and the device driver module to determine which configuration on device must be played with. The application sends the request code using ioctl and then uses the request code in the device driver module to determine which action to perform.

A request code has 4 main parts

    1. A Magic number - 8 bits
    2. A sequence number - 8 bits
    3. Argument type (typically 14 bits), if any.
    4. Direction of data transfer (2 bits).  

If the request code is SETFONT to set font on a printer, the direction for data transfer will be from user application to device driver module (The user application sends the font name "Arial" to the printer). If the request code is GETFONT, direction is from printer to the user application.

In order to generate a request code, Linux provides some predefined function-like macros.

1._IO(MAGIC, SEQ_NO) both are 8 bits, 0 to 255, e.g. let us say we want to pause printer. This does not require a data transfer. So we would generate the request code as below

#define PRIN_MAGIC 'P'
#define NUM 0
#define PAUSE_PRIN __IO(PRIN_MAGIC, NUM) 

and now use ioctl as

ret_val = ioctl(fd, PAUSE_PRIN);

The corresponding system call in the driver module will receive the code and pause the printer.

  1. __IOW(MAGIC, SEQ_NO, TYPE) MAGIC and SEQ_NO are the same as above, and TYPE gives the type of the next argument, recall the third argument of ioctl is void *. W in __IOW indicates that the data flow is from user application to driver module. As an example, suppose we want to set the printer font to "Arial".
#define PRIN_MAGIC 'S'
#define SEQ_NO 1
#define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long)

further,

char *font = "Arial";
ret_val = ioctl(fd, SETFONT, font); 

Now font is a pointer, which means it is an address best represented as unsigned long, hence the third part of _IOW mentions type as such. Also, this address of font is passed to corresponding system call implemented in device driver module as unsigned long and we need to cast it to proper type before using it. Kernel space can access user space and hence this works. other two function-like macros are __IOR(MAGIC, SEQ_NO, TYPE) and __IORW(MAGIC, SEQ_NO, TYPE) where the data flow will be from kernel space to user space and both ways respectively.

Please let me know if this helps!


Examples related to linux

grep's at sign caught as whitespace How to prevent Google Colab from disconnecting? "E: Unable to locate package python-pip" on Ubuntu 18.04 How to upgrade Python version to 3.7? Install Qt on Ubuntu Get first line of a shell command's output Cannot connect to the Docker daemon at unix:/var/run/docker.sock. Is the docker daemon running? Run bash command on jenkins pipeline How to uninstall an older PHP version from centOS7 How to update-alternatives to Python 3 without breaking apt?

Examples related to linux-kernel

How to fix: fatal error: openssl/opensslv.h: No such file or directory in RedHat 7 How do I delete virtual interface in Linux? Image vs zImage vs uImage iptables v1.4.14: can't initialize iptables table `nat': Table does not exist (do you need to insmod?) IOCTL Linux device driver How to solve "Kernel panic - not syncing - Attempted to kill init" -- without erasing any user data What is ":-!!" in C code? What is the difference between the kernel space and the user space? What does "make oldconfig" do exactly in the Linux kernel makefile? "FATAL: Module not found error" using modprobe

Examples related to driver

NVIDIA NVML Driver/library version mismatch php artisan migrate throwing [PDO Exception] Could not find driver - Using Laravel ADB Driver and Windows 8.1 Nexus 7 (2013) and Win 7 64 - cannot install USB driver despite checking many forums and online resources IOCTL Linux device driver How to add the JDBC mysql driver to an Eclipse project? How to get the nvidia driver version from the command line? Setting up PostgreSQL ODBC on Windows java.sql.SQLException: No suitable driver found for jdbc:microsoft:sqlserver

Examples related to linux-device-driver

IOCTL Linux device driver "FATAL: Module not found error" using modprobe

Examples related to ioctl

IOCTL Linux device driver "inappropriate ioctl for device"