nda*_*ers 6 ioctl linux-device-driver linux-kernel
谢谢你看这篇文章.我正在尝试修补网络块设备驱动程序.如果您需要查看源代码,请访问http://code.ximeta.com.
我注意到从linux 2.6.37开始,lock_kernel()似乎已被弃用.我读了"ioctl()的新方法",发现设备驱动程序现在应该在操作之前执行特定的锁定.
所以如果可能的话,我想要一些建议.
我在块文件夹部分找到了当前代码中我认为相关的两个部分.
Source
block->io.c
->ctrldev.c
Run Code Online (Sandbox Code Playgroud)
我把每个片段都放在你的考虑范围内.
io.c包含对lock_kernel的一次调用:
NDAS_SAL_API xbool sal_file_get_size(sal_file file, xuint64* size)
{
definitions and declarations etc..
lock_kernel();
#ifdef HAVE_UNLOCKED_IOCTL
if (filp->f_op->unlocked_ioctl) {
some small statements
error = filp->f_op->unlocked_ioctl(filp, BLKGETSIZE64, (unsigned long)size);
actions if error or not etc.
}
#endif
unlock_kernel();
return ret;
}
Run Code Online (Sandbox Code Playgroud)
并且ctrldev.c包含主要的io函数:
#include <linux/spinlock.h> // spinklock_t
#include <linux/semaphore.h> // struct semaphore
#include <asm/atomic.h> // atomic
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/ide.h>
#include <linux/smp_lock.h>
#include <linux/time.h>
......
int ndas_ctrldev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
lots of operations and functions.
return result;
}
Run Code Online (Sandbox Code Playgroud)
后来ndas_ctrldev_ioctl函数被设置为前者.ioctl.
static struct file_operations ndasctrl_fops = {
.write = ndas_ctrldev_write,
.read = ndas_ctrldev_read,
.open = ndas_ctrldev_open,
.release = ndas_ctrldev_release,
.ioctl = ndas_ctrldev_ioctl,
};
Run Code Online (Sandbox Code Playgroud)
现在我想转换它以避免使用lock_kernel();
根据我的理解,我将修改前面的部分如下:
NDAS_SAL_API xbool sal_file_get_size(sal_file file, xuint64* size)
{
definitions and declarations etc..
#ifndef HAVE_UNLOCKED_IOCTL
lock_kernel();
#endif
#ifdef HAVE_UNLOCKED_IOCTL
if (filp->f_op->unlocked_ioctl) {
some small statements
error = filp->f_op->unlocked_ioctl(filp, BLKGETSIZE64, (unsigned long)size);
actions if error or not etc.
}
#endif
#ifndef HAVE_UNLOCKED_IOCTL
unlock_kernel();
#endif
return ret;
}
#ifdef HAVE_UNLOCKED_IOCTL
long ndas_ctrldev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
#else
int ndas_ctrldev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
#endif
{
#ifdef HAVE_UNLOCKED_IOCTL
! add some sort of lock here !
#endif
lots of operations and functions.
#ifdef HAVE_UNLOCKED_IOCTL
! add unlock statement here !
#endif
return result;
}
static struct file_operations ndasctrl_fops = {
.write = ndas_ctrldev_write,
.read = ndas_ctrldev_read,
.open = ndas_ctrldev_open,
.release = ndas_ctrldev_release,
#ifdef HAVE_UNLOCKED_IOCTL
.unlocked_ioctl = ndas_ctrldev_ioctl,
#else
.ioctl = ndas_ctrldev_ioctl,
#endif
};
Run Code Online (Sandbox Code Playgroud)
所以,我会问以下建议.
这看起来是正确的吗?
我理解将锁移动到io功能是否正确?
基于crtrldev.c中的包含,你能推荐任何锁头吗?(我试图研究一些其他处理filp和lock_kernel的驱动程序,但我太过于努力找到答案了.)
大内核锁(BKL)已被弃用 - 从2.6.39开始,它不再存在.
lock_kernel()转换的方式是用每个驱动程序的互斥锁替换它.如果驱动程序是很简单的,你可以简单地为驱动程序创建一个互斥体,并更换所有用途lock_kernel()和unlock_kernel()互斥锁锁定/解锁电话.但是请注意,以前使用BKL(lock_kernel()用于锁定的锁)调用的某些函数保持不变; 您还必须为这些功能添加锁定/解锁调用.
如果驱动程序可以递归获取BKL,则无效; 如果是这种情况,你必须自己跟踪它以避免死锁(这是在转换中完成的reiserfs,它在递归BKL行为和在休眠时丢弃的事实上都有很大的依赖).
转换为每个驱动程序互斥锁后的下一步是将其更改为使用每设备互斥锁而不是每个驱动程序互斥锁.
这是解决方案.
#if HAVE_UNLOCKED_IOCTL
#include <linux/mutex.h>
#else
#include <linux/smp_lock.h>
#endif
.
.
.
#if HAVE_UNLOCKED_IOCTL
mutex_lock(&fs_mutex);
#else
lock_kernel();
#endif
Run Code Online (Sandbox Code Playgroud)
这仅显示替换锁定调用.正如我在上面关于unlocked_ioctl的问题部分中所猜测的那样,其他部分已经解决了.感谢您的检查和帮助.
| 归档时间: |
|
| 查看次数: |
11440 次 |
| 最近记录: |