前面寫到如何向系統(tǒng)申請(qǐng)一個(gè)設(shè)備號(hào),設(shè)備號(hào)就像我們的身份證號(hào)一樣,號(hào)本身并沒有什么特殊的意義,只有把這個(gè)號(hào)和人對(duì)應(yīng)才有意義,通用設(shè)備號(hào)也需要和一個(gè)特殊的東西對(duì)于,這就是cdev, cdev是linux下抽象出來(lái)的一個(gè)用來(lái)描述一個(gè)字符設(shè)備的結(jié)構(gòu)體,在linux下定義如下:
struct cdev {
struct kobject kobj;
struct module *owner;
const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
結(jié)構(gòu)體中有幾個(gè)成員事我們寫驅(qū)動(dòng)的時(shí)候必須關(guān)心的:
dev 類型是dev_t,也就是我們的設(shè)備號(hào)
ops是一個(gè)同樣也是一個(gè)結(jié)構(gòu)體并且是一個(gè)字符驅(qū)動(dòng)實(shí)現(xiàn)的主體,字符驅(qū)動(dòng)通常需要和應(yīng)用程序交互,在學(xué)linux系統(tǒng)編程的時(shí)候,都會(huì)講到linux 應(yīng)用程序通過(guò)系統(tǒng)調(diào)用陷入到內(nèi)核空間,從而執(zhí)行內(nèi)核代碼,而驅(qū)動(dòng)作為內(nèi)核的一部分同樣也是需要在內(nèi)核空間執(zhí)行的,ops也就是file_operations這個(gè)結(jié)構(gòu)體就是我們的驅(qū)動(dòng)為應(yīng)用程序調(diào)用驅(qū)動(dòng)而實(shí)現(xiàn)的一個(gè)操作的集合,它的定義如下:
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, loff_t, loff_t, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **);
long (*fallocate)(struct file *file, int mode, loff_t offset,loff_t len);
};
我們?cè)隍?qū)動(dòng)中要做的事情就是申請(qǐng)一個(gè)cdev并把cdev注冊(cè)到系統(tǒng)中去,操作cdev的函數(shù)有:
void cdev_init(struct cdev *, const struct file_operations *);
struct cdev *cdev_alloc(void);
int cdev_add(struct cdev *, dev_t, unsigned);
void cdev_del(struct cdev *);
1、cdev的定義
cdev的定義有兩種方式一種是:struct cdev cdev;另外一種是:strcut cdev cdev;cdev = cdev_alloc();
2、cdev的初始化
cdev_init實(shí)現(xiàn)cdev的初始化,主要的工作是將我們定義好的file_operaionts與cdev關(guān)聯(lián)起來(lái),file_operations的實(shí)現(xiàn)根據(jù)實(shí)際需求來(lái)實(shí)現(xiàn),后面詳細(xì)介紹。
3、cdev的注冊(cè)
cdev_add實(shí)現(xiàn)cdev的注冊(cè),linux內(nèi)核里維護(hù)了一個(gè)cdev_map的表,所謂cdev的注冊(cè)就是把我們的cdev注冊(cè)到cdev_map表上,cdev_map表結(jié)構(gòu)如圖:

4、設(shè)備的刪除
cdev_del 將我們的cdev從cdev_map中移除。