cdev结构体及其相关函数

一、在Linux2.6内核中一个字符设备用cdev结构来描述,其定义如下:

1 struct cdev {
2         struct kobject kobj;
3         struct module *owner;   //所属模块
4         const struct file_operations *ops;         //文件操作结构,在写驱动时,其结构体内的大部分函数要被实现
5         struct list_head list;
6         dev_t dev;          //设备号,int 类型,高12位为主设备号,低20位为次设备号
7         unsigned int count;
8 }; 

可以使用如下宏调用来获得主次设备号:
MAJOR(dev_t dev) 
MINOR(dev_t dev) 
MKDEV(int major,int minor) //通过主次设备号来生成dev_t

以上宏调用在内核源码中如此定义:

1 #define MINORBITS       20
2 #define MINORMASK       ((1U << MINORBITS) - 1)         //(1<<20 -1) 此操作后,MINORMASK宏的低20位为1,高12位为0
3 #define MAJOR(dev)      ((unsigned int) ((dev) >> MINORBITS))
4 #define MINOR(dev)      ((unsigned int) ((dev) & MINORMASK))
5 #define MKDEV(ma,mi)    (((ma) << MINORBITS) | (mi))

二、下面一组函数用来对cdev结构体进行操作:

1 void cdev_init(struct cdev *, const struct file_operations *);//初始化,建立cdev和file_operation 之间的连接
2 struct cdev *cdev_alloc(void); //动态申请一个cdev内存
3 void cdev_put(struct cdev *p);   //释放
4 int cdev_add(struct cdev *, dev_t, unsigned);  //注册设备,通常发生在驱动模块的加载函数中
5 void cdev_del(struct cdev *);//注销设备,通常发生在驱动模块的卸载函数中

1)如果希望在运行时动态的获得一个独立的 cdev 结构,有两种方法可以分配并初始化 cedv 结构。

 1 struct cdev *my_cdev = cdev_alloc();
 2     my_cdev->ops = &my_fops;
 3
 4     struct cdev *cdev_alloc(void)
 5     {
 6         struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);
 7         if (p) {
 8             INIT_LIST_HEAD(&p->list);
 9             kobject_init(&p->kobj, &ktype_cdev_dynamic);
10         }
11         return p;
12     }

2)有时可能希望就把 cdev 结构内嵌在自己的特定设备结构里,那么在分配好 cdev 结构后,就用 cdev_init() 函数对其初始化:

1 void cdev_init(struct cdev *cdev, const struct file_operations *fops)
2 {
3     memset(cdev, 0, sizeof *cdev);
4     INIT_LIST_HEAD(&cdev->list);
5     kobject_init(&cdev->kobj, &ktype_cdev_default);
6     cdev->ops = fops;
7 }

3)注册与注销:像cdev 中的owner 要设置为 THIS_MOULE ,在注册时应该先调用:
int register_chrdev_region(dev_t from,unsigned count,const char *name)函数为其分配设备号,此函数可用:

int alloc_chrdev_region(dev_t *dev,unsigned baseminor,unsigned count,const char *name)函数代替,他们之间的区别在于:register_chrdev_region()用于已知设备号时,另一个用于动态申请,其优点在于不会造成设备号重复的冲突。 
在注销之后,应调用:void unregister_chrdev_region(dev_t from,unsigned count)函数释放原先申请的设备号。 
他们之间的顺序关系如下: 
register_chrdev_region()-->cdev_add()     //此过程在加载模块中 
cdev_del()-->unregister_chrdev_region()     //此过程在卸载模块中

参考原文:http://bbs.ednchina.com/BLOG_ARTICLE_1897586.HTM

时间: 2024-10-11 20:51:23

cdev结构体及其相关函数的相关文章

驱动学习之register_chrdev_region函数和cdev结构体

