当前位置:首页 > 操作系统课设
华 中 科 技 大 学 课 程 设 计 报 告
int (*fasync) (int, struct file *, int); //通知设备FASYNC标志发生变化 int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); int (*setlease)(struct file *, long, struct file_lock **); };
子功能函数详细代码见4.4.3。 (4) 设备驱动程序安装
① make clean,清除make产生的残留
② make,重新调用Makefile编译设备驱动程序
③ insmod -f MyDeviceDriver.ko,加载生成的 MyDeviceDriver.ko模块 ④ cat /proc/devices,获取设备驱动程序的主设备号
⑤mknod /dev/MyDeviceDriver c 250 0,创建设备文件,250为主设备号,0为从设备号
(5) 测试驱动程序
此设备驱动程序实现的功能是将一个字符串中内容拷贝到另外一个字符串中。测试程序编写完成后,在终端输入gcc test.c -o test进行编译。测试结果如下:
详细代码见4.3.3。 4.3.3 源代码
(1) 设备驱动程序
#include
16
华 中 科 技 大 学 课 程 设 计 报 告
#include
#define DEV_SIZE 102400 //设备申请的最大内存空间
struct Device {
char *data;//数组指针,用于存放从用户读入的数据 long size;//存储的数据长度 }*devp;
struct cdev cdev;//字符设备结构体
static int devNum_major = 0;//主设备号变量
//对应用户态的lseek
static loff_t my_llseek(struct file *file,loff_t offset, int whence) {
loff_t cfo=0;//文件当前偏移量,current file offset
switch(whence){ case 0://SEEK_SET cfo=offset;break; case 1://SEEK_CUR
cfo=file->f_pos+offset;break; case 2://SEEK_END
cfo=DEV_SIZE-1+offset;break; }
if ((cfo<0) || (cfo>DEV_SIZE))//文件偏移量越界 return -EINVAL; file->f_pos = cfo; return cfo; }
//对应用户态的read,写数据到用户空间
static ssize_t my_read(struct file *file, char __user *buf, size_t count, loff_t *p_cfo)
{
int val = 0;
struct Device *dev = file->private_data; //设备描述结构体指针,获取设备信息
if (copy_to_user(buf, (void*)(dev->data + *p_cfo), count))//如果成功返回0;如果失败,返回未完成copy的长度
17
华 中 科 技 大 学 课 程 设 计 报 告
val = -EFAULT; else { *p_cfo += count;//copy成功,文件偏移量加上count val = count; }
return val; }
//对应用户态的write,从用户空间读入数据
static ssize_t my_write(struct file *file, const char __user *buf, size_t count, loff_t *p_cfo)
{
int val = 0;
struct Device *dev = file->private_data;
if (copy_from_user(dev->data + *p_cfo, buf, count))//如果成功返回0;如果失败,返回未完成copy的长度
val = -EFAULT; else { *p_cfo += count;//copy成功,文件偏移量加上count val = count; }
return val; }
static int my_open(struct inode *inode, struct file *file) {
file->private_data = devp; return 0; }
struct file_operations fops={ .owner = THIS_MODULE, .llseek = my_llseek, .read = my_read, .write = my_write, .open = my_open, };
int init_module(void) {
int dev_num;
dev_num = register_chrdev(0,\ if (dev_num < 0) {
18
华 中 科 技 大 学 课 程 设 计 报 告
printk(KERN_INFO \ return dev_num; }
if (devNum_major == 0) devNum_major = dev_num;
//初始化cdev结构
cdev_init(&cdev, &fops);
cdev.owner = THIS_MODULE; cdev.ops = &fops;
cdev_add(&cdev,MKDEV(devNum_major, 0), 1);//注册1个字符设备
//为设备描述结构体分配内存
devp = kmalloc(sizeof(struct Device), GFP_KERNEL); if (!devp) { dev_num = -ENOMEM; printk(KERN_INFO \ return dev_num; }
(*devp).size = DEV_SIZE;
(*devp).data = kmalloc(DEV_SIZE, GFP_KERNEL); memset((*devp).data, 0, (*devp).size);//初始化为0
return 0; }
void cleanup_module(void) {
cdev_del(&cdev);//注销设备
kfree(devp);//注销设备结构体
kfree((*devp).data);//注销设备内存空间
unregister_chrdev(devNum_major,\卸载主设备号 }
MODULE_LICENSE(\(2) 驱动程序测试程序
#include
#define BUFFER_SIZE 102400 int main(void) {
int dev,i=0; char c;
char source[BUFFER_SIZE];//写入MyDeviceDriver设备的内容
char goal[BUFFER_SIZE]; //MyDeviceDriver设备的内容读入到该goal中 printf(\ while((c=getchar())!='\\n')
19
共分享92篇相关文档