总线,设备,驱动——(1)

来源:互联网 发布:网络订票在代办点取票 编辑:程序博客网 时间:2024/04/29 16:44
总线、设备和驱动


一、sysfs文件系统


设备模型是2.6内核新引入的特征。设备模型提供了一个独立的机制专门来表示设备,并描述其在系统中的拓扑结构。

2.4内核中,设备的信息放在/proc中。

而在2.6内核,内核把设备相关的信息归类在新增加sysfs文件系统,并将它挂载到/sys目录中,把设备信息归类的同时,让用户可以通过用户空间访问。


接下来简单介绍一些sys中的目录:

block:用于管理块设备,系统中的每一个块设备会在该目录下对应一个子目录。

bus:用于管理总线,没注册一条总线,在该目录下有一个对应的子目录。

其中,每个总线子目录下会有两个子目录:devicesdrivers

devices包含里系统中所有属于该总线的的设备。

drivers包含里系统中所有属于该总线的的驱动。

class:将系统中的设备按功能分类。

devices:该目录提供了系统中设备拓扑结构图。

dev:该目录已注册的设备节点的视图。

kernel:内核中的相关参数。

module:内核中的模块信息。

fireware:内核中的固件信息。

Fs:描述内核中的文件系统。

上面的目录,接下来的章节会常常提起busdevice


再说说这些目录,来个简单的命令:

root@xiaobai-laptop:/sys# llclass/net/eth0

lrwxrwxrwx 1 root root 0 2011-01-3110:11 class/net/eth0 ->../../devices/pci0000:00/0000:00:1c.5/0000:86:00.0/net/eth0/

上面的命令也可以看到class/net/eth0的路径其实就是devices目录中一个网卡设备的软连接


贴个书上的图:

由上面两个例子看到,sys中的其他目录都是将devvice目录下的数据加以转换加工而得。上面的图中,将use设备归类到bus总线上,又把它归类到class。正是在sys中有很多这样的结构,内核就有一个完整而且复杂的拓扑结构图。

而维护这些关系的结构体就包括kobjectksetktypesubsystem等数据结构,不过这里就先不介绍。

通过设备模型,内核就能实现多种不同的任务,如:

1、电源管理和系统关机。

2、与用户空间通信。这个就比较容易理解,sys目录向用户展示了设备模型的结构图。

3、热插拔设备。大概意思就是,当设备插入后,内核会根据插入的设备安装驱动,设备拔出后,内核又会自动卸载驱动。

4、设备类型。将设备归类。


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

在接下来的内容会简单介绍总线、设备和驱动程序的概念和函数调用,以下的函数我将模拟创建一条ubs总线,一个usb设备和一个usb驱动。

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


二、总线


总线是处理器和设备之间的通道,在设备模型中,所有的设备都通过总线相连,以总线来管理设备和驱动函数。总线有bus_type结构表示。

/*linux/device.h*/

51 struct bus_type {

52 constchar *name;

53 structbus_attribute *bus_attrs;

54 struct device_attribute*dev_attrs;

55 struct driver_attribute*drv_attrs;

56

57 int(*match)(struct device *dev, struct device_driver *drv);

58 int(*uevent)(struct device *dev, struct kobj_uevent_env *env);

59 int(*probe)(struct device *dev);

60 int (*remove)(struct device*dev);

61 void (*shutdown)(structdevice *dev);

62

63 int (*suspend)(struct device*dev, pm_message_t state);

64 int (*suspend_late)(structdevice *dev, pm_message_t state);

65 int (*resume_early)(structdevice *dev);

66 int (*resume)(struct device*dev);

67

68 struct dev_pm_ops *pm;

69

70 struct bus_type_private *p;

71 };

红色部分是以后将会介绍的成员,其中name是总线的名字,bus_attrs是总线的属性,那些函数指针的操作总线的方法,在这一章节先不讲总线的方法。


总线的注册和删除:

总线的注册有两个步骤:

1、定义一个bus_type结构体,并设置好需要设置的结构体成员。

