linux 添加简单字符设备驱动6,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

编译后的结果:

a4c26d1e5885305701be709a3d33442f.png

7.加载模块

sudo insmod VirtualDisk.ko

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

sudo /dev/VirtualDisk c 200 0

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

测试程序

#include

#include

#include

#include

#include

#include

#include

#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.测试程序

a4c26d1e5885305701be709a3d33442f.png

2.内核空间

a4c26d1e5885305701be709a3d33442f.png

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、付费专栏及课程。

余额充值