ioctl系统调用流程

转载 2013年07月24日 21:14:39

原文地址:http://blog.sina.com.cn/s/blog_60692ff60100ecd2.html

 

一、系统调用框架

  • 与系统调用相关的数据结构和函数
系统调用函数名以“sys_”开头,后面是该系统调用的名字,由此构成了sys_name()这样的函数名。在include/asm/unistd.h中不同的体系结构为每一个系统调用定义了惟一的编号,假设用name来表示系统调用的名称,那么系统调用号与系统调用响应函数的关系是:以系统调用号 __NR_name作为下标,可找出系统调用表sys_call_table中对应表项的内容,它也就是该系统调用的响应函数sys_name的入口地址。
  • 系统调用具体执行流程
当执行一个系统调用时,处理器跳转到地址 0xc00。
参考代码:
 
arch/ppc/kernel/head.S

. = 0xc00
SystemCall:
EXCEPTION_PROLOG

stw r3,ORIG_GPR3(r21)
li r20,MSR_KERNEL
rlwimi r20,r23,0,16,16
bl transfer_to_handler
.long DoSyscall
.long ret_from_except
有关DoSyscall,它在文件arch/ppc/kernel/entry.S 中定义。这个函数最终使用系统调用编号把系统调用表的地址和索引加载,操作系统使用系统调用表把系统调用编号翻译为特定的系统调用。
系统调用表名为 sys_call_table,在 arch/ppc/kernel/misc.S 中定义。系统调用表包含有实现每个系统调用的函数的地址。
 
_GLOBAL(sys_call_table)
.long sys_ni_syscall
long sys_getegid
.long sys_acct
.long sys_umount
.long sys_ni_syscall
.long sys_ioctl
.long sys_fcntl
 
当DoSyscall 找到正确的系统调用地址后,它把调用指定的系统调用函数。如要做系统ioctl调用,对应的系统调用号为54,它把调用函数sys_ioctl()。下面具体会说明sys_ioctl()的调用过程。
当函数调用完毕之后,返回到 DoSyscall(),它把控制权切换给 ret_from_except(在 arch/ppc/kernel/entry.S 中定义)。它会去检查那些在切换回用户空间之前需要完成的任务。如果没有需要做的事情,那么就通过 restore 函数恢复用户进程的状态,并把控制权交还给用户程序。

二、ioctl系统调用的整个流程

sys_ioctl()是整个ioctl系统调用过程中的最顶级函数,它需要对输入的参数进行预处理,检查参数的合法性,然后调用底层的处理函数作更进一步的处理。
分析函数sys_ioctl(),参考代码:
 
fs/ioctl.c
asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct file * filp;
unsigned int flag;
int on, error = -EBADF;
filp = fget(fd);

if (!filp)
goto out;
error = 0;
TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_IOCTL,
fd,
cmd,
NULL);
lock_kernel();
switch (cmd) {
case FIOCLEX:
set_close_on_exec(fd, 1);
break;
case FIONCLEX:
set_close_on_exec(fd, 0);
break;
case FIONBIO:
if ((error = get_user(on, (int *)arg)) != 0)
break;
flag = O_NONBLOCK;
#ifdef __sparc__

if(O_NONBLOCK != O_NDELAY)
flag |= O_NDELAY;
#endif
if (on)
filp->f_flags |= flag;
else
filp->f_flags &= ~flag;
break;
case FIOASYNC:
if ((error = get_user(on, (int *)arg)) != 0)
break;
flag = on ? FASYNC : 0;

if ((flag ^ filp->f_flags) & FASYNC) {
if (filp->f_op && filp->f_op->fasync)
error = filp->f_op->fasync(fd, filp, on);
else error = -ENOTTY;
}
if (error != 0)
break;
if (on)
filp->f_flags |= FASYNC;
else
filp->f_flags &= ~FASYNC;
break;
default:

if (S_ISREG(filp->f_dentry->d_inode->i_mode))
error = file_ioctl(filp, cmd, arg);
else if (filp->f_op && filp->f_op->ioctl)

error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
}
unlock_kernel();
fput(filp);
out:
return error;
}
 
其中调用到函数的说明:
★ fget()函数,它是用来获取操作文件的指针,在这篇文档里,我是使用socket创建了一个文件描述符,fd = socket(AF_INET6, SOCK_DGRAM, 0);用户态的创建socket()到内核中传给函数sys_socket()处理, sys_socket()函数先调用函数sock_create()创建socket,然后把socket操作和文件操作关联起来,具体调用函数sock_map_fd()来实现,成功后把文件描述和文件结构file都保存在sock->file中。
对于函数fget()函数,它首先调用fcheck函数,检查一下文件描述符fd是否对应一个打开的文件,如果是就获取该文件,调用函数get_file()把f_count加1。
具体看一下fcheck函数的执行,参考代码:
 
include/linux/file.h
static inline struct file * fcheck(unsigned int fd)
{
struct file * file = NULL;
struct files_struct *files = current->files;
if (fd < files->max_fds)
file = files->fd[fd];
return file;
}
★ filp->f_op->ioctl()函数,调用设备对应的ioctl函数,对于使用socket创建文件描述符,它应该调用sock_ioctl()函数,具体流程图如下:
每一个设备都可以定义自己的ioctl命令字,命令编号的范围是SIOCDEVPRIVATE到SIOCDEVPRIVATE + 15。针对ipv6隧道,它定一个四个命令字,分别是SIOCGETTUNNEL,SIOCADDTUNNEL,SIOCCHGTUNNEL,SIOCDELTUNNEL。用户空间通过ioctl系统调用,最终调用到内核中定义的函数ip6ip6_tnl_ioctl。
 