1:register_chrdev_region int register_chrdev_region(dev_t from, unsigned count, const char *name) {     struct char_device_struct *cd;     dev_t to = from + count;     dev_t n, next;     for (n = from; n < to; n = next) {         next = MKDEV(MAJOR(n

Linux中表示“时间”的结构体和相关函数

转载于:http://blog.chinaunix.net/uid-25909722-id-2827364.html Linux中表示“时间”的结构体和相关函数 2011-09-13 17:01:13 分类: C/C++ 在Linux系统中,表示“时间”概念的结构体有多个,相关的时间处理函数也有很多,给人以很混乱的感觉.导致了当我们真正要使用这些结构体和函数的时候,却不知道到底该用哪个结构体和哪些函数.有必要加以归纳总结一下.通过查看头文件/usr/include/time.h 和 /usr/i

struct list_head结构体及相关函数

struct list_head结构体是linux实现数据结构双向链表的基础.其定义: struct list_head { struct list_head *next, *prev; }; 可见链表里面的成员还是链表,每个链表都指向了前面和后面的链表. 一般将struct list_head作为一个成员,放到一个结构体中,其作用是可以从当前的结构体指针,获取到下一个链表元素的地址.一般用list_entry()来实现.具体按照下面的链接: http://www.cnblogs.com/bas

Linux字符设备中的两个重要结构体(file、inode)

对于Linux系统中,一般字符设备和驱动之间的函数调用关系如下图所示 上图描述了用户空间应用程序通过系统调用来调用程序的过程.一般而言在驱动程序的设计中,会关系 struct file 和 struct inode 这两个结构体. 用户空间使用open()系统调用函数打开一个字符设备时( int fd = open("dev/demo", O_RDWR) )大致有以下过程: 在虚拟文件系统VFS中的查找对应与字符设备对应 struct inode节点 遍历字符设备列表(chardevs

20150220 IMX257 linux设备驱动之Cdev结构

20150220 IMX257 linux设备驱动之Cdev结构 2015-02-20 21:17 李海沿 一.CDEV结构 /*   *内核源码位置   *linux2.6.38/include/linux/cdev.h   */        struct cdev {       struct kobject kobj;       struct module *owner;   //一般初始化为:THIS_MODULE       const struct file_operations

inode结构体

inode分为内存中的inode和文件系统中的inode,为了避免混淆,我们称前者为VFS inode, 而后者以EXT2为代表,我们称为Ext2 inod.这里说明的是VFS inode. 重要成员: 1. struct cdev *i_cdev; 若是字符设备,为其对应的cdev结构体指针. 2. struct block_device *i_bdev; 若是块设备,为其对应的block_device结构体指针 3. dev_t i_rdev; 若是设备文件,此成员记录设备的设备号 1 st

字符设备驱动之结构体

https://blog.csdn.net/tigerjibo/article/details/6412469 大部分驱动程序操作都涉及到三个重要的内核数据结构,分别是file_operations.file和inode,它们定义在<linux/fs.h> 1.file_operations:是一个函数指针的集合 1>应用程序和VFS之间的接口是系统调用,而VFS与磁盘文件系统以及普通设备之间的接口是file_operations结构体成员函数.file_operations结构体中成员

C语言_相关函数与结构体

字符串相关函数 //了解 #include<ctype.h> 1. int isalpha(int c); //判断一个字符是否是字母. 2. int isnumber(int c); //判断一个字符是否是表示数字的字符. 3. int isupper(int c); //判断一个字符是否是表示大写字母的字符 4. int islower(int c); //判断一个字符是否是小写字母. 5. int toupper(int c): //将字符转换为大写字母. 6. int tolower(

APUE学习笔记——4.2结构体 struct stat 及其相关函数介绍

以下不少内容来自man手册 结构体struct stat 结构体struct stat用于保存文件相关的所有信息. struct stat的基本成员如下所示 struct stat { dev_t st_dev; // 文件所在设备的设备id,可以分解为主设备号和此设备号 ino_t st_ino; // inode号 mode_t st_mode; // 文件的类型.存取权限等 nlink_t st_nlink; // 文件硬连接数 uid_t st_uid; // 文件拥有者的用户id gi