2、调用函数bus_register注册总线。函数原型如下:

/*drivers/base/bus.c*/

865 int bus_register(structbus_type *bus)

该调用有可能失败,所以必须检查它的返回值,如果注册成功,会在/sys/bus下看到指定名字的总线。


总线删除时调用:

/*drivers/base/bus.c*/

946 void bus_unregister(structbus_type *bus)


接下来贴个函数:

/*8th_devModule_1/1st/bus.c*/

1 #include

2 #include

3

4 #include

5

6 structbus_type usb_bus = {

7 .name= "usb", //定义总线的名字为usb,注册成功后将在/sys/bus目录下看到

8 }; //目录usb,如果你的系统已经有usb总线,那你就要换个名字。

9

10 static int __initusb_bus_init(void)

11 {

12 int ret;

13 /*总线注册,必须检测返回值*/

14 ret =bus_register(&usb_bus);

15 if(ret){

16 printk("busregister failed!\n");

17 return ret;

18 }

19

20 printk("usb businit\n");

21 return 0;

22 }

23

24 static void __exitusb_bus_exit(void)

25 {

26 bus_unregister(&usb_bus);

27 printk("usb busbye!\n");

28 }

29

30 module_init(usb_bus_init);

31 module_exit(usb_bus_exit);

32

33 MODULE_LICENSE("GPL");

上面的函数可以看到,我仅仅定义了总线的名字为usb,其他的都没有做。看看效果:

[root: 1st]# insmod bus.ko

usb bus init

[root: 1st]# ls /sys/bus/usb///sys/bus目录下多了一个usb的目录,但是里面的东西都是空的,

devices drivers_autoprobe uevent //因为我仅仅设置了总线的名字

drivers drivers_probe


总线属性添加和删除:

个人理解,设置总线的属性后,会在对应的总线目录下增加了一个新的文件,通过对该文件的读写访问,触发相应的函数操作,从而实现/sys/的文件接口与内核设备模型的数据交互

/*linux/sysfs.h*/

28 struct attribute {

29 const char *name;//设定该文件的名字

30 struct module *owner;//设定该文件的属主

31 mode_t mode;//设定该文件的文件操作权限

32 };

/*linux/device.h*/

38 struct bus_attribute {

39 struct attribute attr;

40 ssize_t (*show)(structbus_type *bus, char *buf);

41 ssize_t (*store)(structbus_type *bus, const char *buf, size_t count);

42 };

bus_attribute中有两个函数指针,showstore

当访问总线目录中的name文件时,就会触发show函数,一般会将指定的信息存放到数组buf,并传到用户空间显示。

当修改总线目录中的name文件是,就会触发stroe函数,一般会将从用户空间传来的buf指针存放的count个字节内容存放到内核中。

由此可以看到,通过这样的文件,就能实现sys目录下的文件与内核设备模型之间的数据交互。


设置总线属性有两个步骤:

1、创建并初始化bus_attribute结构,使用宏BUS_ATTR

BUS_ATTR(_name, _mode, _show,_store)

该宏会定义一个名叫bus_attr__name(红色部分是固定的)的bus_attibute的结构,并且成员name设置为_name,文件权限mode设置为_mode,两个函数调用分别人showstore

下面看看BUS_ATTR的定义:
#define BUS_ATTR(_name, _mode, _show, _store) \
struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
bus_attr_##_name!!!!!

2、将bus_attibute添加到指定的总线上,使用以下调用:

/*/drivers/base/bus.c*/

123 int bus_create_file(structbus_type *bus, struct bus_attribute *attr)

该函数失败时返回错误号。

一旦调用该函数,会就在指定bus总线的目录下新建一个名叫_name的文件,权限为_mode,当访问和修改该文件是会分别调用showstore函数调用。


如果不需要该属性时,使用以下函数删除:

/*/drivers/base/bus.c*/

135 voidbus_remove_file(struct bus_type *bus, struct bus_attribute *attr)


说了这么多,马上来个程序:


/*8th_devModule_1/2nd/bus.c*/

1 #include

2 #include

