气质,源于心灵的自信!
全部博文(204)
分类: Android平台
2013-03-08 17:07:34
自己写的一个小总结,主要是看了《深入linux设备驱动程序机制》和http://blog.chinaunix.net/uid-20543672-id-3203690.html
/*字符设备号管理结构*/
#define CHRDEV_MAJOR_HASH_SIZE 255
static struct char_device_struct {
struct char_device_struct *next;
unsigned int major;
unsigned int baseminor;
int minorct;
char name[64];
struct cdev *cdev; /* will die */
} *chrdevs[CHRDEV_MAJOR_HASH_SIZE];
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 = 128; n < 130; n = next) {
next = MKDEV(MAJOR(n)+1, 0);
if (next > to)
next = to;
cd = __register_chrdev_region(MAJOR(n), MINOR(n),
next - n, name);
if (IS_ERR(cd))
goto fail;
}
return 0;
}
/*动态分配*/
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
const char *name)
{
struct char_device_struct *cd;
cd = __register_chrdev_region(0, baseminor, count, name);
if (IS_ERR(cd))
return PTR_ERR(cd);
*dev = MKDEV(cd->major, cd->baseminor);
return 0;
}
/*字符设备cdev的管理,和字符设备号相同过的管理方法*/
static struct kobj_map *cdev_map;
struct kobj_map {
struct probe {
struct probe *next;
dev_t dev;
unsigned long range;
struct module *owner;
kobj_probe_t *get;
int (*lock)(dev_t, void *);
void *data;//指向注册的cdev
} *probes[255];
struct mutex *lock;
};
int cdev_add(struct cdev *p, dev_t dev, unsigned count)
{
p->dev = dev;
p->count = count;
return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
}
//下面是用户空间到驱动空间的交互过程
/******************************************************************/
struct task_struct {
........
/* open file information */
struct files_struct *files;
.........
}
struct files_struct {
....
struct fdtable fdtab;
......
};
struct fdtable {
unsigned int max_fds;
struct file __rcu **fd; /* 文件描述符数组 */
fd_set *close_on_exec;
fd_set *open_fds;
struct rcu_head rcu;
struct fdtable *next;
};
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode)
do_sys_open(AT_FDCWD, filename, flags, mode);
fd = get_unused_fd_flags(flags);//获得一个未用的fd,作为struct file __rcu **fd;的索引值
if(fd > 0)
{
/*找一个空的file,放入fd指向的空间中*/
struct file *f = do_filp_open(dfd, tmp, &op, lookup);
filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU);// 分配filep
filp = do_last(nd, &path, op, pathname);
filp = nameidata_to_filp(nd);
filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp, NULL, cred);
inode = dentry->d_inode;//查找到该设备节点对应的inode
f->f_op = fops_get(inode->i_fop);//取出inode的的默认操作函数,赋值给file
if (!open && f->f_op)
open = f->f_op->open;//调用该默认操作的open函数
if (open) {
error = open(inode, f);//默认的open函数如下
if (error)
goto cleanup_all;
}
}
/*字符设备的操作函数*/
const struct file_operations def_chr_fops = {
.open = chrdev_open,
.llseek = noop_llseek,
};
/*特定的文件系统调用该函数*/
void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
{
inode->i_mode = mode;
if (S_ISCHR(mode)) {//如果是字符设备
inode->i_fop = &def_chr_fops;//字符设备的操作函数
inode->i_rdev = rdev;
} else if (S_ISBLK(mode)) {
inode->i_fop = &def_blk_fops;
inode->i_rdev = rdev;
}
...........
}
//下面接着分析chrdev_open函数
static int chrdev_open(struct inode *inode, struct file *filp)
{
struct cdev *p;
struct cdev *new = NULL;
if (!p) {
struct kobject *kobj;
kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);//由创建节点的主设备号i_rdev,查找到对应的probes
new = container_of(kobj, struct cdev, kobj);
/* Check i_cdev again in case somebody beat us to it while
we dropped the lock. */
p = inode->i_cdev;
if (!p) {
inode->i_cdev = p = new;
list_add(&inode->i_devices, &p->list);
new = NULL;
}
filp->f_op = fops_get(p->ops);//把驱动的操作赋值给file的操作函数
if (filp->f_op->open) {//调用驱动个的open函数
ret = filp->f_op->open(inode,filp);
if (ret)
goto out_cdev_put;
}
}
}