linux 混杂设备模型

来源:岁月联盟 编辑:exp 时间:2011-10-14

在Linux系统中,存在一类字符设备,他们共享一个主设备号(10),但此设备号不同,我们称这类设备为混杂设备(miscdeivce),查看/proc/device中可以看到一个名为misc的主设备号为10.所有的混杂设备形成一个链表,对设备访问时内核根据次设备号找到对应的miscdevice设备。

Linux内核使用struct miscdeivce来描述一个混杂设备

struct miscdevice  {

    int minor;

    const char *name;

    const struct file_operations *fops;

    struct list_head list;

    struct device *parent;

    struct device *this_device;

    const char *nodename;

    mode_t mode;

};

minor是这个混杂设备的次设备号,若由系统自动配置,则可以设置为MISC_DYNANIC_MINOR,name是设备名.使用时只需填写minor次设备号,*name设备名,*fops文件操作函数集即可。

Linux内核使用misc_register函数注册一个混杂设备,使用misc_deregister移除一个混杂设备。注册成功后,linux内核为自动为该设备创建设备节点,在/dev/下会产生相应的节点。

 注册函数:

int misc_register(struct miscdevice * misc)

输入参数:struct miscdevice

返回值:

   表示注册成功。

负数 表示未成功。

卸载函数:

int  misc_deregister(struct miscdevice *misc)

0 表示成功。

负数 表示失败。

下面是基于linux 混杂设备模型的一个简单示例:

view sourceprint?01 #include <linux/module.h> 

02 #include <linux/kernel.h> 

03 #include <linux/types.h> 

04 #include <linux/fs.h> 

05 #include <linux/init.h> 

06 #include <linux/delay.h> 

07 #include <asm/uaccess.h> 

08 #include <asm/irq.h> 

09 #include <asm/io.h> 

10 #include <linux/cdev.h> 

11 #include <linux/device.h> 

12 #include <linux/miscdevice.h> 

13 #define DEVICE_NAME "BELL-Control" 

14 volatile unsigned long *gpbcon = NULL ; 

15 volatile unsigned long *gpbdat = NULL ;   

16 volatile unsigned long *gpbup = NULL ; 

17 static int bell_drv_open(struct inode *inode, struct file *file) 

18 { 

19      *gpbcon &= ~(0x3<<(0*2)); 

20      *gpbcon |= (0x1<<(0*2)) ;  

21      *gpbup = 0x0; 

22       printk("first_drv_open/n"); 

23       return 0; 

24 } 

25   

26 static ssize_t bell_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) 

27 { 

28       int val;    

29       copy_from_user(&val, buf, count) ;     

30       if (val == 1) 

31       { 

32        *gpbdat &= ~(1<<0); 

33          printk("first_drv_write 1111111/n"); 

34       } 

35       else

36       { 

37   

38          *gpbdat |= (1<<0); 

39           printk("first_drv_write 00000/n"); 

40       }   

41      return 0; 

42 } 

43   

44 static struct file_operations bell_drv_fops = { 

45      .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */

46      .open   =   bell_drv_open,      

47     .write = bell_drv_write,     

48 }; 

49  //注册混杂设备,每一个misc驱动会自动出现在/sys/class/misc/下 

50 static struct miscdevice misc = { 

51       .minor =MISC_DYNAMIC_MINOR, 

52       .name = DEVICE_NAME, 

53       .fops = &bell_drv_fops, 

54 }; 

55   

56 static int bell_drv_init(void) 

57 { 

58      int result; 

59      result = misc_register(&misc);    

60      printk (""DEVICE_NAME" initialized/n");  

61      gpbcon = (volatile unsigned long *)ioremap(0x56000010, 16); 

62      gpbdat = gpbcon + 1; 

63      gpbup = gpbcon + 2; 

64      return 0;  

65 } 

66   

67 static void bell_drv_exit(void) 

68 { 

69       misc_deregister(&misc); 

70       iounmap(gpbcon); 

71 } 

72   

73 module_init(bell_drv_init); 

74 module_exit(bell_drv_exit); 

75 MODULE_LICENSE("GPL"); 

摘自:liufazhang的博客