文档介绍:设计自己的驱动程序
实验目的:
通过一个简单的设备驱动的实现过程。学会 Linux 中设备驱动程序的编写,
实验内容:
设计和实现一个虚拟命名管道(FIFO)的字符设备。写一个模块化的字符设备驱动程序
实验提示:
一、设备的功能
设计和实现一个虚拟命名管道(FIFO)的字符设备。我们知道,管道是进程间通信的一种
方式:一个进程向管道中写数据,另一个进程从管道中读取数据,先写入的数据先读出。我
们的驱动程序要实现 N(N=4)个管道,每个管道对应两个设备,次设备号是偶数的设备是只
写设备,次设备号是奇数的是只读设备。写入设备 i(i 是偶数)的字符可以从设备 i+1 读出。
这样,我们一共就需要 2N 个次设备号。
我们的目标是写一个模块化的字符设备驱动程序。设备所使用的主设备号可以从尚未分
配的主设备号中任选一个,/Documentation/ 记录了当前版本内核的主设备号分配
情况。如果设备文件系统(devfs)尚未激活,我们在加载模块之后,还必须用 mknod 命令创
建相应的设备文件节点。
如果 FIFO 的写入端尚未打开,FIFO 中就不会有数据可读,所以此时试图从 FIFO 中读
取数据的进程应该返回一个错误码。如果写入端已经打开,为了保证对临界区的互斥访问,
调用读操作的进程必须被阻塞。如果存在被阻塞的读者,在写操作完成后(或者关闭一个写
设备时)必须唤醒它。
如果写入的数据太多,超出了缓冲区中空闲块的大小,调用写操作的进程必须睡眠,以
等待缓冲区中有新的空闲块。
二、设备的实现
1. 数据结构:
首先,我们要包含一些必要的头文件、宏和全局变量。
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#define __NO_VERSION__
#include<linux/>
#include<linux/>
#include<linux/>
#include<linux/>
#include<linux/>
#include<linux/>
#include<linux/>
#include<linux/>
#include<linux/>
#include<linux/>
#include<asm/>
#include<asm/>
#ifndef VFIFO_MAJOR
#define VFIFO_MAJOR 241
#endif
#ifndef VFIFO_NR_DEVS
#define VFIFO_NR_DEVS 4
#endif
#ifndef VFIFO_BUFFER
#define VFIFO_BUFFER 4000
#endif
#include<linux/>
devfs_handle_t vfifo_devfs_dir;
struct file_operations vfifo_fops;
int vfifo_major=VFIFO_MAJOR;
int vfifo_nr_devs=VFIFO_NR_DEVS;
int vfifo_buffer=VFIFO_BUFFER;
MODULE_PARM(vfifo_major,"i");
MODULE_PARM(vfifo_nr_devs,"i");
MODULE_PARM(vfifo_buffer,"i");
MODULE_AUTHOR("EBUDDY");
每个实际的 FIFO 设备都对应于一个 Vfifo_Dev{ }结构体。其中,rdq 是阻塞读的等待
队列,wrq 是阻塞写的等待队列,base 是所分配缓冲区的起始地址,buffersize 是缓冲区的
大小,len 表示管道中已有数据块的长度,start 表示当前应该读取的缓冲区位置相对于 base
的偏移量,即缓冲区起始数据的偏移量,readers 和 writers 分别表示 VFIFO 设备当前的读者
个数和写者个数,sem 是用于互