设备管理实验
if(mych_major<0)
return mych_major;
printk("The major is:%d\n",mych_major);
return 0;
}
static void cleanup_module()
{
unregister_chrdev(mych_major,"My character Device File");
实验过程与结果:
参考程序:
Example1:
#define _KERNEL_
#define MODULE
#include<linux/module.h>
#include<asm/uaccess.h>
#include<linux/fs.h>
#include<linux/kernel.h>
#include<linux/sched.h>
Int(*readdir)(struct inode *,struct file *,void,select_table *);
Int(*select)(struct inode *,struct file *,int,select_table *);
Int(*ioctl)(struct inode *,struct file *,unsigned int,unsigned long);
return -EFAULT;
*f_pos=pos;
}
ptintk("Mych:Complete the Writing\n");
return count;
}
static loff_t mych_lseek(struct file *file,loff_t offset,int orig)
{
loff_t pos;
Struct file_operations
{
Int(*llseek)(struct inode *,struct file *,off_t,int);
Int(*read)(struct inode *,struct file *,char *,int);
Int(*write)(struct inode *,struct file *,void *,const char *,int);
printk("Mych:lseek error %d\n",pos);
return -EINVAL;
}
return file->f_pos=pos;
}
struct file_operations mych_fops=
{
open:mych_open,
release:mych_release,
read:mych_read,
(1)设备驱动程序与内核和应用程序的接口
无论哪种类型的设备,Linux都是通过在内核中维护特殊的设备控制块来操作设备驱动程序。在字符设备和块设备的控制块中,有一个重要的数据结构file_operations,它是一个定义在Linux/fs.h头文件中的函数指针表,它包含了驱动程序提供给应用程序访问硬件设备的各种方法,该结构体的定义如下。
(3)与硬件设备的接口
Linux中为设备驱动程序访问I/O端口、硬件中断和DMA提供了简便方法,相应的头文件分别为io.h、irq.h和dma.h。为了降低实验难度,本实验不涉及硬件设备,而是讲一个大小为4096字节的内存作为一个字符设备来操作。
(4)内存分配
设备驱动程序作为内核的一部分,不能使用虚拟内存,必须利用内核提供的kmalloc()与kfree()来申请和释放内存空间。本实验不涉及内存的申请。
实验报告
课程名称_______设备管理实验______
学院_______计算机工程学院____
班级_________11软件1W______
学号_________********________
姓名__________成杰_________
2013年12月20日
学 号
11144126
姓名
成杰
实验日期
return 0;
}
static int mych_release(struct inode *inode,struct file *filp)
{
printk("Mych:Close\n");
return 0;
}
static ssize_t mych_read(struct file *filp,char *buf,size_t count,loff_t *f_pos)
2013.12.20
实验名称
设备管理实验
实验目的:
理解Linux设备管理技术,学会Linux模块编程方法,掌握基本的Linux设备驱动程序设计。
实验内容:
设计一个简单的字符设备驱动程序,并进行测试。
实验原理:
1、Linux模块概述
尽管Linux内核是整体结构,但是Linux内核允许内核在运行时动态的向其中插入或从中删除代码。这些代码包括相关的函数、数据函数入口和函数出口被一并组合在一个单独的二进制镜像中,即所谓的可装载内核模块,简称模块。支持模块的好处是基本内核镜像可以尽可能的小,因为可选的功能和设备驱动程序可以利用模块形式再提供。
{
int testdev();
int i;
char buf[10];
int pos=0;
testdev=open(argv[1],O_RDWR);
if(testdev==-1){
static int mych_major;
static unsigned char mych_body[4096]="my character device\n";
static int mych_open(struct inode *inode,struct file *filp)
{
printk("Mych:Open %s\n",current->comm);
{
loff_t pos;
printk("Mych:Reading...\n");
pos=*f_pos;
if((pos==4096)||(count>4096))
count=0;
else{
pos+=count;
if(pos>4096){
count-=(pos-4096);
pos=4096;
}
if(copy_to_user(buቤተ መጻሕፍቲ ባይዱ,mych_body+ *f_pos,count))
write:mych_write,
llseek:mych_lseek,
};
static int init_module()
{
printk("Hi,This's my character Device File!\n");
mych_major=re gister_chrdev(0,"My character Device File",&mych_fops);
};
多数情况下,只需为file_operations结构体中的少数方法
其他设备设为NULL即可。
每个可装备的设备驱动程序都必须有init_module和cleanup_module两个函数,在装载和卸载设备是系统自动调用这两个函数。Init_module函数除了对硬件进行检查和初始化之外,还要在内核中登记设备,对字符设备使用register_chrdev函数进行登记,而块设备和网络设备分贝使用register_blkdev和register_netdev函数进行登记。
Int(*fsync)(struct inode *,struct file *);
Int(*fasync)(struct inode *,struct file *,int);
Int(*check_media_change)(kdev_t dev);
Int(*revalidate)(kdev_t dev);
{
loff_t pos;
pos=*f_pos;
printk("Mych:Writing....\n");
if((pos==4096)||(count>4096))
count=0;
else{
pos+=count;
if(pos>4096){
count-=(pos-4096);
pos=4096;
}
if(copy_from_user(mych_body+ *f_pos,buf,count))
Modprobe modulename[module parameter]
其中,modulename指定需要加载的模块名称,后面的参数将在模块加载时传入内核。
Modprobe命令不但会加载指定的模块,还会自动加载任何它所依赖的相关模块。它还可以用来在内核中卸载模块,例如;
Modprobe-r modulename
pos=file->f_pos;
switch(orig){
case 0:
pos=offset;
break;
case 1:
pos+=offset;
break;
case 2:
pos=4096+offset;
break;
default:
return -EINVAL;
}
if((pos>4096)||(pos<0)){
Insmod module