设为首页 加入收藏

TOP

Linux字符设备驱动之register_chrdev_region()系列(一)
2014-11-24 12:31:33 】 浏览:7946
Tags:Linux 字符 设备驱动 register_chrdev_region 系列

1.内核中所有已分配的字符设备编号都记录在一个名为 chrdevs 散列表里。该散列表中的每一个元素是一个 char_device_struct 结构,它的定义如下:


static struct char_device_struct {


struct char_device_struct *next; // 指向散列冲突链表中的下一个元素的指针


unsigned int major; // 主设备号


unsigned int baseminor; // 起始次设备号


int minorct; // 设备编号的范围大小


char name[64]; // 处理该设备编号范围内的设备驱动的名称


struct file_operations *fops;


struct cdev *cdev; // 指向字符设备驱动程序描述符的指针


} *chrdevs[CHRDEV_MAJOR_HASH_SIZE];


1>内核并不是为每一个字符设备编号定义一个 char_device_struct 结构,而是为一组对应同一个字符设备驱动的设备编号范围定义一个 char_device_struct 结构。chrdevs 散列表的大小是 255,散列算法是把每组字符设备编号范围的主设备号以 255 取模插入相应的散列桶中。同一个散列桶中的字符设备编号范围是按起始次设备号递增排序的。


2.注册


内核提供了三个函数来注册一组字符设备编号,这三个函数分别是 register_chrdev_region()alloc_chrdev_region()


register_chrdev()。这三个函数都会调用一个共用的


__register_chrdev_region() 函数来注册一组设备编号范围(即一个 char_device_struct 结构)。


1>int register_chrdev_region(dev_t from, unsigned count, const char *name)


from :要分配的设备编号范围的初始值(次设备号常设为0);


Count:连续编号范围.


name:编号相关联的设备名称. (/proc/devices);



2>动态分配:


int alloc_chrdev_region(dev_t *dev,unsigned int firstminor,unsigned int count,char *name);


firstminor是请求的最小的次编号;


count是请求的连续设备编号的总数;


name为设备名,返回值小于0表示分配失败。


然后通过major=MMOR(dev)获取主设备号


3>释放:


Void unregist_chrdev_region(dev_t first,unsigned int count);


调用Documentation/devices.txt中能够找到已分配的设备号.


3.__register_chrdev_region() 函数的实现代码


/*


84 * Register a single major with a specified minor range.


85 *


86 * If major == 0 this functions will dynamically allocate a major and return


87 * its number.


88 *


89 * If major > 0 this function will attempt to reserve the passed range of


90 * minors and will return zero on success.


91 *


92 * Returns a -ve errno on failure.


93 */


94static struct char_device_struct *


95__register_chrdev_region(unsigned int major, unsigned int baseminor,


96 int minorct, const char *name)


97{


98 struct char_device_struct *cd, **cp;


99 int ret = 0;


100 int i;


101


102 cd = kzalloc(sizeof(struct char_device_struct), GFP_KERNEL);


103 if (cd == NULL)


104 return ERR_PTR(-ENOMEM);


105


106 mutex_lock(&chrdevs_lock);


107


108 /* temporary */


109 if (major == 0) {


110 for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) {


111 if (chrdevs[i] == NULL)


112 break;


113 }


114


115 if (i == 0) {


116 ret = -EBUSY;


117 goto out;


118 }


119 major = i;


120 ret = major;


121 }


122


123 cd->major = major;


124 cd->baseminor = baseminor;


125 cd->minorct = minorct;


126 strlcpy(cd->name, name, sizeof(cd->name));


127


128 i = major_to_index(major);


129


130 for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)


131 if ((*cp)->major > major ||


132 ((*cp)->major == major &&


133 (((*cp)->baseminor >= baseminor) ||


134 ((*cp)->baseminor + (*cp)->minorct > baseminor))))


135 break;


136


137 /* Check for overlapping minor ranges. */


138 if (*cp && (*cp)->major == major) {


139 int old_min = (*cp)->baseminor;


140 int old_max = (*cp)->baseminor + (*cp)->m

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇基于ARM LPC2210的以太网RTL8019A.. 下一篇构建内核树

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目