解决方法
ioctl(2)通过fs / ioctl.c函数进入:
SYSCALL_DEFINE3(ioctl,unsigned int,fd,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,arg); if (error) goto out_fput; error = do_vfs_ioctl(filp,arg); out_fput: fput_light(filp,fput_needed); out: return error; }
请注意,已经有一个文件描述符fd关联.内核然后调用fget_light()来查找一个filp(大致是文件指针,但是不要把它与标准的IO FILE *文件指针混淆).对security_file_ioctl()的调用检查加载的安全模块是否允许ioctl(无论是按照AppArmor和TOMOYO中的名称,还是按照SMACK和SELinux中的标签),以及用户是否具有正确的功能(功能(7))进行通话.如果调用被允许,那么调用do_vfs_ioctl()来处理常见的ioctl本身:
switch (cmd) { case FIOCLEX: set_close_on_exec(fd,1); break; /* ... */
如果没有一个常见的情况是正确的,那么内核调用一个helper例程:
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,arg); if (error == -ENOIOCTLCMD) error = -EINVAL; out: return error; }
驱动程序提供自己的.unlocked_ioctl函数指针,像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,};