driver - 驱动程序中的文件操作和结构声明
问题描述
我试图弄清楚基本内核驱动程序背后的代码是如何工作的。
我有以下结构:
static struct file_operations fops =
{
.open = dev_open,
.read = dev_read,
.write = dev_write,
.release = dev_release,
};
我的 dev_open 函数定义为:
static int dev_open(struct inode *, struct file *);
现在我也熟悉打开设备文件的原型是在 linux/fs.h 中定义的:
http://lxr.linux.no/linux+v3.10/include/linux/fs.h#L1517
这是该链接中的特定行:
int (*open) (struct inode *, struct file *);
现在我的问题是linux/fs.h 中定义的.open = dev_open,
和之间的关系是什么?int (*open) (struct inode *, struct file *);
是否将 dev_open 的地址传递给int (*open)
linux/fs.h 中定义的函数指针?必须有某种关系,或者将 struct fops 定义为“文件操作”类型有什么意义?
在这里提出并回答了一个类似的问题,但我觉得我的问题被遗漏了: 驱动程序中的文件操作
谢谢
解决方案
我认为这个问题更多是关于 C 而不是 Linux 内核。
结构或联合类型的成员不能具有函数类型,但它们可以具有指向函数类型的指针。例如,在 Linux 内核中,需要使用指向函数类型的指针来声明 的open
成员: . 将成员声明为错误。struct file_operations
int (*open)(struct inode *, struct file *);
int open(struct inode *, struct file *);
在 Linux 内核代码中的这个变量定义中:
static struct file_operations fops =
{
.open = dev_open,
.read = dev_read,
.write = dev_write,
.release = dev_release,
};
顺便说一句,上面通常应该owner
像这样初始化成员:
.owner = THIS_MODULE,
表达式dev_open
,和是函数指示符dev_read
,用作赋值表达式来初始化 的成员。函数指示符是具有函数类型的表达式。除非它是 , 的操作数或一元运算符,否则函数指示符将转换为指向函数类型的指针。因此,上述变量的定义完全等价于:dev_write
dev_release
fops
sizeof
_Alignof
&
foo
static struct file_operations fops =
{
.open = &dev_open,
.read = &dev_read,
.write = &dev_write,
.release = &dev_release,
};
(不要忘记也初始化.owner = THIS_MODULE,
。)
在那里,函数指示符是一元运算&
符的操作数,因此不会隐式转换为指向函数类型的指针,但&
运算符会将它们显式转换为指向函数类型的指针。
在上面的初始化之后fops
,rc = fops.open(inode, file);
间接调用dev_open(inode, file)
并将返回值赋值给rc
。有时您可能会看到这是用旧样式编写的:rc = (*fops.open)(inode, file);
. 他们都做同样的事情。函数调用运算符的操作数(
)
实际上始终是指向函数的指针。在 的情况下rc = (*fops.open)(inode, file);
,fops.open
有一个指向函数类型的指针。取消对函数(*fops.open)
类型的引用,但由于是函数指示符,因此它在函数调用之前隐式转换回指向函数类型的指针。同样,在直接调用中,是一个函数指示符,因此有一个fops.open
(*fops.open)
rc = dev_open(inode, file);
dev_open
函数类型,但在函数调用之前隐式转换为指向函数类型的指针。
推荐阅读
- javascript - React 无法解析我目录中的模块
- azure - 如何在 AD B2C 中更改用户密码后验证用户 ID 令牌
- c# - ManagedThreadId 如何对应 C# 中的 Thread 和 CPU 上的 Thread?
- css - 40px 的浏览器字体大小正在触发移动布局。这是一个错误吗?
- javascript - Javascript - 编写此函数的更好方法
- haskell - 在列表列表中计算第一名
- python - 为什么不显示来自导入模块的日志消息?
- python - 将 160*320 uint8 转置为 320*160 Mat(在 MATLAB 中)
- java - Itext 将 PDF 转换为 PDF-A-1A,Vera PDF 验证
- php - 我如何从 Apache 重写 url 请求值