3

4 #include

5

6 #define VER_SIZE 100

7

8 struct bus_type usb_bus = {

9 .name = "usb",

10 };

11

12 char Version[VER_SIZE] ="xiaobai V1.0";

13

14 staticssize_tshow_bus_version(struct bus_type*bus, char *buf)

15 {

16 return snprintf(buf,VER_SIZE, "%s\n", Version);

17 }

18 staticssize_tstore_bus_version(structbus_type *bus, const char *buf, size_t count)

19 {

20 return snprintf(Version,VER_SIZE, "%s", buf);

21 }

22/*该宏会定义一个名叫bus_attr_versionbus_attribute的结构,并且成员name设置为

23 *version,文件权限mode设置为S_IRUGO|S_IWUGO,并设置show函数为

24 *show_bus_versionstror函数为stroe_bus_version*/

25 staticBUS_ATTR(version, S_IRUGO|S_IWUGO, show_bus_version,store_bus_version);

26

27 static int __initusb_bus_init(void)

28 {

29 int ret;

30

31 /*总线注册*/

32 ret =bus_register(&usb_bus);

33 if(ret){

34 printk("busregister failed!\n");

35 goto err1;

36 }

37 /*为总线添加属性,调用成功后在/sys/bus/usb目录下有一个version的文件,权限为

38 *S_IRUGO|S_IWUGO,查看该文件时会调用函数show_bus_version,修改时调用store*/

39 ret =bus_create_file(&usb_bus, &bus_attr_version);

40 if(ret){

41 printk("bus creatfile failed!\n");

42 goto err2;

43 }

44 printk("usb businit\n");

45 return 0;

46

47 err2:

48 bus_unregister(&usb_bus);

49 err1:

50 return ret;

51 }

52

53 static void __exitusb_bus_exit(void)

54 {

55 bus_remove_file(&usb_bus,&bus_attr_version);//不调用这个也可以的,删除总线时会删除

56 bus_unregister(&usb_bus);

57 printk("usb busbye!\n");

58 }

验证一下:

[root: 2nd]# insmod bus.ko

usb bus init

[root: 2nd]# ls /sys/bus/usb/

devices drivers_autoprobe uevent

drivers drivers_probeversion //多了一个version文件

[root: 2nd]# ls -l/sys/bus/usb/version//文件的权限的可读可写(S_IRUGO|S_IWUGO

-rw-rw-rw-1 root root 4096 Oct 27 23:46 /sys/bus/usb/version

[root: 2nd]#cat /sys/bus/usb/version //读文件时触发show函数

xiaobai V1.0

[root: 2nd]#echo "haha"> /sys/bus/usb/version //写文件是触发store函数

[root: 2nd]# cat/sys/bus/usb/version

haha


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


三、设备


在最底层,linux系统中每个设备都用一个device结构的表示,如下,我省略掉部分成员:

/*linux/device.h*/

369 struct device {

370 struct klist klist_children;

371 struct klist_node knode_parent; /* node in sibling list */

372 struct klist_node knode_driver;

373 struct klist_node knode_bus;

374 structdevice *parent;//指定该设备的父设备,如果不指定(NULL),注册后的设备目录

375///sys/device

376 struct kobject kobj;

377 char bus_id[BUS_ID_SIZE]; /* position on parent bus */ //在总线生识别设备的字符串,

385//同时也是设备注册后的目录名字。

386 structbus_type *bus; /* type of bus device is on *///指定该设备连接的总线

387 structdevice_driver *driver; /* which driver has allocated this

388 device *///管理该设备的驱动函数

389 void *driver_data; /* data private to the driver *///驱动程序的私有数据

392 struct dev_pm_info power;

422 void (*release)(struct device *dev);//当给设备的最后一个引用被删除时,调用该函数

423 };

注册一个完整的device结构前,至少定义parrentbus_idbusrelease成员。但我接下来的程序仅仅定义了bus_id(指定目录的名字)、bus(对应的总线,不加也行)和release(这是必须的,不然卸载模块时会出错,不信自己试试)。


