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