内核怎么通过主设备号找驱动、次设备号找设备

之前看韦东山老师视频,说到linux驱动就知道主设备号找驱动,,次设备号找设备。这句到底怎么理解呢,如何在驱动中实现呢,在介绍该实现之前先看下内核中主次设备号的管理。在内核中,dev_t 类型( 在 <linux/types.h>头文件有定义 ) 用来表示设备号,包括主设备号和次设备号两部分。对于 2.6.x内核,dev_t是个32位量,其中高12位用来表示主设备号,低20位用来表示次设备号。

<span style="font-family:Times New Roman;font-size:12px;">(linux/kdev_t.h)#define MINORBITS 20/*次设备号*/#define MINORMASK ((1U << MINORBITS) – 1)/*次设备号掩码*/#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS)) /*dev右移20位得到主设备号*/#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK)) /*与次设备掩码与,得到次设备号*/</span>MAJOR宏将dev_t向右移动20位,得到主设备号;MINOR宏将dev_t的高12位清零,得到次设备号。相反,可以将主设备号和次设备号转换为设备号类型(dev_t),使用宏MKDEV可以完成这个功能。

Linux内核允许多个驱动共享一个主设备号,但更多的设备都遵循一个驱动对一个主设备号的原则。

尽管这些从设备都涉及到内存访问,但所实现功能有很大差别。然后来看下图1中主设备号为1的memory_fops中定义了哪些函数指针。代码如下:

<span style="font-family:Times New Roman;font-size:12px;">driver/char/mem.cstatic const struct file_operations memory_fops = { .open = memory_open, .llseek = noop_llseek,};</span>,其作用是根据次设备号找到次设备的驱动程序。

<span style="font-family:Times New Roman;font-size:12px;">static int memory_open(struct inode *inode, struct file *filp){// select different devices through minor device number commented by guoqingbo int minor; const struct memdev *dev; minor = iminor(inode); //get the minor device number commented by guoqingbo if (minor >= ARRAY_SIZE(devlist))return -ENXIO; dev = &devlist[minor];//select the specific file_operations if (!dev->fops)return -ENXIO; filp->f_op = dev->fops; if (dev->dev_info)filp->f_mapping->backing_dev_info = dev->dev_info; /* Is /dev/mem or /dev/kmem ? */ if (dev->dev_info == &directly_mappable_cdev_bdi)filp->f_mode |= FMODE_UNSIGNED_OFFSET; if (dev->fops->open) //open the devicereturn dev->fops->open(inode, filp); return 0;}</span>数组定义如下:

<span style="font-family:Times New Roman;font-size:12px;">static const struct memdev { const char *name; mode_t mode; const struct file_operations *fops; struct backing_dev_info *dev_info;} devlist[] = { [1] = { "mem", 0, &mem_fops, &directly_mappable_cdev_bdi },#ifdef CONFIG_DEVKMEM [2] = { "kmem", 0, &kmem_fops, &directly_mappable_cdev_bdi },#endif [3] = { "null", 0666, &null_fops, NULL },#ifdef CONFIG_DEVPORT [4] = { "port", 0, &port_fops, NULL },#endif [5] = { "zero", 0666, &zero_fops, &zero_bdi }, [7] = { "full", 0666, &full_fops, NULL }, [8] = { "random", 0666, &random_fops, NULL }, [9] = { "urandom", 0666, &urandom_fops, NULL }, [11] = { "kmsg", 0, &kmsg_fops, NULL },#ifdef CONFIG_CRASH_DUMP [12] = { "oldmem", 0, &oldmem_fops, NULL },#endif};</span> 通过上面代码及图1可看出,),图2说明了打开内存设备时,文件操作是如何改变的。所涉及的函数逐渐反映了设备的具体特性。最初只知道用于打开设备的一般函数。然后由打开与内存相关设备文件的具体函数所替代。接下来根据选择的次设备号,进一步细化函数指针 ,为不同的次设备号最终选定函数指针。

同时也用对她的怀念来惩罚自己。

内核怎么通过主设备号找驱动、次设备号找设备

相关文章:

你感兴趣的文章:

标签云: