linux驱动学习加强版-3 (驱动代码测试,以及代码完善)
创始人
2025-05-31 18:17:47
0

文章目录

  • 一、用户测试代码
  • 二、驱动功能完善。
  • 三、open函数的特异性
  • 四、代码中的注意事项

一、用户测试代码

#include 
#include 
#include 
#include 
#include 
#include int main(int argc,char **argv)
{   if(argc <2){printf("Usage:%s -w \n",argv[0]);printf("Usage:%s -r \n",argv[0]);return -1;}int fd;char buf[1024];fd = open("/dev/filectl",O_RDWR);if(fd < 0){printf("can not open /dev/filectl\n");return -1;}if(strcmp(argv[1],"-w")==0 && argc==3){write(fd, argv[2], strlen(argv[2]));}else{read(fd,buf,1024);buf[1023] = '\n';printf("APP get data %s\n",buf);}close(fd);return  0;
}

这样一个简单的用户demo就写完了,然后让我们来试试看结果吧;
使用 gcc -o file_ctl file_test.c 将测试的demo编译为一个可执行文件。
在这里插入图片描述
执行完后是乱码,我们看下log呢

在这里插入图片描述
发现Log是调用了的,为啥呢 。
因为我们驱动之提供了接口,但没有提供功能。
在这里插入图片描述

我们驱动没有提供功能,你们怎么使用呢。哈哈!所以接下来我们需要的是完善驱动功能

二、驱动功能完善。

这个demo的功能就是我调用对应的函数,将我要写的文件传递到底层,然后再把数据读取出来,返回给上层。
这个时候我们就需要内核的标准的函数

copy_from_user  // 从用户空间拷贝文件到驱动
copy_to_user // 从驱动拷贝文件到用户层
#include 
#include 
#include 
#include 
#include 
#include 
#include static int major = 0; //确定主设备号,0默认系统分配
static struct class *filectl_class;
static char kbuffer[1024]; //内核空间的bufferssize_t filectl_read(struct file *file, char __user *buf, size_t size, loff_t *pops)
{int ret;printk("[%s %d]\n", __FUNCTION__, __LINE__);ret = copy_to_user(buf, kbuffer, size);if(ret < 0) {printk("[%s %d]copy_to_user error \n ",__FUNCTION__, __LINE__ );}return size;
}ssize_t filectl_write(struct file *file,const char __user *buf, size_t size, loff_t *pops)
{int ret;printk("[%s %d]\n", __FUNCTION__, __LINE__);ret = copy_from_user(kbuffer, buf, size);if(ret < 0) {printk("[%s %d]copy_from_user error \n ",__FUNCTION__, __LINE__ );}return size;
}int filectl_open(struct inode *inode, struct file *file)
{printk("[%s %d]\n", __FUNCTION__, __LINE__);return 0;
}int filectl_close(struct inode *inode, struct file *file)
{printk("[%s %d]\n", __FUNCTION__, __LINE__);return 0;
}// 定义自己的驱动的 file_operations
static struct file_operations filectl_ops = {.owner	 = THIS_MODULE,.read    = filectl_read,.write   = filectl_write,.open    = filectl_open,.release = filectl_close, // 好像没有close这个函数
};static int __init filectl_init(void)
{// 在初始化的时候进行驱动注册,设备号major = register_chrdev(0,"filectl",&filectl_ops);if(major < 0) {printk("[%s %d] filectl error\n", __FUNCTION__, __LINE__); // 注册失败return -1;}filectl_class = class_create(THIS_MODULE, "filectl"); // class_create 动态创建dev的类// IS_ERR 查看指针是否有错误if(IS_ERR(filectl_class)) {printk("[%s %d] class_create error\n", __FUNCTION__, __LINE__);unregister_chrdev(major,"filectl");return -1;}// 创建字符设备device_create(filectl_class, NULL, MKDEV(major, 0),NULL, "filectl");printk("[%s %d] filectl driver create success\n", __FUNCTION__, __LINE__);return 0;
}static void __exit filectl_exit(void) {device_destroy(filectl_class, MKDEV(major, 0));class_destroy(filectl_class);// 注销字符设备unregister_chrdev(major,"filectl");printk("[%s %d]goodbye filectl driver\n",  __FUNCTION__, __LINE__);
}module_init(filectl_init);
module_exit(filectl_exit);
MODULE_LICENSE		("GPL");
MODULE_AUTHOR		("cong.luo");
MODULE_DESCRIPTION	("First file contrl module");

再来测试一把呢:
在这里插入图片描述
在这里插入图片描述

这样就OK了哇。

三、open函数的特异性

下面我们修改下代码:
首先是驱动文件,我们去掉read、write、open

