cdev_alloc() 对比 cdev_init()
cdev_alloc() vs cdev_init()
在 Linux 内核模块中,创建 struct cdev
时可以遵循两种不同的方法,如 this site and in this answer:
中所建议
第一种方法、cdev_alloc()
struct cdev *my_dev;
...
static int __init example_module_init(void) {
...
my_dev = cdev_alloc();
if (my_dev != NULL) {
my_dev->ops = &my_fops; /* The file_operations structure */
my_dev->owner = THIS_MODULE;
}
else
...
}
第二种方法,cdev_init()
static struct cdev my_cdev;
...
static int __init example_module_init(void) {
...
cdev_init(&my_cdev, my_fops);
my_cdev.owner = THIS_MODULE;
...
}
(假设 my_fops
是指向已初始化 struct file_operations
的指针)。
- 第一种方法是已弃用还是仍在使用?
- 第一种方法
cdev_alloc()
也可以使用 cdev_init()
吗?如果不是,为什么?
第二个问题也在linked answer的评论里。
他们做不同的事情。偏好是通常的 - 不需要时不使用动态分配,而在可能的情况下在堆栈上分配。
cdev_alloc()
动态分配my_dev
,所以在cdev_del()
.
时会调用kfree(pointer)
cdev_init()
不会释放指针。
最重要的是,结构my_cdev
的生命周期不同。在 cdev_init()
情况下 struct cdev my_cdev
绑定到包含的词法范围,而 cdev_alloc()
returns 动态分配指针直到 free-d 有效。
Can cdev_init()
be used also in the first approach, with cdev_alloc()
?
不,cdev_init
不应该用于字符设备,分配为cdev_alloc
。
在某种程度上,cdev_alloc
相当于 kmalloc
加上 cdev_init
。因此,为使用 cdev_alloc
创建的字符设备调用 cdev_init
没有任何意义。
此外,分配有 cdev_alloc
的字符设备包含一个 提示,该设备应该 解除分配 当不再被分配时用过的。为该设备调用 cdev_init
将清除该提示,因此您将得到 内存泄漏 。
cdev_init
和 cdev_alloc
之间的选择取决于您希望字符设备拥有的生命周期。
通常,人们希望字符设备的生命周期与模块的生命周期相同。在那种情况下:
- 定义类型为
struct cdev
的静态或全局变量。
- 使用
cdev_init
. 在模块的init函数中创建字符设备
- 使用
cdev_del
. 在模块的exit函数中销毁字符设备
- 确保字符设备的文件操作将
.owner
字段设置为 THIS_MODULE
。
在复杂的情况下,希望在模块初始化后的特定点创建一个字符设备。例如。模块可以为某些硬件提供驱动程序,而字符设备应该与该硬件绑定。在那种情况下,字符设备无法在模块的 init 函数中创建(因为尚未检测到硬件),更重要的是,字符设备无法在模块的 exit 函数中销毁。在那种情况下:
- 在结构中定义一个字段,描述硬件,指针类型
struct cdev*
。
- 在创建(探测)硬件的函数中使用
cdev_alloc
创建字符设备。
- 在销毁(断开)硬件的函数中用
cdev_del
销毁字符设备
第一种情况 cdev_del
在字符设备 未被用户使用 时被调用。 THIS_MODULE
在文件操作中提供了这种保证:如果用户打开了与字符设备对应的文件,则无法卸载模块。
在第二种情况下没有这样的保证(因为 cdev_del
在模块的退出函数中被调用 NOT)。所以,在cdev_del
returns的时候,一个字符设备可能还在被用户使用。这里 cdev_alloc
真的很重要:字符设备的 释放 将 延迟 直到用户关闭与字符设备关联的所有文件描述符.没有 cdev_alloc
.
就无法获得这种行为
在 Linux 内核模块中,创建 struct cdev
时可以遵循两种不同的方法,如 this site and in this answer:
第一种方法、cdev_alloc()
struct cdev *my_dev;
...
static int __init example_module_init(void) {
...
my_dev = cdev_alloc();
if (my_dev != NULL) {
my_dev->ops = &my_fops; /* The file_operations structure */
my_dev->owner = THIS_MODULE;
}
else
...
}
第二种方法,cdev_init()
static struct cdev my_cdev;
...
static int __init example_module_init(void) {
...
cdev_init(&my_cdev, my_fops);
my_cdev.owner = THIS_MODULE;
...
}
(假设 my_fops
是指向已初始化 struct file_operations
的指针)。
- 第一种方法是已弃用还是仍在使用?
- 第一种方法
cdev_alloc()
也可以使用cdev_init()
吗?如果不是,为什么?
第二个问题也在linked answer的评论里。
他们做不同的事情。偏好是通常的 - 不需要时不使用动态分配,而在可能的情况下在堆栈上分配。
cdev_alloc()
动态分配my_dev
,所以在cdev_del()
.
kfree(pointer)
cdev_init()
不会释放指针。
最重要的是,结构my_cdev
的生命周期不同。在 cdev_init()
情况下 struct cdev my_cdev
绑定到包含的词法范围,而 cdev_alloc()
returns 动态分配指针直到 free-d 有效。
Can
cdev_init()
be used also in the first approach, withcdev_alloc()
?
不,cdev_init
不应该用于字符设备,分配为cdev_alloc
。
在某种程度上,cdev_alloc
相当于 kmalloc
加上 cdev_init
。因此,为使用 cdev_alloc
创建的字符设备调用 cdev_init
没有任何意义。
此外,分配有 cdev_alloc
的字符设备包含一个 提示,该设备应该 解除分配 当不再被分配时用过的。为该设备调用 cdev_init
将清除该提示,因此您将得到 内存泄漏 。
cdev_init
和 cdev_alloc
之间的选择取决于您希望字符设备拥有的生命周期。
通常,人们希望字符设备的生命周期与模块的生命周期相同。在那种情况下:
- 定义类型为
struct cdev
的静态或全局变量。 - 使用
cdev_init
. 在模块的init函数中创建字符设备
- 使用
cdev_del
. 在模块的exit函数中销毁字符设备
- 确保字符设备的文件操作将
.owner
字段设置为THIS_MODULE
。
在复杂的情况下,希望在模块初始化后的特定点创建一个字符设备。例如。模块可以为某些硬件提供驱动程序,而字符设备应该与该硬件绑定。在那种情况下,字符设备无法在模块的 init 函数中创建(因为尚未检测到硬件),更重要的是,字符设备无法在模块的 exit 函数中销毁。在那种情况下:
- 在结构中定义一个字段,描述硬件,指针类型
struct cdev*
。 - 在创建(探测)硬件的函数中使用
cdev_alloc
创建字符设备。 - 在销毁(断开)硬件的函数中用
cdev_del
销毁字符设备
第一种情况 cdev_del
在字符设备 未被用户使用 时被调用。 THIS_MODULE
在文件操作中提供了这种保证:如果用户打开了与字符设备对应的文件,则无法卸载模块。
在第二种情况下没有这样的保证(因为 cdev_del
在模块的退出函数中被调用 NOT)。所以,在cdev_del
returns的时候,一个字符设备可能还在被用户使用。这里 cdev_alloc
真的很重要:字符设备的 释放 将 延迟 直到用户关闭与字符设备关联的所有文件描述符.没有 cdev_alloc
.