设备注册和注销:


与总线的注册一样:

1、定义结构体device

2、调用注册函数:

int device_register(struct device*dev)

函数失败返回非零,需要判断返回值来检查注册是否成功。


设备注销函数:

voiddevice_unregister(struct device *dev)


设备属性:


这个也是和总线属性差不多,不细讲:

设备相关的结构体和总线的类似,处理指定文件属性为,还定义了showstore两个函数。

/*linux/device.h*/

300 struct device_attribute {

301 struct attribute attr;

302 ssize_t (*show)(structdevice *dev, struct device_attribute *attr,

303 char *buf);

304 ssize_t (*store)(structdevice *dev, struct device_attribute *attr,

305 const char *buf,size_t count);

306 };


设置设备属性有两个步骤:

1、创建并初始化device_attribute结构,使用宏DEVICE_ATTR

DEVICE_ATTR(_name, _mode, _show,_store)

该宏会定义一个名叫dev_attr__name(红色部分是固定的)的device_attibute的结构,并且成员name设置为_name,文件权限mode设置为_mode,两个函数调用分别人showstore。这个跟bus的差不多,可参考上面。

2、将device_attibute添加到指定的设备上,使用以下调用:

/*drivers/base/core.c*/

430 int device_create_file(structdevice *dev, struct device_attribute *attr)

该函数失败时返回错误号。

一旦调用该函数,会就在指定dev设备的目录下新建一个名叫_name的文件,权限为_mode,当访问和修改该文件是会分别调用showstore函数调用。


如果不需要该属性时,使用以下函数删除:

/*drivers/base/core.c*/

443 voiddevice_remove_file(struct device *dev, struct device_attribute*attr)


讲了这么多,来个函数,和总线那个函数差不多,具体功能就是新建了一个执行名字(usb_device)的的设备目录,并且里面有一个属性文件version

/*8th_devModule_1/3rd/device.c*/

1 #include

2 #include

3

4 #include

5

6 #define VER_SIZE 100

7

8 externstruct bus_type usb_bus;

9

10 voidusb_dev_release(struct device *dev)

11 {

12 printk(" release\n");

13 }

14

15 structdevice usb_device = {

16.init_name = "usb_deivce",

17 .bus =&usb_bus, //指定该设备的总线,这样会在sys/bus/usb/device目录下有一个软连接

18 .release = usb_dev_release, //必须要都有release函数,不然卸载时会出错

19 };

11

12 char Version[VER_SIZE] ="xiaobai V1.0";

13

14 static ssize_tshow_device_version(struct device *dev,

15 structdevice_attribute *attr, char *buf)

16 {

17 return snprintf(buf,VER_SIZE, "%s\n", Version);

18 }

19 static ssize_tstore_device_version(struct device*dev,

20 structdevice_attribute *attr, const char *buf, size_t count)

21 {

22 return snprintf(Version,VER_SIZE, "%s", buf);

23 }

24/*该宏会定义一个名叫dev_attr_versiondevice_attribute的结构,并且成员name设置

25 *version,文件权限mode设置为S_IRUGO|S_IWUGO,并设置show函数为

26 *show_device_version,stror函数为stroe_device_version*/

27 staticDEVICE_ATTR(version, S_IRUGO|S_IWUGO,

28 show_device_version, store_device_version);

29

30 static int __initusb_device_init(void)

31 {

32 int ret;

33

34 /*设备注册,注册成功后在/sys/device目录下创建目录usb_device*/

35 ret =device_register(&usb_device);

36 if(ret){

37 printk("deviceregister failed!\n");

38 goto err1;

39 }

40 /*为设备添加属性,调用成功后在/sys/device/usb_device/目录下有一个version

41 *文件,权限为S_IRUGO|S_IWUGO,查看该文件时会调用函数show_device_version,

42 *修改时调用store_device_version*/

43 ret =device_create_file(&usb_device, &dev_attr_version);

44 if(ret){

45 printk("devicecreat file failed!\n");

46 goto err2;

47 }

48 printk("usb deviceinit\n");

49 return 0;

50

51 err2:

52 device_unregister(&usb_device);

53 err1:

54 return ret;

55 }

