Linux2.6内核下简单的字符设备驱动及测试

Linux2.6内核下的简单字符设备

1.自定设备符结构体

struct VirtualDisk{
 struct cdev cdev;
 unsigned char mem[VIRTUALDISK_SIZE];

long count;
};

2.声明函数

//设备驱动模块加载函数
int __init VirtualDisk_init(void);

//模块卸载函数
void __exit VirtualDisk_exit(void);

//初始化并注册
static void VirtualDisk_setup_cdev(struct VirtualDisk *, int );

//文件打开函数
int VirtualDisk_open(struct inode *, struct file *);

//文件读函数
static ssize_t VirtualDisk_read(struct file *, char __user *, size_t, loff_t *);

//文件写函数
static ssize_t VirtualDisk_write(struct file *, const char __user *, size_t, loff_t *);

3.初始化文件操作结构体

static const struct file_operations VirtualDisk_fops = {
 .owner = THIS_MODULE,
 .read = VirtualDisk_read,
 .write = VirtualDisk_write,
 .open = VirtualDisk_open,
};

4.定义函数

int __init VirtualDisk_init(void)
{
 int result ;
 dev_t devno = MKDEV(VirtualDisk_major, 0); //构建设备号
 if(VirtualDisk_major)
 {
  result = register_chrdev_region(devno, 1, "VirtualDisk");//静态申请
 }
 else
 {
  result = alloc_chrdev_region(&devno, 0, 1, "VirtualDisk");//动态申请
  VirtualDisk_major = MAJOR(devno);
 }
 if(result < 0)
 {
  return result;
 }
 VirtualDisk_devp = kmalloc(sizeof(struct VirtualDisk),GFP_KERNEL);//动态申请设备结构体内存
 if(!VirtualDisk_devp)
 {
  result = -ENOMEM;
  goto fail_kmalloc;
 }
 memset(VirtualDisk_devp, 0, sizeof(struct VirtualDisk));
 VirtualDisk_setup_cdev(VirtualDisk_devp, 0);
 
 printk("register_chrdev_region success\n");
 return 0;
 
 fail_kmalloc:
  unregister_chrdev_region(devno, 1);
 
 return result;
 
}

 

void __exit VirtualDisk_exit(void)
{
 cdev_del(&VirtualDisk_devp->cdev);//注销设备结构体
 kfree(VirtualDisk_devp);//释放内存
 unregister_chrdev_region(MKDEV(VirtualDisk_major,0),1);//释放设备号
}

 

static void VirtualDisk_setup_cdev(struct VirtualDisk *dev, int minor)
{
 int err;
 dev_t devno = MKDEV(VirtualDisk_major, minor);
 printk("major:%d\n",MAJOR(devno));
 printk("minor:%d\n",MINOR(devno));
 cdev_init(&dev->cdev, &VirtualDisk_fops);//初始化cdev设备
 dev->cdev.owner = THIS_MODULE;
 err = cdev_add(&dev->cdev, devno, 1);//注册cdev设备到系统
 if(err)
 {
  printk(KERN_NOTICE "Error in cdev_add()\n");
 }
}

 

int VirtualDisk_open(struct inode *inode, struct file *filp)
{
 filp->private_data = VirtualDisk_devp;
 struct VirtualDisk *devp = filp->private_data;
 devp->count++;
 return 0;
}

 

static ssize_t VirtualDisk_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
 unsigned long p = *ppos;
 unsigned int count = size;
 int ret = 0;
 struct VirtualDisk *devp = filp->private_data;
 if(p >= VIRTUALDISK_SIZE)
 {
  return count? -ENXIO: 0;
 }
 if(count > VIRTUALDISK_SIZE)
 {
  count = VIRTUALDISK_SIZE - p;
 }
 if(copy_to_user(buf, (void *)(devp->mem + p), count))//将内核中的内容拷贝到用户空间
 {
  ret = -EFAULT;
 }
 else
 {
  *ppos += count; 
  ret = count;
  printk(KERN_INFO "read %d bytes from %d\n",count,p);
 }
 *ppos = 0;//将内核指针复位
 printk("read:%s\n",buf);
 return ret;

static ssize_t VirtualDisk_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
 unsigned long p = *ppos;
 int ret = 0;
 unsigned int count = size;
 struct VirtualDisk *devp = filp->private_data;
 if(p >= VIRTUALDISK_SIZE)
 {
  return count? -ENXIO:0;
 }
 if(count > VIRTUALDISK_SIZE)
 {
  count = VIRTUALDISK_SIZE - p;
 }
 if(copy_from_user(devp->mem + p, buf, count))
 {
  ret = -EFAULT;
 }
 else
 {
  *ppos += count;
  ret = count;
  printk(KERN_INFO "written %d bytes from %d\n",count,p);
 }
 *ppos = 0;//内核指针复位
 printk("write:%s\n",buf);
 return ret;
}

 

//模块函数

module_init(VirtualDisk_init);
module_exit(VirtualDisk_exit);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Zhang San");

 

5.Makefile文件

obj-m := VirtualDisk.o

#内核中Makefile文件的位置

KDIR := /lib/modules/2.6.35-22-generic/build
all:
 make -C $(KDIR) M=$(shell pwd) modules

clean:
 rm -f *.ko *.o *.mod *.mod.c *.symvers *.order

 

6.编译

make

编译后的结果:

7.加载模块

sudo insmod VirtualDisk.ko

8.在/dev文件夹下创建设备文件

sudo /dev/VirtualDisk c 200 0

9.测试(简单的open、write、read)

测试程序

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define BFSIZE 256
int main()
{
 int fd,size;
 const char *buff= "hello";
 char temp[BFSIZE];
 if((fd = open("/dev/VirtualDisk",O_RDWR)) < 0)//打开文件描述符
 {
  perror("open");
  exit(1);
 }
 if((size = write(fd,buff,strlen(buff))) < 0)//写
 {
  perror("write");
  exit(1);
 }
 if((size = read(fd,temp,BFSIZE)) < 0)//读
 {
  perror("read");
  exit(1);
 }
 
 printf("Read from device :%s\n",temp);
 close(fd);
 return 0;
}

测试结果

1.测试程序

2.内核空间

10.卸载驱动

sudo rmmod VirtualDisk

11.删除设备文件

sudo rm -f /dev/VirtualDisk.

结束。

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值