广州大学学生实验报告
开课学院及实验室:计算机科学与工程实验室 2018 年 6月 16日
学院 | 计算机科学与教育软件学院 | 年级/专业/班 | 网工152班 | 姓名 | 学号 | ||
实验课程名称 | Linux操作系统分析实验 | 成绩 | |||||
实验项目名称 | 实验五 设备驱动: Linux系统下的字符设备驱动程序编程 | 指导老师 | 陶文正 | ||||
一、实验目的
通过一个简单的设备驱动的实现过程。学会Linux中设备驱动程序的编写
二、使用仪器、器材
1.设备:带网卡的PC若干、交换机一台。
2.工具:网线若干,已经安装好Red Hat Linux 9。0系统的PC一台。
三、实验内容及原理
设计和实现一个虚拟命名管道(FIFO)的字符设备。写一个模块化的字符设备驱动程序
四、实验过程
(1)设备的实现
1、数据结构
/*vfifo.c*/
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#define __NO_VERSION__
#include〈linux/config。h>
#include〈linux/module。h>
#include<linux/kernel.h〉
#include〈linux/malloc。h〉
linux重定向#include〈linux/fs。h〉
#include<linux/proc_fs。h〉
#include<linux/errno.h〉
#include<linux/types。h〉
#include〈linux/fcntl。h>
#include〈linux/init。h〉
#include〈asm/system.h〉
#include<asm/uaccess.h〉
#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_fs_kernel。h〉
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”);
结构体
/*vfifo。c*/
typedef struct Vfifo_Dev{
wait_queue_head rdq,wrq;
char* base;
unsigned int buffersize;
unsigned int len;
unsigned int start;
unsigned int readers,writers;
struct semaphore sem;
devfs_handle_t r_handle,w_handle;
}Vfifo_Dev;
2、设备操作接口
A、注册与注销
/*vfifo.c*/
char vfifoname[8];
static int __init vfifo_init_module(void)
{
int result,i;
SET_MODULE_OWNER(&vfifo_fops);
#ifdef CONFIG_DEVFS_FS vfifo_devfs_dir=devfs_mk_dir(NULL,”vfifo”,NULL); if(!vfifo_devfs_dir) return -EBUSY;
#endif result=devfs_register_chrdev(vfifo_major,"vfifo”,&vfifo_fops); if(result〈0){
printk(KERN_WARNING "vfifo: can't get major %d\n",vfifo_major); return result;
}
if(vfifo_major==0)
vfifo_major=result;
vfifo_devices = kmalloc(vfifo_nr_devs*sizeof(Vfifo_Dev),GFP_KERNEL); if(!vfifo_devices){
return -ENOMEM;
}
memset(vfifo_devices,0,vfifo_nr_devs*sizeof(Vfifo_Dev));
for(i=0;i〈vfifo_nr_devs;i++) {
init_waitqueue_head(&vfifo_devices[i]。rdq);
init_waitqueue_head(&vfifo_devices[i]。wrq);
sema_init(&vfifo_devices[i]。sem,1);
#ifdef CONFIG_DEVFS_FS
sprintf(vfifoname,"vfifo%d”,2*i);
vfifo_devices[i].w_handle= devfs_register(vfifo_devfs_dir,vfifoname, DEVFS_FL_NON, vfifo_major,2*i,S_IFCHR|S_IRUGO|S_IWUGO, &vfifo_fops,vfifo_device+i);
sprintf(vfifoname,”vfifo%d”,2*i+1);
vfifo_devices[i]。r_handle= devfs_register(vfifo_devfs_dir,vfifoname,
DEVFS_FL_NON,
vfifo_major,2*i+1,S_IFCHR|S_IRUGO|S_IWUGO, &vfifo_fops,vfifo_device+i);
if(!vfifo_devices[i]。r_handle||!vfifo_devices[i].w_handle){
printk(KERN_WARNING ”vfifo: can’t register vfifo device nr %i\n”,i);
}
#endif
}
#ifdef VFIFO_DEBUG
create_proc_read_entry(”vfifo”,0,NULL,vfifo_read_mem,NULL);
#endif
return 0;
}
/*vfifo。c */
static void __exit vfifo_cleanup_module(void)
{
int i;
devfs_unregister_chrdev(vfifo_major,"vfifo");
#ifdef VFIFO_DEBUG
remove_proc_entry("vfifo”,NULL);
#endif
if(vfifo_devices){
for(i=0;i〈vfifo_nr_devs;i++){
if(vfifo_devices[i].base)
kfree(vfifo_devices[i]。base);
devfs_unregister(vfifo_devices[i].r_handle);
devfs_unregister(vfifo_devices[i]。w_handle);
}
kfree(vfifo_devices);
devfs_unregister(vfifo_devfs_dir);
}
}
B、打开与释放
/*vfifo。c */
static int vfifo_open(struct inode *inode,struct file *filp)
{
Vfifo_Dev *dev;
int num=MINOR(inode-〉i_rdev);
/*检查读写权限是否合法*/ if((flip—>f_mode&FMODE_READ)&&!(num%2)||(filp-〉f_mode&FMOD E_WRITE)&&(num%2))
return -EPERM;
if(!filp-〉private_data){
if(num>=vfifo_nr_devs*2)
return —ENODEV;
dev=&vfifo_nr_devices[num/2];
filp—>private_data=dev;
}
else{
dev=filp-〉private_data;}
/*获得互斥访问的信号量*/ if(down_interruptible(&dev-〉sem))
return -ERESTARTSYS;
/*如果尚未分配缓冲区,则分配并初始化*/
if(!dev->base){
dev->base=kmalloc(vfifo_buffer,GFP_KERNEL);
if(!dev-〉base){
up(&dev-〉sem);
return —ENOMEN;
}
dev—〉buffersize=vfifo_buffer;
dev->len=dev-〉start=0;
}
if(filp->mode&FMODE_READ)
dev-〉readers++;
if(filp—>mode&FMODE_WRITE)
dev—>writers++;
filp-〉private_data=dev;
MOD_INC_USE_COUNT;
return 0;
}
C、读写操作
具体的read 代码如下:
/*vfifo.c */
static ssize_t vfifo_read(struct file *filp,char *buf,size_t count,loff_t *f_pos)
{
Vfifo_Dev *dev=filp—>private_data;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论