设为首页 加入收藏

TOP

Linux设备驱动工程师之路——高级字符设备驱动程序
2014-11-24 11:55:09 来源: 作者: 【 】 浏览:1
Tags:Linux 设备驱动 工程师 高级 字符 设备 驱动程序

高级字符设备驱动在简单字符驱动的基础上添加ioctl方法、阻塞非阻塞读写、poll方法、和自动创建设备文件的功能。


一、重要知识点


1.ioctl


ioctl命令:使用4个字段定义一个ioctl命令,包括


type: 幻数,一般使用一个字符定义,在内核中唯一。


number: 序数。


direction: 数据传输方向,当不涉及数据传输时,此字段无效。


size: 所涉及用户数据的大小,当不涉及数据传输时,此字段无效。


_IOC_NONE


_IOC_READ


_IOC_WRITE


“方向”字段的可能值。“读”和“写”是不同的位,可以用“OR”在一起指定读写。


_IOC(dir, type, size)


_IO(type,nr)


_IOR(type, nr, size)


_IOW(type, nr, size)


用于生产ioctl命令的宏


_IOC_DIR(cmd)


_IOC_TYPE(cmd)


_IOC_NR(cmd)


_IOC_SIZE(cmd)


用于解码ioctl命令的宏


intaccess_ok(int type, const void *addr, unsigned long size)


这个函数验证指向用户空间的指针是否可用,如果允许访问,access_ok返回非0值。


int put_user(datum, ptr)


int get_user(local, ptr)


int __put_user(datum, ptr)


int __get_user(local, ptr)


用于向(或从)用户空间保存(或获取)单个数据项的宏。传送的字节数目由sizeof(*ptr)决定。前两个要先调用access_ok,后两个(__put_user和__get_user)则假设access_ok已经被调用过了。



2.阻塞型I/O


typedef struct {/*…..*/} wait_queue_head_t


void init_waitqueue_head(wait_queue_head_t*queue)


DECLARE_WAIT_QUEUE_HEAD(queue)


预先定义的Linux内核等待队列类型。wait_queue_head_t类型必须显示地初始化,初始化方法可以在运行时调用init_waitqueue_head,或在编译时DECLARE_WAIT_QUEUE_HEAD。


void wait_event((wait_queue_head_t q, intcondition)


int wait_event_interruptible(wait_queue_head_tq, int condition)


int wait_event_timeout(wait_queue_head_t q,int condition, int time)


int wait_event_interruptible_timeout(wait_queue_head_tq, int condition, int time)


使进程在指定的队列上休眠,直到给定的condition值为真。


void wake_up(struct wait_queue **q)


void wake_up_interruptible(structwait_queue **q)


这些函数唤醒休眠在队列q上的进程。_interruptible形式的函数只能唤醒可中断的进程。在实践中约定做法是在使用wait_event时用wake_up,而在使用wait_event_interruptible时使用wake_up_interruptible。



3.poll方法


poll方法分两步处理,第一步调用poll_wait指定等待队列,第二步返回是否可操作的掩码。


POLLIN表示设备可读的掩码,POLLRDORM表示数据可读的掩码。POLLOUT表示设备可写的掩码,POLLWRNORM表示数据可读的掩码。一般同时返回POLLIN和POLLRDORM或者POLLOUT和POLLWRNORM。



4.select系统调用


原型为intselect(int mafdp1, fd_set *restrict readfds, fd_set *restrict writefds, fd_set*restrict exceptfds, struct timeva l *restrict tvptr)


返回值:就绪的描述符数,若超时则返回0,若出错则返回-1


void FD_ISSET(int fd, fd_set *fdset)


void FD_CLR(int fd, fd_set *fdset)


void FD_SET(int fd, fd_set *fdset)


void FD_ZERO(fd_set *fdset)


调用FD_ZERO将一个指定的fd_set变量的所有位设置为0。调用FD_SET设置一个fd_set变量指定位。调用FD_CLR则将一指定位清除。最后,调用FD_ISSET测试一指定位是否设置。


5.自动创建设备文件


struct class *class_create(struct module*owner, const char *name)


struct device *device_create(struct class*class, struct device *parent, dev_t devt, const char *fmt, ...)


通过这两个函数可以专门用来创建一个字符设备文件节点,class_create 第一个参数指定所有者,第二参数指定类得名字。class_device_create第一个参数指定第一个参数指定所要创建的设备所从属的类,第二个参数是这个设备的父设备,如果没有就指定为NULL,第三个参数是设备号,第四个参数是设备名称。


二、驱动代码


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Linux设备驱动工程师之路——Linu.. 下一篇Linux设备驱动工程师之路——简单..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·如何从内核协议栈到 (2025-12-27 03:19:09)
·什么是网络协议?有哪 (2025-12-27 03:19:06)
·TCP/ IP协议有哪些 (2025-12-27 03:19:03)
·怎样用 Python 写一 (2025-12-27 02:49:19)
·如何学习python数据 (2025-12-27 02:49:16)