56

57 static void __exitusb_device_exit(void)

58 {

59 device_remove_file(&usb_device, &dev_attr_version);

60 device_unregister(&usb_device);

61 printk("usb devicebye!\n");

62 }

63

64 module_init(usb_device_init);

65 module_exit(usb_device_exit);

再看看效果,这是没有设置总线(bus=&usb_bus)时的效果,代码在8th_devModule_1/3rd/device_bak.c,我没有编译,如果需要的话自己编译运行看看

[root: 3rd]# insmod device.ko

usb device init

[root: /]#find -name "usb_device"//注册后查找一下在哪里有以设备bus_id为名字的目录

./sys/devices/usb_device///sys/device下有一个

[root: /]#

[root: /]# ls/sys/devices/usb_device///里面有一个空文件,一个属性文件version

uevent version

[root: /]# cat/sys/devices/usb_device/version //查看一下version,调用shoe函数

xiaobai V1.0

[root: /]#echo "haha" > /sys/devices/usb_device/version//修改version,调用store函数

[root: /]# cat/sys/devices/usb_device/version

haha

下面的是程序8th_devModule_1/3rd/device.c的效果:

[root: /]# cdreview_driver/8th_devModule/8th_devModule_1/3rd/

[root: 3rd]# insmod bus.ko//先加载总线的模块

usb bus init

[root: 3rd]# insmod device.ko//再加载设备的模块

usb device init

[root: 3rd]# cd /

[root: /]#find -name "usb_device"//查找一下usb_device,发现比没有指定总线时多了一个路径

./sys/devices/usb_device//这个目录的出现是因为语句(.bus= &usb_bus,

./sys/bus/usb/devices/usb_device//这个目录的出现是因为语句(device_register(&usb_device);

[root: /]# cat/sys/devices/usb_device/version

xiaobai V1.0

[root: /]# ls-l sys/bus/usb/devices //原来该路径只是一个软连接,是该设备归类到usb_bus总线下

lrwxrwxrwx 1 root root 0 Oct 27 13:49 usb_device ->../../../devices/usb_device

[root: /]# rmmod device

release//下载时调用release函数调用,如果没有设置release,卸载时会出错。

usb device bye!

[root: /]# rmmod bus

usb bus bye!

[root: /]#

上面的验证需要先加载bus.kobus.c源程序和1st/bus.c的函数没什么区别,只是将usb_bus导出到符号表。不然的话,加载模块时不能找到对应的总线。


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


四、驱动程序


设备模型跟踪所有系统所知道的设备。进行跟踪的主要原因是让驱动程序协调与设备之间的关系。

先看驱动程序的结构体,我仅仅贴出一些重要的成员:

/*linux/device.h*/

122 struct device_driver {

123 constchar *name;//驱动函数的名字,在对应总线的driver目录下显示

124 structbus_type *bus;//指定该驱动程序所操作的总线类型,必须设置,不然会注册失败

125

126 struct module *owner;

127 const char *mod_name; /* used for built-in modules */

128

129 int(*probe) (struct device *dev); //探测函数,以后会讲

130 int(*remove) (struct device *dev);//卸载函数,当设备从系统中删除时调用,以后讲

131 void(*shutdown) (struct device *dev);//当系统关机是调用

132 int (*suspend) (structdevice *dev, pm_message_t state);

133 int (*resume) (struct device*dev);

134 struct attribute_group**groups;

135

136 struct dev_pm_ops *pm;

137

138 struct driver_private *p;

139 };

和设备不一样的是,在注册驱动函数是必须指定该驱动函数对应的总线,因为驱动函数注册成功后,会存放在对应总线的driver目录下,如果没有总线,注册当然会失败。


与总线的注册一样:

1、定义结构体device_driver

2、调用注册函数:

214 int driver_register(structdevice_driver *drv)

函数失败返回非零,需要判断返回值来检查注册是否成功。


