新的方式注册设备驱动(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 ]#