字符设备驱动程序(write & read)——开发步骤(5)

运用应用程序调用自己编写的字符设备驱动

  • 将字符设备驱动程序make,编译一下
    在这里插入图片描述

  • 导入模块并查看模块
    sudo insmod memdev.ko
    sudo lsmod
    在这里插入图片描述

  • 创建设备文件memdev0并查看,在/dev目录下
  • cd /dev

  • sudo mknod 设备文件名 c(字符设备驱动程序) 主设备号 次设备号

  • 查看主设备号
    cat /proc/devices
    在这里插入图片描述

  • 创建设备文件
    sudo mknod memdev0 c 241 0
    在这里插入图片描述

  • 编译mem_app.c文件,生成可执行文件a.out
    gcc mem_app.c
    在这里插入图片描述

  • 用超级用户权限运行可执行文件
    sudo ./a.out
    在这里插入图片描述

运行成功!!!!下面是源码资源!!!!!!

===================================================================================

字符设备驱动程序源码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/uaccess.h>

#define BASEMINOR 0
#define COUNT     3
#define NAME      "memdev"
#define MEMDEV_SIZE		4096

dev_t devno;

struct memdev{
	char *data;
	unsigned long size;
};

struct cdev *cdevp = NULL;
struct memdev *memdevp = NULL;

int mem_open (struct inode *inode,struct file *filp){
	//printk(KERN_INFO "---%s---%s---%d---\n",__FILE__,__func__,__LINE__);
	struct memdev *mdev = NULL;
	
	int num = MINOR(inode->i_rdev);
	if(num >= COUNT){
		return -ENODEV;
	}
	mdev = &memdevp[num];          
	filp->private_data = mdev;
	
	return 0;
}
int mem_release (struct inode *inode,struct file *filp){
	printk(KERN_INFO "---%s---%s---%d---\n",__FILE__,__func__,__LINE__);
	return 0;
}

static ssize_t mem_read (struct file *filp,char __user *buf,size_t size,loff_t *ppos){
	//printk(KERN_INFO "---%s---%s---%d---\n",__FILE__,__func__,__LINE__);

	unsigned long p = *ppos;
	unsigned int count = size;
	int ret =0;
	struct memdev *mdev = filp->private_data;

	if(p >= MEMDEV_SIZE){
		return 0;
	}
	if(count > MEMDEV_SIZE - p){
		count = MEMDEV_SIZE - p;
	}
	if(copy_to_user(buf,(void*)(mdev->data+p),count)){
		return -EFAULT;
	}else{
		*ppos += count;				/
		ret = count;
	}

	return ret;
}

static ssize_t mem_write (struct file *filp,const char __user *buf,size_t size,loff_t *ppos){
	//printk(KERN_INFO "---%s---%s---%d---\n",__FILE__,__func__,__LINE__);

	unsigned long p = *ppos;
	unsigned int count = size;
	int ret =0;
	struct memdev *mdev = filp->private_data;

	if(p >= MEMDEV_SIZE){
		return 0;
	}
	if(count > MEMDEV_SIZE - p){
		count = MEMDEV_SIZE - p;
	}
	if(copy_from_user(mdev->data + p,buf,count)){
		return -EFAULT;
	}else{
		*ppos += count;				/
		ret = count;
	}

	return ret;
}

loff_t mem_llseek (struct file *filp,loff_t offset,int whence){
	//printk(KERN_INFO "---%s---%s---%d---\n",__FILE__,__func__,__LINE__);

	loff_t newpos;
	
	switch(whence){
		case 0:
			newpos = offset;
			break;
		case 1:
			newpos = filp->f_pos + offset;
			break;
		case 2:
			newpos = MEMDEV_SIZE - 1 + offset;
			break;
		default:
			return -EINVAL;
	}
	
	if((newpos < 0) || (newpos > MEMDEV_SIZE)){
		return -EINVAL;
	}
	filp->f_pos = newpos;
	
	return newpos;
}