设备注销函数:

249 voiddriver_unregister(struct device_driver *drv)


驱动函数属性:


这个也是和总线属性差不多,不细讲:

驱动函数相关的结构体和总线的类似,处理指定文件属性为,还定义了showstore两个函数。

155 struct driver_attribute {

156 struct attribute attr;

157 ssize_t (*show)(structdevice_driver *driver, char *buf);

158 ssize_t (*store)(structdevice_driver *driver, const char *buf,

159 size_t count);

160 };


设置设备属性有两个步骤:

1、创建并初始化device_attribute结构,使用宏DEVICE_ATTR

DRIVER_ATTR(_name, _mode, _show,_store)

该宏会定义一个名叫driver_attr__name(红色部分是固定的)的driver_attibute的结构,并且成员name设置为_name,文件权限mode设置为_mode,两个函数调用分别人showstore

2、将device_attibute添加到指定的驱动函数上,使用以下调用:

/*drivers/base/driver.c*/

93 int driver_create_file(structdevice_driver *drv, struct driver_attribute *attr)

该函数失败时返回错误号。

一旦调用该函数,会就在指定dev设备的目录下新建一个名叫_name的文件,权限为_mode,当访问和修改该文件是会分别调用showstore函数调用。


如果不需要该属性时,使用以下函数删除:

/*drivers/base/driver.c*/

110 voiddriver_remove_file(struct device_driver *drv, structdriver_attribute *attr)


贴上函数:

/*8th_devModule_1/4th/driver.c*/

1 #include

2 #include

3

4 #include

5

6 #define VER_SIZE 100

7

8 extern struct bus_type usb_bus;

9

10 structdevice_driver usb_driver = {

11 .name= "usb_driver",

12 .bus =&usb_bus,

13 };

14

15 char Version[VER_SIZE] ="xiaobai V1.0";

16

17 static ssize_tshow_driver_version(struct device_driver*drv, char *buf)

18 {

19 return snprintf(buf,VER_SIZE, "%s\n", Version);

20 }

21 static ssize_tstore_driver_version(structdevice_driver *drv,

22 const char *buf, size_t count)

23 {

24 return snprintf(Version,VER_SIZE, "%s", buf);

25 }

26/*该宏会定义一个名叫driver_attr_versiondriver_attribute的结构,并且成员

27 *name设置为version,文件权限mode设置为S_IRUGO|S_IWUGO,并设置show函数为

28 *show_driver_version,stror函数为stroe_driver_version*/

29 staticDRIVER_ATTR(version, S_IRUGO|S_IWUGO,

30 show_driver_version, store_driver_version);

31

32 static int __initusb_driver_init(void)

33 {

34 int ret;

35

36 /*驱动注册,注册成功后在/sys/bus/usb/driver目录下创建目录usb_driver*/

37 ret =driver_register(&usb_driver);

38 if(ret){

39 printk("driverregister failed!\n");

40 goto err1;

41 }

42 /*为驱动添加属性,调用成功后在/sys/bus/usb/dirver目录下有一个version

43 *文件,权限为S_IRUGO|S_IWUGO,查看该文件时会调用函数show_driver_version,修改时

44 *调用store_driver_version*/

45 ret =driver_create_file(&usb_driver, &driver_attr_version);

46 if(ret){

47 printk("drivercreat file failed!\n");

48 goto err2;

49 }

50 printk("usb driverinit\n");

51 return 0;

52

53 err2:

54 driver_unregister(&usb_driver);

55 err1:

56 return ret;

57 }

58

59 static void __exitusb_driver_exit(void)

60 {

61 driver_remove_file(&usb_driver, &driver_attr_version);

62 driver_unregister(&usb_driver);

63 printk("usb driverbye!\n");

64 }

看看效果,同样必须先加载bus.ko

[root: /]# cdreview_driver/8th_devModule/8th_devModule_1/4th/

[root: 4th]#insmod bus.ko //必须先加载总线

usb bus init

[root: 4th]# insmod driver.ko

usb driver init

[root: 4th]# cd /

