科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道Liunx用户和内核空间之间的通信实现 (2)

Liunx用户和内核空间之间的通信实现 (2)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

当DoSyscall 找到正确的系统调用地址后,它将调用指定的系统调用函数。如要做系统ioctl调用,对应的系统调用号为54,它将调用函数sys_ioctl()。下面具体会说明sys_ioctl()的调用过程。

作者:赛迪网技术社区 来源:赛迪网技术社区 2007年10月25日

关键字: 实现 通信 内核 Linux

  • 评论
  • 分享微博
  • 分享邮件
 

当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); 
/*通过传入的参数文件句柄fd来获得需要操作的文件(或者设备)的指针,后面做了具体的说明*/
if (!filp)
goto out;
error = 0;
TRACE_FILE_SYSTEM(TRACE_EV_FILE_SYSTEM_IOCTL,
fd,
cmd,
NULL);
lock_kernel();
switch (cmd) { /*不同的传入命令字参数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__
/* SunOS compatibility item. */
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;

/* Did FASYNC state change ? */
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: 
/*如果传入的命令字参数cmd不符合上述情况,则需要调用更底层的ioctl处理函数
error = -ENOTTY;
/*下面根据情况调用ioctl处理函数*/
if (S_ISREG(filp->f_dentry->d_inode->i_mode))
error = file_ioctl(filp, cmd, arg); /*执行关于文件的ioctl的一般操作*/
else if (filp->f_op && filp->f_op->ioctl)
/*如果filp本身是一个设备,则执行filp->f_op->ioctl()函数,
对设备进行ioctl函数操作,该指针在初始化时就已经指向了设备函数接口中的ioctl函数,
因此在设备初始化时,只要向内核提交了file_operations{}结构
或block_device_operations{},其中的ioctl函数就会被调用到*/
error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
}
unlock_kernel();
fput(filp);

out:
return error;
}
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章