Linux设备驱动注册

新的方式注册设备驱动(2.6内核之后的都是用cdev方式进行设备注册)


驱动部分的代码

#include <linux/module.h>		// module_init  module_exit
#include <linux/init.h>			// __init   __exit
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <linux/slab.h>




#define DEVICE_NAME		"suge char"
#define DEV_NUM 	(1)//设备数量
static dev_t char_devNum;//设备主次设备号的联合体
static struct cdev * char_cdev;//设备cdev结构体指针
static char *stringBuffer;


static int test_chrdev_open(struct inode *inode, struct file *file)
{
	// 这个函数中真正应该放置的是打开这个设备的硬件操作代码部分
	// 但是现在暂时我们写不了这么多,所以用一个printk打印个信息来做代表。
	printk(KERN_INFO "test_chrdev_open\n");
	
	return 0;
}


static int test_chrdev_release(struct inode *inode, struct file *file)
{
	printk(KERN_INFO "test_chrdev_release\n");
	
	return 0;
}
ssize_t test_chrdev_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{	
	int ret= 0;
	ret = copy_to_user(buf, stringBuffer, strlen(stringBuffer));
	printk(KERN_INFO "go in read function%d,%d\n",ret,strlen(stringBuffer));
	if(ret!= 0)
	{
		printk(KERN_INFO "read fail");
	}
	return ret;
}
ssize_t test_chrdev_write(struct file *file,	const char __user *user_buf,	size_t count, loff_t *ppos)
{
	int ret = 0;
	memset(stringBuffer,0,sizeof(stringBuffer));
	ret = copy_from_user(stringBuffer, user_buf, count);
	printk(KERN_INFO "go in write function%d,%d\n",ret, count);
	
	printk(KERN_INFO "buffer:::%s\n",stringBuffer);
	if(ret!= 0)
	{
		printk(KERN_INFO "write fail");
	}
	return count;
}


// 自定义一个file_operations结构体变量,并且去填充
static const struct file_operations char_fops = {
	.owner		= THIS_MODULE,				// 惯例,直接写即可
	
	.write		= test_chrdev_write,		//write函数
	.read		= test_chrdev_read,			//read函数
	.open		= test_chrdev_open,			// 将来应用open打开这个设备时实际调用的
	.release	= test_chrdev_release,		// 就是这个.open对应的函数
};


// 模块安装函数
static int __init chrdev_init(void)
{	


	char_devNum = MKDEV(0, 0);
	
	printk(KERN_INFO "start initial char device\n");
	stringBuffer = kmalloc(sizeof(char)*100, GFP_KERNEL);
	if(stringBuffer == NULL)
	{
		printk(KERN_INFO "malloc fail\n");
	}
	sprintf(stringBuffer,"welcome to device ");
	printk(KERN_INFO "driver buffer::::%s\n",stringBuffer);
	//让内核分配主设备号和次设备号
	if(0 != alloc_chrdev_region(&char_devNum, 3, DEV_NUM, DEVICE_NAME))
	{
		//注册失败
		printk(KERN_INFO "initial device fail\n");
		goto end1;
	}
	printk(KERN_INFO "major number:%02x,minor number:%02x\n",MAJOR(char_devNum),MINOR(char_devNum));
	/*申请cdev空间,初始化cdev,向内核注册cdev*/
	char_cdev = cdev_alloc();
	if(char_cdev ==NULL)
	{
		printk(KERN_INFO "alloc fail\n");
		goto end1;
	}
	cdev_init(char_cdev, &char_fops);
	if (0 != cdev_add(char_cdev, char_devNum, DEV_NUM))
	{
		//向内核注册cdev失败
		printk(KERN_INFO "initial device fail\n");
		goto end2;
	}
	return 0;




end2:
	cdev_del(char_cdev);
	unregister_chrdev_region(char_devNum, DEV_NUM);
end1://主次设备号注册失败
	kfree(stringBuffer);
	return -1;
}


// 模块卸载函数
static void __exit chrdev_exit(void)
{


	
	cdev_del(char_cdev);
	unregister_chrdev_region(char_devNum, DEV_NUM);
	printk(KERN_INFO "start uninitial device\n");
	kfree(stringBuffer);
	
}




module_init(chrdev_init);//注册驱动设备安装函数
module_exit(chrdev_exit);//注册驱动设备卸载函数


// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL");				// 描述模块的许可证
MODULE_AUTHOR("suge");				// 描述模块的作者
MODULE_DESCRIPTION("module test");	// 描述模块的介绍信息
MODULE_ALIAS("xxx");			// 描述模块的别名信息


用户空间程序代码

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

int main(void)
{
	int fileDes = -1;
	int size=0;
	char buffer[100];
	fileDes = open("/dev/suge",O_RDWR);
	if(fileDes < 0)
	{
		printf("open file fail\n");
		perror("error::");
		return 0;
	}
	memset(buffer,0,sizeof(buffer));
	size = read(fileDes,buffer,100);
	printf("read::::%s,size:%d",buffer,size);
	memset(buffer,0,sizeof(buffer));
	sprintf(buffer,"hahahahhahhaahahah",sizeof("hahahahhahhaahahah"));
	write(fileDes,buffer,strlen(buffer));
	memset(buffer,0,sizeof(buffer));
	size = read(fileDes,buffer,100);
	printf("read::%s,size:%d",buffer,size);
	
	
	close(fileDes);
}

运行结果

[@Suge ]# insmod module_test.ko 
[ 1804.195877] start initial char device
[ 1804.198871] driver buffer::::welcome to device 
[ 1804.202594] major number:fa,minor number:03
[@Suge ]# ./app >log
[ 1810.331518] test_chrdev_open
[ 1810.332945] go in read function0,18
[ 1810.336672] go in read function0,18
[ 1810.339895] test_chrdev_release
[@Suge ]# cat log 
[@Suge ]# rmmod module_test.ko 
[ 1840.101890] start uninitial device
[@Suge ]# insmod module_test.ko 
[ 1841.942490] start initial char device
[ 1841.945482] driver buffer::::welcome to device 
[ 1841.949219] major number:fa,minor number:03
[@Suge ]# ./app >log
[ 1846.324345] test_chrdev_open
[ 1846.325775] go in read function0,18
[ 1846.329386] go in write function0,18
[ 1846.332797] buffer:::hahahahhahhaahahah
[ 1846.336601] go in read function0,18
[ 1846.340075] test_chrdev_release
[@Suge ]# cat log 
read::::welcome to device ,size:0read::::welcome to device ,size:0read::hahahahhahhaahahah,size:0[@Suge ]# 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值