sock_ioctl()函数调用中有关的内核函数:
sock_ioctl
inet6_ioctl
dev_ioctl
dev_ifsioc
■ sock_ioctl()
功能::直接调用一个协议特定的函数,如:当socket family是PF_INET6,调用函数inet6_ioctl。
■ inet6_ioctl()
功能:v6对应socket的ioctl内核函数,根据不同的case情况,作相应的处理。
 
case SIOCADDRT:
case SIOCDELRT:
return(ipv6_route_ioctl(cmd,(void *)arg));
当ioctl命令字不满足上述各种case情况时:
 
default:
if ((cmd >= SIOCDEVPRIVATE) &&
(cmd <= (SIOCDEVPRIVATE + 15)))
return(dev_ioctl(cmd,(void *) arg));
该设备自己定义了一些ioctl命令字范围在SIOCDEVPRIVATE到SIOCDEVPRIVATE + 15之间),调用函数dev_ioctl实现对该设备指定的ioctl命令的操作。
■ dev_ioctl()
功能:用来处理所有设备接口的ioctl请求,只是一个包装器,实际的动作把由dev_ifsioc()来实现。dev_ioctl做的只是检查这个调用是否具有了正当的权限。
■ dev_ifsioc()
功能:真正处理所有设备接口的ioctl请求。
具体操作说明:函数首先要做的一些事情包括得到与ifr.ifr_name相匹配的设备的结构,但这是在实现特定的接口命令之后。这些特定的接口命令被放置到一个巨大的switch语句之中。其中SIOCDEVPRIVATE命令和其他的在0x89F0到0x89FF之间的代码把出现在switch语句中的一个分支——default语句中,代码最后还增加了对无线网络的支持。内核执行时会检查表示设备的结构变量中,是否已经定义了一个与设备相关的 ioctl句柄(handler)。这里的句柄是一个函数指针,它在表示设备的结构变量中do_ioctl部分。如果已经设置了这个句柄,那么内核把会执行它。如ipv6隧道设备体,在初始化时,就作了说明:dev->do_ioctl = ip6ip6_tnl_ioctl,其中函数ip6ip6_tnl_ioctl就是该设备对应的ioctl句柄,由于隧道设备是自己定义的ioctl命令字,因而执行应在default语句中,进而调用到自己定义的ioctl处理函数ip6ip6_tnl_ioctl。

 

v4l2中ioctl的调用流程

leesagacious 原创,欢迎转载 vivi入口函数: vivi_init( )vivi_init(void) static int __init vivi_init(void) ...
  • leesagacious
  • leesagacious
  • 2015年09月21日 16:04
  • 1943

v4l2中ioctl的调用流程

leesagacious 原创,欢迎转载 vivi入口函数: vivi_init( )vivi_init(void) static int __init vivi_init(void) ...
  • leesagacious
  • leesagacious
  • 2015年09月21日 16:04
  • 1943

ioctl系统调用流程

  • 2010年11月11日 01:22
  • 40KB
  • 下载

ioctl系统调用

简介 ioctl是设备驱动程序中对设备的I/O通道进行管理的函数,提供了一种获得设备信息和向设备发送控制参数的手段。用于向设备发控制和配置命令,有些命令需要控制参数,这些数据是不能用read / wr...
  • coldsnow33
  • coldsnow33
  • 2013年11月15日 10:23
  • 839

用V4L2采集图像经常卡死在VIDIOC_DQBUF

最初写了一个小程序,循环采集10次图像,在PC机ubuntu12.4(在虚拟机里)中运行,没有发现问题,后来把采集次数改成100次后,发现经常会卡死在ioctl(fd, VIDIOC_DQBUF, &...
  • lucykingljj
  • lucykingljj
  • 2015年01月25日 20:59
  • 3524

linux网络协议栈分析——ioctl的调用流程

http://blog.csdn.net/cbmsft/article/details/7214639 首先从系统调用开始,ioctl的系统调用在fs/ioctl.c中: [c...
  • chengfangang
  • chengfangang
  • 2013年03月12日 10:12
  • 1172

系统调用的初始化过程与系统调用执行过程

刘昆   + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 本文首先介绍系统调用的初始化过程,其次已get...
  • yure1333
  • yure1333
  • 2015年04月05日 20:21
  • 644

ioctl是如何实现用户态向内核传参的

原文见链接ioctl的实现 原文见链接模块-模块开发(用户态和内核态通信-通过参数传递数据) 原文见链接Linux内核学习笔记之使用ioctl函数实现用户态命令 原文见链接ioctl系统...
  • zmbbb
  • zmbbb
  • 2016年03月19日 14:21
  • 250

视频驱动V4L2子系统驱动架构 - ioctl

文章系列 视频驱动V4L2子系统驱动架构 - 驱动框架 视频驱动V4L2子系统驱动架构 - ioctl 基于linux4.6.3,最后会附上一张ioctl调用总图,分析代码还是要用图来说明,这样...
  • l289123557
  • l289123557
  • 2016年07月23日 23:21
  • 3590

Linux的帧缓冲设备

参见: http://blog.ednchina.com/exbob/254847/message.aspx Linux的帧缓冲设备 帧缓冲(framebuffer)是 Linux 为显示设备...
  • Dable_cn
  • Dable_cn
  • 2013年10月22日 13:16
  • 941
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ioctl系统调用流程
举报原因:
原因补充:

(最多只允许输入30个字)