Can anyone explain me,
- What is
IOCTL
? - What is it used for?
- How can I use it?
- Why can't I define new function that does the same work as
IOCTL
?
Can anyone explain me,
IOCTL
?IOCTL
?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:
static ssize_t mydrvr_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", DRIVER_RELEASE);
}
static DEVICE_ATTR(version, S_IRUGO, mydrvr_version_show, NULL);
And during driver setup:
device_create_file(dev, &dev_attr_version);
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 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
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.
#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 direction of data flow will be from kernel space to user space and both ways respectively.
Please let me know if this helps!