获取另一个驱动的设备结构体_字符设备驱动的另一种写法
字符設(shè)備驅(qū)動(dòng)的另一種寫(xiě)法
在Linux2.6內(nèi)核中,使用cdev結(jié)構(gòu)體描述一個(gè)字符設(shè)備;
cdev結(jié)構(gòu)體(include/linux/cdev.h)定義如下:
struct cdev {
struct kobject kobj; /* 內(nèi)嵌的kobject對(duì)象 */
struct module *owner; /* 所屬模塊 */
const struct file_operations *ops; /* 文件操作結(jié)構(gòu)體 */
struct list_head list;
dev_t dev; /* 設(shè)備號(hào) */
unsigned int count;
};
cdev結(jié)構(gòu)體中的dev成員定義了設(shè)備號(hào),為32位,其中12位主設(shè)備號(hào),20位次設(shè)備號(hào);
使用下列宏可以從dev獲得主設(shè)備號(hào)和次設(shè)備號(hào),以及通過(guò)主設(shè)備號(hào)和次設(shè)備號(hào)生成dev_t,定義如下:
#define MINORBITS20
#define MINORMASK((1U << MINORBITS) - 1)
#define MAJOR(dev)((unsigned int) ((dev) >> MINORBITS)) /* 獲取主設(shè)備號(hào) */
#define MINOR(dev)((unsigned int) ((dev) & MINORMASK)) /* 獲取次設(shè)備號(hào) */
#define MKDEV(ma,mi)(((ma) << MINORBITS) | (mi)) /* 根據(jù)主次設(shè)備號(hào)生成dev*/
cdev結(jié)構(gòu)體中的另一個(gè)重要成員file_operations定義了字符設(shè)備驅(qū)動(dòng)提供給虛擬文件系統(tǒng)的接口函數(shù);
Linux2.6內(nèi)核提供了一組函數(shù)用于操作cdev結(jié)構(gòu)體,定義如下:
/* 用于初始化cdev的成員,并建立cdev和file_operation之間的連接 */
void cdev_init(struct cdev *, const struct file_operations *);
/* 用于動(dòng)態(tài)申請(qǐng)一個(gè)cdev內(nèi)存 */
struct cdev *cdev_alloc(void);
void cdev_put(struct cdev *p);
/* 向系統(tǒng)添加一個(gè)cdev,完成字符設(shè)備的注冊(cè) */
int cdev_add(struct cdev *, dev_t, unsigned);
/* 向系統(tǒng)刪除一個(gè)cdev,完成字符設(shè)備的注銷 */
void cdev_del(struct cdev *);
對(duì)于cdev_add()函數(shù)的調(diào)用通常發(fā)生在字符設(shè)備驅(qū)動(dòng)模塊加載函數(shù)中,向系統(tǒng)注冊(cè)一個(gè)字符設(shè)備,在此之前應(yīng)首先調(diào)用如下函數(shù)向系統(tǒng)申請(qǐng)?jiān)O(shè)備號(hào):
/* 用于已知起始設(shè)備的設(shè)備號(hào)的情況 */
int register_chrdev_region(dev_t from, unsigned count, const char *name);
或者:
/* 用于設(shè)備號(hào)未知,向系統(tǒng)動(dòng)態(tài)申請(qǐng)未被占用的設(shè)備號(hào)的情況 */
/* 調(diào)用該函數(shù)成功后,會(huì)把得到的設(shè)備號(hào)放入第一個(gè)參數(shù)dev中 */
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
const char *name);
對(duì)于cdev_del()函數(shù)從系統(tǒng)注銷字符設(shè)備之后,unregister_chrdev_region()應(yīng)該被調(diào)用以釋放原先申請(qǐng)的設(shè)備號(hào);
具體使用如下:
/* 定義一個(gè)dev_t類型變量 */
dev_t dev_id;
static struct cdev xxx_cdev;
static int major;
static const struct file_operations xxx_fops = {
.owner= THIS_MODULE,
.write= xxx_write,
.read= xxx_read,
.open= xxx_open
};
/* 設(shè)備驅(qū)動(dòng)模塊加載函數(shù) */
static int __init xxx_init(void)
{
if (major) { /* 如果已知主設(shè)備號(hào) */
dev_id = MKDEV(major, 0);
retval = register_chrdev_region(dev_id, 1, DEV_NAME);
} else {
retval = alloc_chrdev_region(&dev_id, 0, 1, DEV_NAME);
major = MAJOR(dev_id);
}
cdev_init(&xxx_cdev, &xxx_fops);
cdev_add(&xxx_cdev, dev_id, 1);
}
/* 設(shè)備驅(qū)動(dòng)模塊卸載函數(shù) */
static void __exit xxx_exit(void)
{
cdev_del(&xxx_cdev);
unregister_chrdev_region(dev_id, 1);
}
總結(jié)
以上是生活随笔為你收集整理的获取另一个驱动的设备结构体_字符设备驱动的另一种写法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: php是阻塞模式吗,PHP非阻塞模式 -
- 下一篇: Python学习笔记:I/O编程