An ioctl, which means "input-output control" is a kind of device-specific system call. There are only a few system calls in Linux (300-400), which are not enough to express all the unique functions devices may have. So a driver can define an ioctl which allows a userspace application to send it orders. However, ioctls are not very flexible and tend to get a bit cluttered (dozens of "magic numbers" which just work... or not), and can also be insecure, as you pass a buffer into the kernel - bad handling can break things easily.
An alternative is the sysfs interface, where you set up a file under /sys/ and read/write that to get information from and to the driver. An example of how to set this up:
You would then have a file for your device in /sys/, for example, /sys/block/myblk/version for a block driver.
Another method for heavier use is netlink, which is an IPC (inter-process communication) method to talk to your driver over a BSD socket interface. This is used, for example, by the WiFi drivers. You then communicate with it from userspace using the libnl or libnl3 libraries.
ioctl function is useful when one is implementing a device driver to set the configuration on the device. e.g. a printer has configuration options to check and set font, font size etc. ioctl could be used to get current font as well as set font to another one. In user application make use of ioctl to send a code to a printer telling it to return the current font or to set font to a new one.
int ioctl(int fd, int request, ...)
fd is file descriptor, the one returned by open
request is request code. e.g GETFONT will get current font from printer, SETFONT will set font on a printer.
third argument is void *. Depending on second argument, the third may or may not be present.
e.g. if second argument is SETFONT, third argument may give font name as ARIAL.
So now int request is not just a macro, one is required to generate request code to be used by user application and device driver module to determine which configuration on device must be played with. One sends a request code using ioctl from user application and then uses the request code in 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 request code is SETFONT to set font on a printer, the direction for data transfer will be from user application to device driver module. User sends font name Arial to printer. If request code is GETFONT, direction is from printer to user application.
To generate request code Linux provide 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 adata transfer. So we would generate request code as below
#define PRIN_MAGIC 'P'
#define NUM 0
#define PAUSE_PRIN __IO(PRIN_MAGIC, NUM)
Now use ioctl as
ret_val = ioctl(fd, PAUSE_PRIN);
Corresponding system call in driver module will receive the code and pause the printer.
__IOW(MAGIC, SEQ_NO, TYPE)MAGIC and SEQ_NO are same as above, but third part gives the type of next argument, recall the third argument of ioctl is void *. W in __IOW indicates that direction of data is from user application to driver module. Let us take an example,
Suppose one is telling printer to set font to Arial.
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 direction of data flow will be from kernel space to user space and both ways respectively.
An
ioctl
, which means "input-output control" is a kind of device-specific system call. There are only a few system calls in Linux (300-400), which are not enough to express all the unique functions devices may have. So a driver can define an ioctl which allows a userspace application to send it orders. However, ioctls are not very flexible and tend to get a bit cluttered (dozens of "magic numbers" which just work... or not), and can also be insecure, as you pass a buffer into the kernel - bad handling can break things easily.An alternative is the
sysfs
interface, where you set up a file under/sys/
and read/write that to get information from and to the driver. An example of how to set this up:And during driver setup:
You would then have a file for your device in
/sys/
, for example,/sys/block/myblk/version
for a block driver.Another method for heavier use is netlink, which is an IPC (inter-process communication) method to talk to your driver over a BSD socket interface. This is used, for example, by the WiFi drivers. You then communicate with it from userspace using the
libnl
orlibnl3
libraries.ioctl
function is useful when one is implementing a device driver to set the configuration on the device. e.g. a printer has configuration options to check and set font, font size etc.ioctl
could be used to get current font as well as set font to another one. In user application make use ofioctl
to send a code to a printer telling it to return the current font or to set font to a new one.fd
is file descriptor, the one returned by openrequest
is request code. e.g GETFONT will get current font from printer, SETFONT will set font on a printer.void *
. Depending on second argument, the third may or may not be present. e.g. if second argument is SETFONT, third argument may give font name as ARIAL.So now int request is not just a macro, one is required to generate request code to be used by user application and device driver module to determine which configuration on device must be played with. One sends a request code using
ioctl
from user application and then uses the request code in device driver module to determine which action to perform.A request code has 4 main parts
If request code is SETFONT to set font on a printer, the direction for data transfer will be from user application to device driver module. User sends font name Arial to printer. If request code is GETFONT, direction is from printer to user application.
To generate request code Linux provide 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 adata transfer. So we would generate request code as belowNow use
ioctl
asCorresponding system call in driver module will receive the code and pause the printer.
__IOW(MAGIC, SEQ_NO, TYPE)
MAGIC
andSEQ_NO
are same as above, but third part gives the type of next argument, recall the third argument ofioctl
isvoid *
. W in__IOW
indicates that direction of data is from user application to driver module. Let us take an example, Suppose one is telling printer to set font to Arial.further,
Now
font
is a pointer, which means it is an address best represented asunsigned 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 asunsigned 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 direction of data flow will be from kernel space to user space and both ways respectively.Please let me know if this helps!