3. 0644 访问权限(下面文件)
2. 加载模块时,传参方法: insmod test.ko num=1234
num = 1234
3. cat /sys/module/test/parameters/num
1234
十. 字符设备:
1. dev_t devno; ---> 设备号,设备的身份证号码
1. 高12位: 主设备号
2. 低20位: 次设备号
2. 设备号操作辅助宏
1. major = MAJOR(devno);
2. minor = MINOR(devno);
3. devno = MKDEV(major, minor);
3. 查看当前系统中注册的所有设备
cat /proc/devices
4. 手动创建设备节点
1. mknod /dev/test0 c 250 0
2. ls /dev/test0 -l
crw-r--r-- 1 0 0 250, 0 Jan 1 15:31 /0
十一. 2种字符设备注册:
字符设备底层接口实现linux-3.5/fs/char_dev.c
1. static inline int register_chrdev(unsigned int major, const char *name,
const struct file_operations *fops)
{
//该函数调用了下面的3步注册方式
return __register_chrdev(major, 0, 256, name, fops);
}
2. 3步详细注册:
1. struct cdev cdev; //char device
2. 分配设备号,有2种方式:
1. 动态分配设备号
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
2. 静态指定设备号
int register_chrdev_region(dev_t from, unsigned count, const char *name)
3. 初始化cdev结构
cdev_init();
4. 添加cdev到系统中
cdev_add();
十二. 驱动中常见的3种结构体:
1. struct file_operations; //每个驱动对应一个
2. struct inode *inode; //每个文件对应一个
3. struct file *file; //文件每打开一次,对应一个file结构维护着打开文件的相关信息
1. loff_t f_pos; //文件指针
3. unsigned int f_flags; //文件访问标志
十三. 内核空间与用户空间之间拷贝数据:
#include 1. copy_to_user(); 2. copy_from_user(); 成功返回0,失败返回未完成拷贝的字节数 十四. 驱动被调用函数流程: 1. 文件IO系统调用 ---> VFS(虚拟文件系统层) ---> 设备驱动 2. 系统调用入口定义:arch/arm/kernel/calls.S 1. open系统调用对应的内核入口:sys_open,该函数在VFS实现对应源文件fs/open.c; 2. sys_open函数定义: SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode) 3. 关键函数调用do_sys_open(); 3. 跟踪该函数do_sys_open(),通过get_unused_fd_flags()返回一个可用的文件描述符, 关键函数调用do_filp_open(); 4. 跟踪该函数do_filp_open(), 关键函数调用path_openat(); 5. 跟踪该函数path_openat(); 关键函数调用do_last(); 6. 跟踪该函数do_last(); 关键函数调用nameidata_to_filp(); 7. 跟踪该函数nameidata_to_filp(); 1. 关键函数调用do_dentry_open(); 2. 关键步骤: //把文件inode的file_operations 保存在file结构里 f->f_op = fops_get(inode->i_fop); if (!open && f->f_op) open = f->f_op->open; if (open) { //调用file_operations的open成员函数 error = open(inode, f); if (error) goto cleanup_all; } 3. 那2中的inode里的i_fop是哪里来的 1. linux-3.5/fs/inode.c 2. 初始化inode结构的i_fop,调用init_special_inode函数: void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev) { inode->i_mode = mode; if (S_ISCHR(mode)) { //如果是字符设备,使用def_chr_fops 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; } else if (S_ISFIFO(mode)) inode->i_fop = &def_fifo_fops; else if (S_ISSOCK(mode)) inode->i_fop = &bad_sock_fops; else printk(KERN_DEBUG 'init_special_inode: bogus i_mode (%o) for' ' inode %s:%lun', mode, inode->i_sb->s_id, inode->i_ino); } 3. 如果是字符设备,使用def_chr_fops: const struct file_operations def_chr_fops = { .open = chrdev_open, .llseek = noop_llseek, }; 4.接下来,跟踪chrdev_open()函数 static int chrdev_open(struct inode *inode, struct file *filp) { struct cdev *p; struct cdev *new = NULL; int ret = 0; spin_lock(&cdev_lock); p = inode->i_cdev; if (!p) { struct kobject *kobj; int idx; spin_unlock(&cdev_lock); //找到之前注册的字符设备时添加的cdev结构的kobj kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx); if (!kobj) return -ENXIO; //通过container_of获取cdev结构的地址 new = container_of(kobj, struct cdev, kobj); spin_lock(&cdev_lock); /* 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; } else if (!cdev_get(p)) ret = -ENXIO;
上一篇:Samsung_tiny4412(驱动笔记04)----volatile,container_of,file_operations,file,inode
下一篇:Samsung_tiny4412(驱动笔记01)----linux 3.5,U-Boot,Busybox,SD卡启动环境搭建
推荐阅读最新更新时间:2026-02-18 18:28
- 羽毛球训练监测器
- 一种 16 位、300 kSPS 低功耗逐次逼近 ADC 系统,具有用于高达 4 kHz 的亚奈奎斯特输入信号的最佳低功耗驱动放大器
- SY898547 EV,用于 SY89547、2.5V、3.2 Gbps LVDS 多路复用器的评估板,带内部终端
- OP484ESZ-REEL 2.5V 基准的典型应用在单 3V 电源上运行
- NCV3063 1.5A 电压反相稳压器的典型电压反相应用原理图
- 具有欠压锁定功能的 LT3973IDD-3.3 5V 降压转换器的典型应用
- NSI45030ZT1G 单串LED恒流LED驱动器的典型应用
- NCP1587A 低压同步降压控制器的典型应用
- 福禄克早期型号 8020A 万用表原理图
- 使用 Richtek Technology Corporation 的 RT8237C 的参考设计



Linux内核驱动笔记
三星2410开发板ALLEGRO BRD原文件
非常经典的关于LLC的杨波博士论文
VI-27WIU






京公网安备 11010802033920号