比较:unlocked_ioctl、compat_ioctl

  • compat_ioctl:支持64bit的driver必须要实现ioctl,当有32bit的userspace application call 64bit kernel的IOCTL的时候,这个callback会被调用到。如果没有实现compat_ioctl,那么32位的用户程序在64位的kernel上执行ioctl时会返回错误:Not a typewriter 
  • 如果是64位的用户程序运行在64位的kernel上,调用的是unlocked_ioctl,如果是32位的APP运行在32位的kernel上,调用的也是unlocked_ioctl。

The ioctl() system call has long been out of favor among the kernel developers, who see it as a completely uncontrolled entry point into the kernel. Given the vast number of applications which expect ioctl() to be present, however, it will not go away anytime soon. So it is worth the trouble to ensure that ioctl()calls are performed quickly and correctly - and that they do not unnecessarily impact the rest of the system.

ioctl() is one of the remaining parts of the kernel which runs under the Big Kernel Lock (BKL). In the past, the usage of the BKL has made it possible for long-running ioctl() methods to create long latencies for unrelated processes. Recent changes, which have made BKL-covered code preemptible, have mitigated that problem somewhat. Even so, the desire to eventually get rid of the BKL altogether suggests that ioctl() should move out from under its protection.

Simply removing the lock_kernel() call before calling ioctl() methods is not an option, however. Each one of those methods must first be audited to see what other locking may be necessary for it to run safely outside of the BKL. That is a huge job, one which would be hard to do in a single "flag day" operation. So a migration path must be provided. As of 2.6.11, that path will exist.

The patch (by Michael s. Tsirkin) adds a new member to the file_operations structure:

    long (*unlocked_ioctl) (struct file *filp, unsigned int cmd, 
                            unsigned long arg);

If a driver or filesystem provides an unlocked_ioctl() method, it will be called in preference to the older ioctl(). The differences are that the inode argument is not provided (it's available as filp->f_dentry->d_inode) and the BKL is not taken prior to the call. All new code should be written with its own locking, and should use unlocked_ioctl(). Old code should be converted as time allows. For code which must run on multiple kernels, there is a new HAVE_UNLOCKED_IOCTL macro which can be tested to see if the newer method is available or not.

Michael's patch adds one other operation:

    long (*compat_ioctl) (struct file *filp, unsigned int cmd, 
                          unsigned long arg);

If this method exists, it will be called (without the BKL) whenever a 32-bit process calls ioctl() on a 64-bit system. It should then do whatever is required to convert the argument to native data types and carry out the request. If compat_ioctl() is not provided, the older conversion mechanism will be used, as before. The HAVE_COMPAT_IOCTL macro can be tested to see if this mechanism is available on any given kernel.

The compat_ioctl() method will probably filter down into a few subsystems. Andi Kleen has posted patches adding new compat_ioctl() methods to the block_device_operations and scsi_host_template structures, for example, though those patches have not been merged as of this writing.

原文翻译:

长期以来,ioctl()系统调用一直不受内核开发人员的青睐,他们认为这是一个完全不受控制的内核入口点。鉴于大量应用程序期望ioctl()存在,但它不会很快消失。因此,确保快速正确地执行ioctl()调用并确保它们不会对系统的其余部分造成不必要的影响是值得的。

ioctl()是在大内核锁(BKL)下运行的内核的其余部分之一。过去,BKL的使用使得长时间运行的ioctl()方法可以为不相关的进程创建长延迟。最近的变化使得BKL覆盖的代码可以抢占,这在一定程度上缓解了这个问题。即便如此,最终完全摆脱BKL的愿望也表明ioctl()应该从它的保护下撤出。

但是,在调用ioctl()方法之前,只需删除lock_kernel()调用就不是一种选择。必须首先审核这些方法中的每一种,以查看在BKL之外安全运行可能需要的其他锁定。这是一项艰巨的工作,在单一的“旗帜日”行动中很难做到。因此必须提供迁移路径。从2.6.11开始,该路径将存在。

补丁(Michael s.Tsirkin)在file_operations结构中添加了一个新成员:

    long(* unlocked_ioctl)(struct file * filp,unsigned int cmd,
                            unsigned long arg);

如果驱动程序或文件系统提供unlocked_ioctl()方法,则将优先于较旧的ioctl()调用它。不同之处在于未提供inode参数(它可用作filp-> f_dentry-> d_inode),并且在调用之前不会使用BKL。所有新代码都应该使用自己的锁定编写,并且应该使用unlocked_ioctl()。旧代码应在时间允许的情况下进行转换。对于必须在多个内核上运行的代码,有一个新的HAVE_UNLOCKED_IOCTL宏可以进行测试,以查看更新的方法是否可用。

Michael的补丁添加了另一个操作:

    long(* compat_ioctl)(struct file * filp,unsigned int cmd,
                          unsigned long arg);
如果存在此方法,则只要32位进程在64位系统上调用ioctl(),就会调用它(没有BKL)。然后,它应该执行将参数转换为本机数据类型并执行请求所需的任何操作。如果未提供compat_ioctl(),则将使用旧的转换机制,如前所述。可以测试HAVE_COMPAT_IOCTL宏以查看此机制是否在任何给定内核上可用。

compat_ioctl()方法可能会过滤到几个子系统。例如,Andi Kleen发布了补丁,为block_device_operations和scsi_host_template结构添加了新的compat_ioctl()方法,尽管这些补丁在撰写本文时尚未合并。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值