1.简述
本实验目的是在proc下创建一个chao_proc节点,用于测试向节点输入一个正整数读取时返回一个保留两位小数的浮点数。通过上述的目的,固需创建proc节点,使用文件操作集中的read和write成员;对用户空间传输的字符串进行转换成正整数用于乘于0.85后的数据还要转换成字符串用于用户空间输出打印。
在这次实验中使用sscanf()函数对用户空间的数字字符串转换成正整数;sprintf()函数对正整数转换成字符串。函数的具体用法请自行百度,在这不做过多的介绍,只知道sprintf()函数有一个巨大的坑,博主搞不太明白。
注意:开发板平台是否支持浮点数的计算,因此需要拆分整数部分与小数部分的运算。
2.代码示例
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/errno.h>
#include <linux/cdev.h>
#include <linux/device.h>
#define BUFSIZE 1024
static char *buf;
static unsigned int len;
// 读函数
ssize_t test_read (struct file *file, char __user *user, size_t size, loff_t *loff_t)
{
int date = 0,value = 0,decimal = 0;
char str[512] = {0};
if(*loff_t > 0)
{
return 0;
}
printk("start read\n");
printk("the strting is >>>> %s\n",buf);
// 判断输入整数的范围
if(strlen(buf) > 11)
{
printk("input data error!\n");
value = -1;
return -EFAULT;
}
if(value < 0)
{
sprintf(str,"%d\n",value);
}
else
{
// 数字字符转换成整型数
sscanf(buf,"%d",&date);
printk("str = %d\n",date);
// 整数部分与小数部分分离
value = (date * 85) /100;
decimal = (date * 85) % 100;
// 判断如果小数部分十分位是否为0,是则补0
if(decimal > 0 && decimal < 10)
{
sprintf(str,"%d.0%d\n",value,decimal);
}
else
{
sprintf(str,"%d.%d\n",value,decimal);
}
}
printk("str = %s\n",str);
// len记录用户空间输入字符串的个数,有read函数中指上报字符串个数
// 故此需要上报数据转换后的个数
len = strlen(str);
// 上报到用户空间
if(copy_to_user(user,str,len))
{
return -EFAULT;
}
// 字符串数组清零
memset(str,0,sizeof(str));
*loff_t = *loff_t + len;
return len;
}
ssize_t test_write (struct file *file, const char __user *user, size_t size, loff_t *loff_t)
{
if(size <= 0)
{
return -EFAULT;
}
printk("---start write---\n");
len = size > BUFSIZE ? BUFSIZE : size;
if(buf != NULL)
{
kfree(buf);
}
// 申请空间
buf = (char*)kmalloc(len + 1,GFP_KERNEL);
if(buf == NULL)
{
printk("kmalloc create failed\n");
return -EFAULT;
}
memset(buf,0,len + 1);
// 内核空间读取用户空间的内容
if(copy_from_user(buf,user,len))
{
return -EFAULT;
}
printk("writing>>>%s",buf);
return len;
}
//文件操作集
static struct file_operations test_fops =
{
.owner = THIS_MODULE,
.read = test_read,
.write = test_write,
};
static int __init test_init(void)
{
struct proc_dir_entry *file;
//注册一个proc下文件节点
file = proc_create("chao_proc",0644,NULL,&test_fops);
if(!file)
{
return -ENOMEM;
}
printk("---succedded to initalize test device.\n");
return 0;
}
static void __exit test_exit(void)
{
//注销文件节点
remove_proc_entry("chao_proc",NULL);//节点名;父节点
printk("---succedded char driver test_exit\n");
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
3.运行结果
该结果是Ubuntu下QEMU仿真运行的结果
有什么错误的地方,还请指出来。谢谢!