versiones ultima torvalds linus descargar como linux linux-kernel

torvalds - ultima version de linux



¿Cómo saben las ioctls a qué función llamar en Linux? (3)

Entonces, cuando llamo a ioctl en un dispositivo, con un número ioctl, ¿cómo sabe a qué función llamar?


Hay un mapa en el kernel. Puede registrar sus propios códigos ioctl si escribe un controlador.

Editar: escribí un controlador ATA sobre Ethernet una vez e implementé un ioctl personalizado para ajustar el controlador en tiempo de ejecución.


Una explicación simplificada:

El descriptor de archivo que pasa a ioctl apunta a la estructura de inode que representa el dispositivo que va a ioctl.

La estructura del inode contiene el número de dispositivo dev_t i_rdev , que se usa como índice para encontrar la estructura file_operations del controlador del file_operations . En esta estructura, hay un puntero a la función ioctl definida por el controlador del dispositivo.

Puede leer Controladores de dispositivo Linux, 3ra Edición para una explicación más detallada. Puede ser un poco desactualizado, pero una buena lectura, sin embargo.


El ioctl(2) entra a través de la función fs/ioctl.c :

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; }

Tenga en cuenta que ya hay un descriptor de archivo fd asociado. El núcleo luego llama a fget_light() para buscar un filp (más o menos, puntero de archivo, pero no confunde esto con el puntero de archivo IO FILE * estándar). La llamada a security_file_ioctl() comprueba si el módulo de seguridad cargado permitirá ioctl (ya sea por nombre, como en AppArmor y TOMOYO, o por etiquetas, como en SMACK y SELinux), así como si el usuario tiene o no la capacidad correcta (capacidades (7)) para hacer la llamada. Si se permite la llamada, se llama a do_vfs_ioctl() para que maneje las ioctls comunes por sí mismo:

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

Si ninguno de esos casos comunes es correcto, entonces el kernel llama a una rutina de ayuda:

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; }

Los controladores proporcionan su propio puntero de función .unlocked_ioctl , como esta implementación de canalización en 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, };