ioctl系统调用流程

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

ioctl系统调用流程

一、系统调用框架

与系统调用相关的数据结构和函数

系统调用函数名以“sys_”开头,后面是该系统调用的名字,由此构成了sys_name()这样的函数名。在include/asm/中不同的体系结构为每一个系统调用定义了惟一的编号,假设用name 来表示系统调用的名称,那么系统调用号与系统调用响应函数的关系是:以系统调用号

__NR_name作为下标,可找出系统调用表sys_call_table中对应表项的内容,它也就是该系统调用的响应函数sys_name的入口地址。

系统调用具体执行流程

当执行一个系统调用时,处理器跳转到地址0xc00。

参考代码:

arch/ppc/kernel/

. = 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/ 中定义。这个函数最终使用系统调用编号把系统调用表的地址和索引加载,操作系统使用系统调用表把系统调用编号翻译为特定的系统调用。

系统调用表名为sys_call_table,在arch/ppc/kernel/ 中定义。系统调用表包含有实现每个系统调用的函数的地址。

_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/ 中定义)。它会去检查那些在切换回用户空间之前需要完成的任务。如果没有需要做的事情,那么就通过restore 函数恢复用户进程的状态,并把控制权交还给用户程序。

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

sys_ioctl()是整个ioctl系统调用过程中的最顶级函数,它需要对输入的参数进行预处理,检查参数的合法性,然后调用底层的处理函数作更进一步的处理。

分析函数sys_ioctl(),参考代码:

fs/

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;

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

相关文档
最新文档