#include 
#include 
#include 
#include 
#include 
#include 
#include static int major = 0; //确定主设备号,0默认系统分配
static struct class *filectl_class;
static char kbuffer[1024]; //内核空间的buffer// ssize_t filectl_read(struct file *file, char __user *buf, size_t size, loff_t *pops)
// {
//     int ret;
// 	printk("[%s %d]\n", __FUNCTION__, __LINE__);
//     ret = copy_to_user(buf, kbuffer, size);
//     if(ret < 0) {
//         printk("[%s %d]copy_to_user error \n ",__FUNCTION__, __LINE__ );
//     }
//     return size;
// }// ssize_t filectl_write(struct file *file,const char __user *buf, size_t size, loff_t *pops)
// {
//     int ret;
// 	printk("[%s %d]\n", __FUNCTION__, __LINE__);
//     ret = copy_from_user(kbuffer, buf, size);
//     if(ret < 0) {
//         printk("[%s %d]copy_from_user error \n ",__FUNCTION__, __LINE__ );
//     }
//     return size;
// }// int filectl_open(struct inode *inode, struct file *file)
// {
// 	printk("[%s %d]\n", __FUNCTION__, __LINE__);
//     return 0;
// }int filectl_close(struct inode *inode, struct file *file)
{printk("[%s %d]\n", __FUNCTION__, __LINE__);return 0;
}// 定义自己的驱动的 file_operations
static struct file_operations filectl_ops = {.owner	 = THIS_MODULE,// .read    = filectl_read,// .write   = filectl_write,//.open    = filectl_open,.release = filectl_close, // 好像没有close这个函数
};static int __init filectl_init(void)
{// 在初始化的时候进行驱动注册,设备号major = register_chrdev(0,"filectl",&filectl_ops);if(major < 0) {printk("[%s %d] filectl error\n", __FUNCTION__, __LINE__); // 注册失败return -1;}filectl_class = class_create(THIS_MODULE, "filectl"); // class_create 动态创建dev的类// IS_ERR 查看指针是否有错误if(IS_ERR(filectl_class)) {printk("[%s %d] class_create error\n", __FUNCTION__, __LINE__);unregister_chrdev(major,"filectl");return -1;}// 创建字符设备device_create(filectl_class, NULL, MKDEV(major, 0),NULL, "filectl");printk("[%s %d] filectl driver create success\n", __FUNCTION__, __LINE__);return 0;
}static void __exit filectl_exit(void) {device_destroy(filectl_class, MKDEV(major, 0));class_destroy(filectl_class);// 注销字符设备unregister_chrdev(major,"filectl");printk("[%s %d]goodbye filectl driver\n",  __FUNCTION__, __LINE__);
}module_init(filectl_init);
module_exit(filectl_exit);
MODULE_LICENSE		("GPL");
MODULE_AUTHOR		("cong.luo");
MODULE_DESCRIPTION	("First file contrl module");

在app代码中添加一些打印:

#include 
#include 
#include 
#include 
#include 
#include int main(int argc,char **argv)
{   if(argc <2){printf("Usage:%s -w \n",argv[0]);printf("Usage:%s -r \n",argv[0]);return -1;}int fd;char buf[1024];fd = open("/dev/filectl",O_RDWR);if(fd < 0){printf("can not open /dev/filectl\n");return -1;}printf("open /dev/filectl success \n");if(strcmp(argv[1],"-w")==0 && argc==3){int err = write(fd, argv[2], strlen(argv[2]));if (err < 0 ) {printf("write /dev/filectl error \n");return -1;}printf("write /dev/filectl success \n");}else{int err = read(fd,buf,1024);if (err < 0 ) {printf("read /dev/filectl error \n");return -1;}printf("read /dev/filectl success \n");buf[1023] = '\n';printf("APP get data %s\n",buf);}close(fd);return  0;
}

在这里插入图片描述没有read和write函数,我们无法读写。
但是我们可以进行open,这说明了open函数是一个比较特殊的函数,或许硬件默认就是可以进行open的,是为了方便一些初始化吧。大家记住就好。

四、代码中的注意事项

copy_to_user 和 copy_from_user传递的参数位置是不一样的哟

ret = copy_to_user(buf, kbuffer, size);
ret = copy_from_user(kbuffer, buf, size);

有些小伙伴可能没有注意到这点。

相关内容

热门资讯

“男子持刀入室盗窃”视频引发关... 近日,一段疑似“小偷”入室盗窃被业主家中监控拍下的视频在网上引发关注。11月21日晚,“翠屏公安”微...
绝不允许日本军国主义幽灵复活!... 2025年11月7日,日本首相高市早苗宣称,如果中国大陆对台湾出动军舰并使用武力,可能会构成“存亡危...
【解决】AI法律助手荣获202... 2025全球数字经济大会启幕,搭建国际数字合作高端平台 经国务院批准,由北京市人民政府、国家互联网信...
嘉兴男子与妻争吵,突然将行李箱... 近日,浙江嘉兴一对夫妻因琐事发生争吵,丈夫突然将装满衣物的行李箱从6楼扔到楼下,引发关注。11月22...
三地107家律所齐聚丰台,京津... 11月22日,京津冀律师驿站举办“党建业务深度融合 促进行业规范发展”主题活动,发布“百千万行动计划...
家装预付资金安全困局如何破解,... 家装预付资金安全困局如何破解 专家提出:建立“先验收后付款”装修资金存管制度 预交数万元甚至数十万元...
工行安康解放路支行积极开展《反... 为深入贯彻落实《国家金融监督管理总局安康监管分局办公室关于开展<反有组织犯罪法>宣传活动的通知》要求...
重庆公布育儿补贴制度实施方案 原标题:每孩每年3600元 重庆公布育儿补贴制度实施方案 11月21日,记者了解到,市卫生健康委、市...
十五运会组委会在深总结本届赛事... 深圳新闻网2025年11月22日讯(深圳报业集团记者 林炜航)11月21日,十五运会组委会在深圳市民...