[root: /]#find -name "usb_driver"//只有一处创建了usb_driver目录

./sys/bus/usb/drivers/usb_driver

[root: /]# ls/sys/bus/usb/drivers/usb_driver/

bind uevent unbind version

[root: /]# cat/sys/bus/usb/drivers/usb_driver/version //访问version文件是触发show函数

xiaobai V1.0


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


五、总结


这节讲得内容其实不多,归纳起来就是四个函数一个属性结构体

属性结构体:xx_attribute

注册函数:xx_register

注销函数:xx+unregister

创建属性文件函数:xx_create_file

删除属性文件函数:xx_remove_file

其中xx可以是总线(bus)、设备(device)或者驱动函数(deriver)

一但注册成功,就会在/sys目录下相应的地方创建一个自己命名的目录。其中,设备和驱动函数还可以添加到指定的bus目录下。

总线的成功注册后会在/sys/bus目录下创建相应的目录。

设备的成功注册后会在/sys/device目录下创建相应的目录,如果指定总线,会在指定总线目录/sys/bus/xx/device下创建一个指向/sys/device目录的软连接。

驱动函数的公共注册会在/sys/bus/xx/driver目录下创建相应的目录。


属性文件提供了shoestore两个函数调用,当读写文件时会触发相应的函数调用,实现内核sysfs与用户空间的数据交互。

--------------------------------------------------------------------------------------------------------------------------

错误修正


按照国嵌的代码(LDD那本书上的代码也一样):
struct device my_bus = {
    .bus_id = "my_bus0",
    .release = my_bus_release,
};

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

编译时,提示 struct device 中没有bus_id 这样的错误。打开/lib/modules/2.6.35-28-generic/build/include/linux/device.h
找到struct device  的定义,里面没有bus_id,但有:
const char *init_name; /* initial name of the device */                      这句。

可见,要把上面结构中的.bus_id = "my_bus0",         改为       .init_name = "my_bus0",
同时上网搜到,return !strncmp(dev->bus_id, driver->name, strlen(driver->name));这句也要改成:
return !strncmp(dev_name(dev), driver->name, strlen(driver->name));

这样编译即可成功!

另注:
如果要设置设备的名字,也不再使用strncpy(my_dev.bus_id, "my_dev", BUS_ID_SIZE);     而改用:
dev_set_name(&dev, "name");




程序代码在这  里面有代码要按上面的修改    点击打开链接

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 索尼z5无限重启怎么办 苹果8基带坏了怎么办 oppo手机忘记图案密码怎么办 电池充不进去电怎么办 电脑充不进去电怎么办 苹果5c白苹果怎么办 港行不支持电信卡怎么办 安卓导航不开机怎么办 鞭炮放一半不响怎么办 禁止鸣笛的地方鸣笛了怎么办 手被炮仗炸了怎么办 手被猴子抓伤了怎么办 炸东西剩的油怎么办 炸臭豆腐剩的油怎么办 油炸久了油发黑怎么办 炸鱼的时候粘锅怎么办 吃了葱蒜有味怎么办 哺乳期喝了抹茶怎么办 干炸小黄鱼凉了怎么办 烧鱼酱油放多了怎么办 夏天腿干燥起皮怎么办 螃蟹柿子同时吃了怎么办 柿子和螃蟹一起吃怎么办 螃蟹和柿子吃了怎么办 今天为什么很多网站打不开怎么办 网上报名人太多服务器卡怎么办 网站换了电脑打不开怎么办 感冒时后背发凉怎么办? 脚扭了脚背疼怎么办 五妙水仙膏干了怎么办 红苹果接不到任务了怎么办 我判刑了家里老母亲怎么办 离婚之前对方把财产转移怎么办 有人侵犯我的名誉权怎么办 耳朵被咬红肿了怎么办 孕29周呼吸困难怎么办 痔疮出血一个星期了怎么办 怀孕长了副乳该怎么办 备孕期间长痔疮怎么办 15年凌度智能钥匙全丢怎么办 西水开发商跑了怎么办