linux2.6字符驱动(一)

关于字符设备的基础知识:

 对于字符驱动程序来说,首先要注册一个设备号,设备号包括主设备和次设备,一般来讲,主设备标志与设备相对应的驱动程序,而次设备则是被内核用来标志所指向是那个设备。内核除了知道次设备指向驱动所对应的设备外,对于次设备其它的一无所知。
如果事先就知道你要注册的设备号,你可以使用宏MKDEV(  )来生成设备号,结构是dev_t, 以后就可以通过MAJOR( )和MINOR可以查看相应的主设备和次设备

MKDEV(int major, int minor);
MAJOR(dev_t dev);
MAJOR(dev_t  dev);

定义好设备号后并且想让他工作的话就必须让内核知道,这里首先要了解几个函数和数据结构

int register_chrdev_region(dev_t first , unsigned int count , char* name );
first 是你想注册的设备号,其中的minor一般为0,count为你设备号临近的设备号的总和,这里需要注意的是,如果count设置的比较大的话,可能使得设备号的major超出你开始分配的major number。name为设备的名称,将会出现在/proc/divices中。注册成功的话将会将会返回0。

一般而言,开发着一般都不能确定主设备应该选择什么,如果是这样的话,可以使用下个这个函数
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char* name);
这个函数可以动态分配主设备,count 和name与上面那个函数的含义一样,firstminor为需要使用的第一个次设备号,通常为0,使用这个函数后,dev为内核为你分配的设备号,可以通过上面的二个宏来获得主设备和次设备号。然而使用这个函数也有个缺点,即不能事先创建设备节点,也就是说不能/dev显示出相应的设备。不过可以通过读取/proc/devices来创建。
下面是几个重要的数据结构file_operations, file, inode
file_operations是一个字符设备把驱动的操作和设备号联系在一起的纽带,是一系列指针的集合,每个被打开的文件都对应于一系列的操作,这就是file_operations,用来执行一系列的系统调用。

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 (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
        ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);//同步读
        ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
             ......
}

file代表一个打开的文件,在执行file_operation中的open操作时被创建,这里需要注意的是与用户空间file指针的区别,一个在内核,而file指针在用户空间,由c库来定义。

struct file {
        struct list_head        f_list;
        struct dentry           *f_dentry;
        struct vfsmount         *f_vfsmnt;
        struct file_operations  *f_op;   //这就是上面所说的file_oeprations
        atomic_t                f_count;
        unsigned int            f_flags;
        mode_t                  f_mode;   //文件是否可读、可写
        int                     f_error;
        loff_t                  f_pos;      //当前读写位置
        struct fown_struct      f_owner;
        unsigned int            f_uid, f_gid;
        struct file_ra_state    f_ra;

        unsigned long           f_version;
        void                    *f_security;

        /* needed for tty driver, and maybe others */
        void                    *private_data;    

#ifdef CONFIG_EPOLL
        /* Used by fs/eventpoll.c to link all the hooks to this file */
        struct list_head        f_ep_links;
        spinlock_t              f_ep_lock;
#endif /* #ifdef CONFIG_EPOLL */
        struct address_space    *f_mapping;
};
inode被内核用来代表一个文件,注意和file的区别,一个是代表文件,一个是代表打开的文件
inode包括很重要的二个成员:
dev_t i_rdev   设备文件的设备号
struct cdev *i_cdev  代表字符设备的数据结构
Inode结构是用来在内核内部表示文件的.同一个文件可以被打开好多次,所以可以对应很多struct file,但是只对应一个struct inode

好了,现在可以注册字符设备了

可以有两种方法注册
    struct cdev *my_cdev=cdev_alloc();
    my_cdev->ops=&my_fops;

    void cdev_init(struct cdev *cdev,struct file_operations *fops);

注册完后还要通知内核一声,通过调用
    int cdev_add(struct cdev *dev,dev_t num,unsigned int count);
count 一般是 1.

删除字符设备,调用
    void cdev_del(struct cdev *dev);
参考资料
驱动读书笔记
Linux Device Driver 3rd Edition
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值