转自:无为和尚的Linux内核大讲堂系列。http://blog.csdn.net/z2007b/article/details/6388753
终于快讲完了,这一节其实就是让上节我们所说的四大天王露下小脸。源码分析请自行完成吧。我建议大家可以试着先看一下代码,如果能看懂,那就把我写的那破玩意删掉,自已实现一遍,如果不能看懂,那马上回过去从第一小节重新看过,耐心,一定要有耐心,没耐心,啥都完了。帖上原码:
Makefile:
obj-m+=wwhs_bus.o
KERNELDIR=/opt/kernel/linux-2.6.38/linux-2.6.38.5
PWD:=$(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o* *.ko* *.mod.c *.cmd *.symvers .tmp_versions .*.cmd
wwhs_public.h:
#include <linux/module.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/stat.h>
#include <linux/slab.h>
#include <linux/kobject.h>
#include <linux/klist.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/kprobes.h>
#define wwhs_dbg(dbgbuf) printk(KERN_ERR"wwhs:%s/n",dbgbuf);
#include "../wwhs_public.h"
#define WWHS_MAJOR 83
void wwhs_release(struct device *dev)
{
printk(KERN_ERR"wwhs:dev:%s is release/n",dev->kobj.name);
}
struct device wwhs_bus = {
.init_name = "wwhs",
.release = wwhs_release,
};
static struct device wwhs_dev = {
.init_name = "wwhsled0",
.release = wwhs_release,
};
static int wwhs_bus_match(struct device *dev, struct device_driver *drv)
{
int ret = -1;
ret = strncmp(dev->kobj.name, drv->name, strlen(drv->name));
printk(KERN_ERR"wwhs:dev->kobj.name:%s drv->name:%s ret:%d/n",dev->kobj.name,drv->name,ret);
return !ret;
}
static int wwhs_bus_probe(struct device *dev)
{
int ret = -1;
if (dev->driver->probe)
ret = dev->driver->probe(dev);
return ret;
}
static struct bus_type wwhs_bus_type = {
.name = "wwhs",
.match = wwhs_bus_match,
};
static struct class *wwhs_class;
static int wwhs_bus_register()
{
int ret = -1;
wwhs_bus.class = wwhs_class;
ret = device_register(&wwhs_bus);
if (ret) goto device_error;
ret = bus_register(&wwhs_bus_type);
if (ret) goto bus_error;
return ret;
bus_error:
device_unregister(&wwhs_bus);
device_error:
return ret;
}
static void wwhs_bus_unregister()
{
device_unregister(&wwhs_bus);
bus_unregister(&wwhs_bus_type);
}
static int wwhs_class_register(void)
{
wwhs_class = class_create(THIS_MODULE, "wwhsclass");
if (IS_ERR(wwhs_class)){
printk(KERN_ERR"wwhs: class create error/n");
return PTR_ERR(wwhs_class);
}
printk(KERN_ERR"wwhs: class create success/n");
return 0;
}
static void wwhs_class_unregister()
{
class_destroy(wwhs_class);
}
static int wwhs_device_register(struct device *dev)
{
dev->devt = MKDEV(WWHS_MAJOR,1);
dev->bus = &wwhs_bus_type;
dev->parent = &wwhs_bus;
return device_register(dev);
}
static void wwhs_device_unregister(struct device *wwhs_dev)
{
device_unregister(wwhs_dev);
}
static struct device_driver wwhs_drv = {
.name = "wwhsled",
};
static wwhs_drv_probe(struct device *dev)
{
printk(KERN_ERR"wwhs:dev:%s is probe/n",dev->kobj.name);
return 0;
}
static wwhs_drv_remove(struct device *dev)
{
printk(KERN_ERR"wwhs:dev:%s is remove/n",dev->kobj.name);
return 0;
}
static int wwhs_driver_register(struct device_driver *wwhs_driver)
{
int ret = -1;
wwhs_driver->bus = &wwhs_bus_type;
wwhs_driver->owner = THIS_MODULE;
wwhs_driver->probe = wwhs_drv_probe;
wwhs_driver->remove = wwhs_drv_remove;
ret = driver_register(wwhs_driver);
return ret;
}
static void wwhs_driver_unregister(struct device_driver *wwhs_driver)
{
driver_unregister(wwhs_driver);
}
static int __init wwhs_init()
{
int ret = -1;
ret = wwhs_class_register();
if (ret) goto error;
ret = wwhs_bus_register();
if (ret) goto error;
ret = wwhs_device_register(&wwhs_dev);
if (ret) goto bus_error;
ret = wwhs_driver_register(&wwhs_drv);
if (ret) goto device_error;
return ret;
device_error:
wwhs_device_unregister(&wwhs_dev);
bus_error:
wwhs_bus_unregister();
class_error:
wwhs_class_unregister();
error:
return ret;
}
static void __exit wwhs_exit()
{
wwhs_device_unregister(&wwhs_dev);
wwhs_driver_unregister(&wwhs_drv);
wwhs_bus_unregister();
wwhs_class_unregister();
}
module_init(wwhs_init);
module_exit(wwhs_exit);
MODULE_AUTHOR("wwhs");
MODULE_DESCRIPTION("wwhs_bus test");
MODULE_LICENSE("GPL");
上面就是四大天王小露一下脸,至此,驱动模型的分析要告一段落了。如果根着看了的朋友,我相信肯定是有所收获的。谢谢各位。你们的支持是我前进的动力。^_^