Linux之设备驱动学习简过程<二>

 简单字符驱动和高级字符驱动实现知识概览。。。学习驱动真累,看了这么多资料,,,还是头绪飘渺,,,但是我还是相信学习的过程是曲折的,坚持就是胜利。So,come on! I like linux ,as like life!

1.内核模块编译进内核:

主要修改 Kconfig/Makefile

2.设备号作用
.主设备号:用来反映设备类型
.次设备号:区分同类型的设备

3.主次设备号实现
dev_t MKDEV(ma,mi)--创建设备号

MAJOR(dev_t dev)--主设备号

MINOR(dev_t dev)--次设备号

4.分配主设备号

a--静态分配

. int register_chrdev_region(dev_t first, unsigned int count, char *name)
.查看已被分配的主设备号 Documentation/devices.txt

b--动态分配

. int alloc_chrdev_region(dev_t *dev,unsigned int firstminor,unsigned int count,char *name)

动态分配的设备号,可以从/proc/devices中取到

c--注销设备号
. void unregister_chrdev_region(dev_t first, unsigned int count)

5.创建设备文件
mknod filename type major minor


6.三个重要的内核数据结构
struct file_operations,struct file,struct inode

7.字符设备的注册步骤(字符设备使用struct cdev来描述)
a--.分配 struct cdev *cdev_alloc(void)
b--.初始化 void cdev_init(struct cdev *cdev,const struct file_operations *fops)

*fops设备对应的操作函数集

c--.添加 int cdev_add(struct cdev *p, dev_t dev,unsigned count)
d--.注销 int_del(struct cdev *p)

8.合理使用Printk
.全局关闭/打开

9.并发控制

--信号量使用(<asm/semaphore.h)
.定义信号量 struct semaphore sem;
.初始化信号量 void sema_init(struct semaphore *sem,int val)

 

--初始化一个互斥锁,把信号量值设为1 :void init_MUTEX(struct semaphore *sem)
                      把信号量值设为0 :void init_MUTEX_LOCKED(struct semaphore *sem)
*DECLARE_MUTEX(name)
*DECLARE_MUTEX_LOCKED(name)

.获取信号量
---void down(struct semaphore *sem)
---int down_interruptible(struct semaphore *sem)
---down_killable(struct semaphore *sem) 

.释放信号量 void up(struct semaphore *sem)

-----自旋锁
*spin_lock_init(x)
*spin_lock(lock)
*spin_trylock(lock)
*spin_unlock(lock)

10.驱动ioctl方法

int (*ioctl)(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)

--ioctl(Type--幻数/Number--第几个命令/Direction--_IOC_NONE _IOC_READ _IOC_WRITE/Size--用户

数据大小)
*定义命令
_IO(type,nr)/_IOR(type,nr,datatype)/_IOW(type,nr,datatype)/_IOWR(type,nr,datatype)
*实现命令
--返回值(每个命令对应才正确,不对应返回-EINVAL)
--参数 int access_ok(int type,const void *addr,unsigned long size)
--命令操作

11.等待队列(阻塞型字符设备驱动)
*定义等待队列
wait_queue_head_t my_queue
*初始化等待队列
init_waitqueue_head(&my_queue)
*定义并初始化
DECLARE_WAIT_QUEUE_HEAD(my_queue)
*有条件睡眠
wait_event(queue,condition) -----TASK_UNINTERRUPTIBLE
wait_event_interruptible(queue,condition)-----TASK_INTERRUPTIBLE
int wait_event_killable(wait_queue_t queue,condition)-----TASK_KILLABLE

*无条件睡眠
sleep_on(wait_queue_head_t *q)
interruptible_sleep_on(wait_queue_head_t *q)

*从等待队列中唤醒进程
wake_up(wait_queue_t *q) ----唤醒状态为TASK_UNINTERRUPTIBLE、TASK_INTERRUPTIBLE、

TASK_KILLABLE
wake_up_interruptible(wait_queue_t *q)----TASK_INTERRUPTIBLE

驱动程序不是进程,而是一个函数。。。??

12.Select 系统调用--多路监控
int select(int maxfd,fd_set *readfds,fd_set *writefds,fe_set *exceptfds,const struct

timeval *timeout)

驱动实现:unsigned int(*poll)(struct file *filp,poll_table *wait)
*把进程添加到等待队列 poll_wait
*返回掩码---设备可读(POLLIN|POLLRDNORM)/设备可写(POLLOUT|POLLWRNORM)

13.自动创建设备文件
*devfs_register(devfs_handle_t dir,const char *name,unsigned int flags,unsigned int

major,unsigned int minor,umode_t mode,void *ops,void *info)--------2.4内核

*struct class *myclass = class_create(THIS_MODULE,"my_device_driver");
 device_create(myclass,NULL,MKDEV(major_num,0),NULL,"my_device");
udev/mdev---------2.6内核

你可能感兴趣的:(Linux之设备驱动学习简过程<二>)