Linux驱动模型-设备

1、设备描述

Linux 系统中的每个设备由一个 struct device 描述。

struct device {
struct klist klist_children;
struct klist_node knode_parent; /* node in sibling list */
struct klist_node knode_driver;
struct klist_node knode_bus;
struct device *parent;

struct kobject kobj;
char bus_id[BUS_ID_SIZE]; /* position on parent bus */
struct device_type *type;
unsigned is_registered:1;
unsigned uevent_suppress:1;
struct device_attribute uevent_attr;
struct device_attribute *devt_attr;


struct semaphore sem; /* semaphore to synchronize calls to
* its driver.
*/


struct bus_type * bus; /* type of bus device is on */
struct device_driver *driver; /* which driver has allocated this
  device */
void *driver_data; /* data private to the driver */
void *platform_data; /* Platform specific data, device
  core doesn't touch it */
struct dev_pm_info power;


#ifdef CONFIG_NUMA
int numa_node; /* NUMA node this device is close to */
#endif
u64 *dma_mask; /* dma mask (if dma'able device) */
u64 coherent_dma_mask;/* Like dma_mask, but for
    alloc_coherent mappings as
    not all hardware supports
    64 bit addresses for consistent
    allocations such descriptors. */


struct list_head dma_pools; /* dma pools (if dma'ble) */


struct dma_coherent_mem *dma_mem; /* internal for coherent mem
    override */
/* arch specific additions */
struct dev_archdata archdata;


spinlock_t devres_lock;
struct list_head devres_head;


/* class_device migration path */
struct list_head node;
struct class *class;
dev_t devt; /* dev_t, creates the sysfs "dev" */
struct attribute_group **groups; /* optional groups */


void (*release)(struct device * dev);

};

2、设备注册、注销

int device_register(struct device * dev);

void device_unregister(struct device * dev);

一条总线也是个设备,也必须按设备注册。

3、设备属性

设备属性由struct device_attribute描述。

struct device_attribute {
struct attribute attr;
ssize_t (*show)(struct device *dev, struct device_attribute *attr,
char *buf);
ssize_t (*store)(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);

扫描二维码关注公众号,回复: 2171723 查看本文章

};

创建属性

int __must_check device_create_file(struct device *device,

struct device_attribute * entry);

删除属性

void device_remove_file(struct device * dev, struct device_attribute * attr);

4、参考实例

#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>

static void my_dev_release(struct device *dev)

printk("release\n");
}

struct device my_dev = {
.release = my_dev_release,
};

static ssize_t mydev_show(struct device *dev,struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", "This is my device!");
}

static DEVICE_ATTR(
dev, S_IRUGO, mydev_show, NULL);

static int __init my_device_init(void)
{
        
    /* 初始化设备 */
    my_dev.init_name = "my_dev"; // 设备名称
        
    /*注册设备*/
    device_register(&my_dev);

    /*创建属性文件*/
    device_create_file(&my_dev, &
dev_attr_dev);

    return 0;


}


static void my_device_exit(void)
{
device_unregister(&my_dev);
}

module_init(my_device_init);
module_exit(my_device_exit);

MODULE_LICENSE("Dual BSD/GPL");

Makefile

ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:                               
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:                                             
        $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
else
    obj-m := device.o

endif

验证结果:

在/sys/devices目录下创建my_dev目录。

test@ubuntu2018:/sys/devices/my_dev$ ls -l
total 0
-r--r--r-- 1 root root 4096 Jul 13 09:59 dev (属性文件)
drwxr-xr-x 2 root root    0 Jul 13 09:59 power

-rw-r--r-- 1 root root 4096 Jul 13 09:59 uevent

test@ubuntu2018:/sys/devices/my_dev$ cat dev
This is my device!

卸载该内核模块时,执行release所对应的函数。

5、参考实例

1)

#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>

static char *Version = "Revision: 1.0";


static int my_match(struct device *dev, struct device_driver *driver)
{
return !strncmp(dev->bus_id, driver->name, strlen(driver->name));
}

static void my_bus_release(struct device *dev)
{
printk(KERN_DEBUG "my bus release\n");
}

struct device my_bus = {
.bus_id   = "my_bus0",
.release  = my_bus_release
};

struct bus_type my_bus_type = {
.name = "my_bus",
.match = my_match,
};

EXPORT_SYMBOL(my_bus);
EXPORT_SYMBOL(my_bus_type);

static ssize_t show_bus_version(struct bus_type *bus, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%s\n", Version);
}

static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);

static int __init my_bus_init(void)
{
int ret;
        
    /*注册总线*/
ret = bus_register(&my_bus_type);
if (ret)
return ret;

/*创建属性文件*/
if (bus_create_file(&my_bus_type, &bus_attr_version))
printk(KERN_NOTICE "Fail to create version attribute!\n");

/*注册总线设备*/
ret = device_register(&my_bus);
if (ret)
printk(KERN_NOTICE "Fail to register device:my_bus!\n");

return ret;
}

static void my_bus_exit(void)
{
device_unregister(&my_bus);
bus_unregister(&my_bus_type);
}

module_init(my_bus_init);
module_exit(my_bus_exit);

MODULE_LICENSE("Dual BSD/GPL");

Makefile

ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:                               
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:                                             
        $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
else
    obj-m := bus.o

endif

2)

#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>

extern struct device my_bus; 
extern struct bus_type my_bus_type;

static void my_dev_release(struct device *dev)

printk("release\n");
}

struct device my_dev = {
.bus = &my_bus_type,// 设备依附的总线
.parent = &my_bus,// 父设备
.release = my_dev_release,
};


static ssize_t mydev_show(struct device *dev,struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", "This is my device!");
}

static DEVICE_ATTR(
dev, S_IRUGO, mydev_show, NULL);

static int __init my_device_init(void)
{
 
    /* 初始化设备 */
strncpy(my_dev.bus_id, "my_dev", BUS_ID_SIZE);// 设备名称
        
    /*注册设备*/
device_register(&my_dev);

/*创建属性文件*/
device_create_file(&my_dev, &
dev_attr_dev);

return 0;

}

static void my_device_exit(void)
{
device_unregister(&my_dev);
}

module_init(my_device_init);
module_exit(my_device_exit);

MODULE_AUTHOR("Andy Lau");

MODULE_LICENSE("Dual BSD/GPL");

Makefile

ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:                               
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:                                             
        $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
else
    obj-m := device.o

endif


猜你喜欢

转载自blog.csdn.net/xiezhi123456/article/details/81023530