Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do ioctls know which function to call in linux?

So when I call an ioctl on a device, with an ioctl number, how does it know which function to call?

like image 576
mdogg Avatar asked Feb 21 '11 02:02

mdogg


People also ask

How do Ioctls work?

In computing, ioctl (an abbreviation of input/output control) is a system call for device-specific input/output operations and other operations which cannot be expressed by regular system calls. It takes a parameter specifying a request code; the effect of a call depends completely on the request code.

Why do we use ioctl?

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.

What is ioctl system call?

The ioctl() system call manipulates the underlying device parameters of special files. In particular, many operating characteristics of character special files (e.g., terminals) may be controlled with ioctl() requests.

How do I use ioctl in userspace?

To invoke ioctl commands of a device, the user-space program would open the device first, then send the appropriate ioctl() and any necessary arguments. static int mydrvr_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);


2 Answers

The ioctl(2) enters via the fs/ioctl.c function:

SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
{
    struct file *filp;
    int error = -EBADF;
    int fput_needed;

    filp = fget_light(fd, &fput_needed);
    if (!filp)
            goto out;

    error = security_file_ioctl(filp, cmd, arg);
    if (error)
            goto out_fput;

    error = do_vfs_ioctl(filp, fd, cmd, arg);
 out_fput:
    fput_light(filp, fput_needed);
 out:
    return error;
}

Note that there is already a filedescriptor fd associated. The kernel then calls fget_light() to look up a filp (roughly, file pointer, but don't confuse this with the standard IO FILE * file pointer). The call into security_file_ioctl() checks whether the loaded security module will allow the ioctl (whether by name, as in AppArmor and TOMOYO, or by labels, as in SMACK and SELinux), as well as whether or not the user has the correct capability (capabilities(7)) to make the call. If the call is allowed, then do_vfs_ioctl() is called to either handle common ioctls itself:

    switch (cmd) {
    case FIOCLEX:
            set_close_on_exec(fd, 1);
            break;
    /* ... */

If none of those common cases are correct, then the kernel calls a helper routine:

static long vfs_ioctl(struct file *filp, unsigned int cmd,
                  unsigned long arg)
{
    int error = -ENOTTY;

    if (!filp->f_op || !filp->f_op->unlocked_ioctl)
            goto out;

    error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
    if (error == -ENOIOCTLCMD)
            error = -EINVAL;
 out:
    return error;
}

Drivers supply their own .unlocked_ioctl function pointer, like this pipe implementation in fs/pipe.c:

const struct file_operations rdwr_pipefifo_fops = {
    .llseek         = no_llseek,
    .read           = do_sync_read,
    .aio_read       = pipe_read,
    .write          = do_sync_write,
    .aio_write      = pipe_write,
    .poll           = pipe_poll,
    .unlocked_ioctl = pipe_ioctl,
    .open           = pipe_rdwr_open,
    .release        = pipe_rdwr_release,
    .fasync         = pipe_rdwr_fasync,
};
like image 98
sarnold Avatar answered Oct 05 '22 03:10

sarnold


There's a map in the kernel. You can register your own ioctl codes if you write a driver.

Edit: I wrote an ATA over Ethernet driver once and implemented a custom ioctl for tuning the driver at runtime.

like image 26
par Avatar answered Oct 05 '22 03:10

par