对节点写入一个正整数,读取节点时返回乘以0.85的两位小数的浮点数

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仿真运行的结果
在这里插入图片描述
有什么错误的地方,还请指出来。谢谢!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员超庆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值