1
我正試圖編寫一個簡單的Linux內核驅動程序來加載模塊時打開一個GPIO引腳。模塊加載工程,但當我打電話rmmod刪除它,我得到這個錯誤:「設備沒有釋放()功能」 - 這是什麼意思?
sudo rmmod psctl
[13051.599199] ------------[ cut here ]------------
[13051.608758] WARNING: at drivers/base/core.c:196 device_release+0x78/0x84()
[13051.620581] Device 'psctl.0' does not have a release() function, it is broken and must be fixed.
[13051.637898] Modules linked in: psctl(O-) tmp102 hwmon nfsd rtc_ds1307 i2c_dev snd_bcm2835 snd_pcm snd_page_alloc snd_seq snd_seq_device snd_timer snd spidev leds_gpio led_class spi_bcm2708 i2c_bcm2708 [last unloaded: psctl]
[13051.670268] [<c0013f64>] (unwind_backtrace+0x0/0xf0) from [<c001e80c>] (warn_slowpath_common+0x4c/0x64)
[13051.688743] [<c001e80c>] (warn_slowpath_common+0x4c/0x64) from [<c001e8b8>] (warn_slowpath_fmt+0x30/0x40)
[13051.707217] [<c001e8b8>] (warn_slowpath_fmt+0x30/0x40) from [<c0239240>] (device_release+0x78/0x84)
[13051.725132] [<c0239240>] (device_release+0x78/0x84) from [<c01f4ad8>] (kobject_release+0x50/0x84)
[13051.742880] [<c01f4ad8>] (kobject_release+0x50/0x84) from [<bf0e6064>] (gpiotest_exit+0x10/0x2c [psctl])
[13051.761326] [<bf0e6064>] (gpiotest_exit+0x10/0x2c [psctl]) from [<c005e140>] (sys_delete_module+0x1b4/0x240)
[13051.780050] [<c005e140>] (sys_delete_module+0x1b4/0x240) from [<c000dae0>] (ret_fast_syscall+0x0/0x30)
[13051.798205] ---[ end trace 2eaa6df2dbf1f2e2 ]---
[13051.810083] psctl: Unloaded module
這是什麼意思?我查看了drivers/base/core.c,似乎kobject或kobj_type都沒有與它們關聯的釋放方法(或者kobj上沒有設置kobj_type)。我是否應該自己設置發佈方法,還是還有其他我沒有做的事情會爲我設置?
該模塊的代碼如下:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
#define AUTHOR "Xian Stannard <[email protected]>"
#define DESCRIPTION "Simple GPIO driver as proof of concept"
#define VERSION "0.1"
#define DRIVER_NAME "psctl"
#define OUT_GPIO 18
#define MPRINT(level, fmt, args...) printk(level DRIVER_NAME ": " fmt "\n", ## args)
struct ps_data_struct {
int out_gpio;
};
static int ps_probe(struct platform_device *pdev) {
struct ps_data_struct *data = pdev->dev.platform_data;
if(data == NULL)
MPRINT(KERN_DEBUG, "No platform data");
else {
MPRINT(KERN_DEBUG, "Has platform data: gpio %d", data->out_gpio);
}
return -ENODEV;
}
static int __exit ps_remove(struct platform_device *dev) {
MPRINT(KERN_DEBUG, "Remove");
return 0;
}
static void ps_release(struct device* dev) {
MPRINT(KERN_DEBUG, "Release");
}
static struct ps_data_struct ps_data = {
.out_gpio = OUT_GPIO
};
static struct platform_driver ps_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE
},
.probe = ps_probe,
.remove = __exit_p(ps_remove)
};
static struct platform_device ps_device = {
.name = DRIVER_NAME,
.id = 0,
.dev = {
.platform_data = &ps_data
}
};
static int __init gpiotest_init(void) {
int retval = 0;
retval = platform_driver_register(&ps_driver);
if(retval != 0) {
MPRINT(KERN_ERR, "Could not register driver");
goto drvreg;
}
retval = platform_device_register(&ps_device);
if(retval != 0) {
MPRINT(KERN_ERR, "Could not create device");
goto devreg;
}
MPRINT(KERN_INFO, "Loaded module");
return 0;
devreg:
platform_driver_unregister(&ps_driver);
drvreg:
MPRINT(KERN_ERR, "Module load failed with error code %d", retval);
return retval;
}
static void __exit gpiotest_exit(void) {
platform_device_unregister(&ps_device);
platform_driver_unregister(&ps_driver);
MPRINT(KERN_INFO, "Unloaded module");
}
module_init(gpiotest_init);
module_exit(gpiotest_exit);
MODULE_AUTHOR(AUTHOR);
MODULE_DESCRIPTION(DESCRIPTION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
我去選項1,它運作良好。謝謝。 – 2013-03-23 16:38:04