struct file_operations fops = {
	.owner = THIS_MODULE,
	.open = mem_open,
	.release = mem_release,
	.llseek = mem_llseek,
	.write = mem_write,
	.read = mem_read
};

static int __init mem_init(void)
{
	int ret;
	int i;
/***********************************************************************/
	ret = alloc_chrdev_region(&devno,BASEMINOR,COUNT,NAME);
	if(ret < 0){
		printk(KERN_ERR "alloc_chrdev_region failed...\n");
		goto err1;
	}
	//设备号申请成功打印出来
	printk(KERN_INFO "major = %d \n",MAJOR(devno));
/***********************************************************************/
	cdevp = cdev_alloc();
	if(NULL == cdevp){
		printk(KERN_ERR "cdev_alloc failed...\n");
		ret = -ENOMEM;
		goto err2;
		//cdev结构体申请失败需要将上一步申请到的设备号资源释放。
	}
/***********************************************************************/	
	cdev_init(cdevp,&fops);
/***********************************************************************/	
	ret = cdev_add(cdevp,devno,COUNT);
	if(ret < 0){
		printk(KERN_ERR "cdev_add failed...\n");
		goto err2;
	}
/***********************************************************************/
	//为memdev设备结构体分配内存
	memdevp = kmalloc(COUNT * sizeof(struct memdev),GFP_KERNEL);
	if(NULL == memdevp){
			printk(KERN_ERR "memdevp kmalloc failed...\n");
			ret = -ENOMEM;
			goto err2;
		}
	memset(memdevp,0,sizeof(struct memdev));

	//上一步申请的是一片空间,这一片空间里是COUNT个设备的总空间,需要为每一个设备分配空间
	for(i = 0;i<COUNT;i++){
		memdevp[i].data = kmalloc(MEMDEV_SIZE,GFP_KERNEL);
		memdevp[i].size = MEMDEV_SIZE;
		memset(memdevp[i].data,0,MEMDEV_SIZE);
	}

/***********************************************************************/
	printk(KERN_INFO "---%s---%s---%d---\n",__FILE__,__func__,__LINE__);
	return 0;
err2:
	unregister_chrdev_region(devno,COUNT);			//释放申请到的设备号资源
err1:
	return ret;
}

static void __exit mem_exit(void)
{
	cdev_del(cdevp);
	unregister_chrdev_region(devno,COUNT);			//释放申请到的设备号资源
	printk(KERN_INFO "---%s---%s---%d---\n",__FILE__,__func__,__LINE__);
}

module_init(mem_init);
module_exit(mem_exit);
MODULE_LICENSE("GPL");

Makefile文件源码


KERNDIR = /lib/modules/4.15.0-107-generic/build
PWD = $(shell pwd)

obj-m:=memdev.o

all:
	make -C $(KERNDIR) M=$(PWD) modules
	
clean:
	make -C $(KERNDIR) M=$(PWD) clean

应用程序源码

#include <stdio.h>
#include <string.h>

int main()
{
	FILE *fp0 = NULL;
	char buf[4096];
	
	strcpy(buf,"mem is a chrdev!!!!");
	printf("buf1: %s",buf);
	
	/****************************************************************
	 *将buf字符串写入memdev0设备文件中,然后将buf字符串更新,
	 *最后从设备文件中读取,写入和读取的内容一致表示成功写入!!!
	 ****************************************************************/

	fp0 = fopen("/dev/memdev0","r+");
	if(fp0 < 0){
		printf("open memdev0 failed!!!\n");
		return -1;
	}
	
	fwrite(buf,sizeof(buf),1,fp0);
	fseek(fp0,0,SEEK_SET);
	
	strcpy(buf,"buf is NULL!!!!");
	printf("buf2: %s",buf);
	
	fread(buf,sizeof(buf),1,fp0);
	printf("buf3: %s",buf);
	
	
	
	return 0;
}
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值