目标:

实现模块读取uboot参数;

实现给模块传递参数;

实现proc文件系统属性的读写。

背景:

因一项目使用的模块,在加载时需要传入参数。于是对这一知识点进行整理,附带实现模块读取uboot参数样例和实现proc文件系统属性的读写的样例。部分代码网络摘抄,部分自己实现。


模块源码(param_proc.c):

#include <linux/kernel.h>
#include <linux/module.h>   //for init_module() 
#include <linux/init.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>    //for init_task
#include <linux/cdev.h>
#include <asm/io.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 3, 0)
#include <asm/switch_to.h>
#include <linux/slab.h>     //for kzalloc, kfree
#include <linux/proc_fs.h>  //for create_proc_info_entry() 
#else
#include <asm/system.h>    
#endif
#include <asm/uaccess.h>
#include <linux/uaccess.h>
//root@wmh-VirtualBox:/opt/param_proc# uname  -a
//Linux wmh-VirtualBox 5.15.0-69-generic #76~20.04.1-Ubuntu SMP Mon Mar 20 15:54:19 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
//root@wmh-VirtualBox:/opt# uname -a
//Linux wmh-VirtualBox 4.15.0-142-generic #146~16.04.1-Ubuntu SMP Tue Apr 13 09:27:15 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

//insmod  paramproc.ko  val1=2  val2=4  pstr="abc" 后执行dmesg,可以看到打印:val1:2, val2:4, pstr:abc
//insmod  paramproc.ko                             后执行dmesg,可以看到打印:val1:0, val2:0, pstr:(null)

//uboot启动参数里面添加参考(未验证):noinitrd  root=/dev/mtdblock2  init=/linuxrc  console=ttySAC0  getval=1,2  getstr=abc

//cat  /proc/result_f/result
//cat  /proc/result

int   val1 = 0,  val2 = 0;
char  *pstr = NULL;
module_param(val1, int,   S_IRUGO);
module_param(val2, int,   S_IRUGO /*0664 ???*/);
module_param(pstr, charp, S_IRUGO);

static int ccnt = 0;
static  ssize_t  fts_debug_read(struct file  *filp, char __user  *buff, size_t count, loff_t *ppos)
{
    size_t size = 0;
    if(ccnt == 0) { ccnt++; } else if(ccnt > 0) { ccnt =0; return 0; } //因为执行cat  /proc/result时,控制台一直打印,所以通过这种方法,当第二次进入
                                                                       //这个函数时,返回0,就可以防止控制台一直打印,及防止执行cat  /proc/result不退出。
    if(NULL == pstr) { pstr = kmalloc(56, GFP_KERNEL); memset(pstr, 0, 56); memcpy(pstr, "111111\r\n", 8);}
    printk("%s():%d, count:%ld, pstr:%s, len:%ld\r\n", __FUNCTION__, __LINE__, count, pstr, strlen(pstr)); /*count打印处理的值为:131072*/
    size = copy_to_user(buff, pstr, strlen(pstr)<count?strlen(pstr):count);
    printk("%s():%d, count:%ld, pstr:%s, len:%ld, size:%ld\r\n", __FUNCTION__, __LINE__, count, pstr, strlen(pstr), size);
    return strlen(pstr);
}

//insmod paramproc.ko   val1=12 val2=13 pstr=123456qwer 后执行dmesg,可以看到打印:val1:12, val2:13, pstr:123456qwer
//echo "qwer123456ghjwe" > /proc/result  后执行dmesg,可以看到打印:
//                                                fts_debug_write():50, count:16, pstr:10
//copy_from_user最后一个参数填count的打印:       fts_debug_write():52, pstr:qwer123456ghjwe  cpuacct.usage_pe\xbfFo\xf64\xf4\xf1, count:16, size:0
//copy_from_user最后一个参数填strlen(pstr)的打印:fts_debug_write():55, pstr:qwer123456, count:16, size:0
static  ssize_t  fts_debug_write(struct file *filp, const char __user *buff, size_t count, loff_t *ppos)
{
    int size = 0;  /*count打印处理的值为:写入值的长度+回车*/
    if(NULL == pstr) { pstr = kmalloc(56, GFP_KERNEL); }
    printk("%s():%d, count:%ld, pstr:%ld\r\n", __FUNCTION__, __LINE__, count, strlen(pstr)); 
    size = copy_from_user(pstr, buff, strlen(pstr)<count?strlen(pstr):count); //返回的是没有被拷贝成功的数量。
    printk("%s():%d, pstr:%s, count:%ld, size:%d\r\n", __FUNCTION__, __LINE__, pstr, count, size);
    return  count; //必须返回count,否则会循环写,直到写满count个字节为止。
}

static  struct   proc_dir_entry   *g_proc_dir = NULL;
static  struct   proc_dir_entry   *proc1 = NULL;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))    
    static  struct  proc_ops  fts_proc_fops={
        .proc_read  = fts_debug_read,
        .proc_write = fts_debug_write,
    };
#else
    static  struct  file_operations  fts_proc_fops={
        .owner = THIS_MODULE,
        .read  = fts_debug_read,
        .write = fts_debug_write,    
    };
#endif

static  __init  int  test_init_module(void) {
    printk("val1:%d, val2:%d, pstr:%s\r\n", val1, val2, pstr);
    g_proc_dir = proc_mkdir("result_f", NULL);    //会在 /proc目录下创建result_f目录
    if(NULL == g_proc_dir) { return  -EINVAL; }
//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
//    proc = proc_create("result", 0664, /*g_proc_dir*/NULL, &fts_proc_fops);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
    proc1 = proc_create("result", 0664, /*g_proc_dir*/NULL, &fts_proc_fops); //如果有g_proc_dir,则会在result_f目录下创建result文件
    //如果没有g_proc_dir,则会在 /proc目录下创建 result文件
#else
    proc1 = create_proc_entry("result", 0664,  /*g_proc_dir*/NULL);
    if(NULL != proc1) { //proc->read_proc = read_result;
        proc1->write_proc = fts_debug_write;
        proc1->read_proc  = fts_debug_read;
    }
#endif
    if(NULL == proc1) { proc_remove(g_proc_dir); }
    return 0;
}

static   void   test_exit_module(void) {
//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
//    proc_remove(proc1);
//    proc_remove(g_proc_dir);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
    proc_remove(proc1);
    proc_remove(g_proc_dir);
#else
    remove_proc_entry("result", g_proc_dir);
#endif
}

#ifndef  MODULE
    static  __init   int  get_val(char  *str) {
        int  ints[10];
        str = get_options(str, ARRAY_SIZE(ints), ints);
        if(ints[0] == 2) {
            val1 = ints[1];
            val2 = ints[2];
        }
        return 1;
    }
    static  __init   int  get_str(char *str) {
        if(NULL == pstr) { pstr = kmalloc(56, GFP_KERNEL); }
        memcpy(pstr, str, min(strlen(str), 56));
        return 1;
    }        
    __setup("getval=", get_val);
    __setup("getstr=", get_str);
    __initcall(test_init_module);
#else
    module_init(test_init_module);
#endif
    module_exit(test_exit_module);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("wmh");
MODULE_DESCRIPTION("wmh's program");

Makefile文件:

#make   modules
#make   clean
#make   install
CONFIG_MODULE_SIG = n
TARGET_MODULE:=paramproc
$(TARGET_MODULE)-objs := param_proc.o
ifneq ($(KERNELRELEASE),)
    obj-m := $(TARGET_MODULE).o
else
    PWD := $(shell pwd)
    KDIR := /lib/modules/$(shell uname -r)/build
modules:
    $(MAKE) -C $(KDIR) M=$(PWD)  modules
install:
    $(MAKE) -C $(KDIR) M=$(PWD)  modules_install    
clean:
    rm -rf *.o *.mod.c *.ko *.symvers *.order *.cmd *.maker .tmp_versions *.mod *.cmd
endif

编译、运行结果:

执行make编译出 paramproc.ko

执行 insmod  paramproc.ko  val1=2  val2=4  pstr="abc" ,后执行dmesg,可以看到打印:val1:2, val2:4, pstr:abc。

执行:echo "12345678" > /proc/result 往result里面写值,实际上值写到了pstr指向的地址。

执行:cat  /proc/result读取数据。

疑问:

fts_debug_read函数中如果没有添加  if(ccnt == 0) { ccnt++; } else if(ccnt > 0) { ccnt =0; return 0; },执行cat   /proc/result会一直打印?????。

实现insmod 模块名.ko 参数1=值 参数2=值 参数3=值.......相关推荐

  1. mysql安装服务:Internal error (值不能为null.参数名:path1)The installer will now close

    因为之前安装的是mysql8,我重新卸载后再安装mysql5.6时报错: Internal error (值不能为null.参数名:path1)The installer will now close ...

  2. insmod: error inserting '***.ko': -1 Invalid parameters 真正原因以及解决方法

    原因1 :的确是你的内核版本和你Makefile制定的不一样. 这个我就不谈了 原因二:是我们在确保了内核版本和我们Makefile指定的一样的情况下: 竟然还报错 insmod: error ins ...

  3. python函数参数定义顺序_Python函数定义-位置参数-返回值

    原标题:Python函数定义-位置参数-返回值 1 函数介绍 函数在编程语言中就是完成特定功能的一个词句组(代码块),这组语句可以作为一个单位使用,并且给它取一个名字.可以通过函数名在程序的不同地方多 ...

  4. db2自定义函数能返回几个参数_函数的定义、参数、返回值

    一.昨日内容回顾 昨日内容回顾 其他模式补充 r+ w+ a+ 文件内光标移动 在rt模式下read内n表示的读取字符的个数 其他情况及其他方法内n表示都是字节数 f.read(n) f.seek(o ...

  5. insmod: init_module ‘xxx.ko‘ failed (No such file or directory)

    linux 加载模块时遇到: insmod: init_module 'xxx.ko' failed (No such file or directory) 解决办法: 使用dmesg查看问题 dme ...

  6. 2020-09-22C++学习笔记之引用1(1.引用(普通引用)2.引用做函数参数 3.引用的意义 4.引用本质5.引用结论 6.函数返回值是引用(引用当左值)7测试代码)

    2020-09-22C++学习笔记之引用1(1.引用(普通引用)2.引用做函数参数 3.引用的意义 4.引用本质5.引用结论 6.函数返回值是引用(引用当左值)7测试代码) 1.引用(普通引用) 变量 ...

  7. MVC路由学习:自定义路由参数(用户看不到参数名),重新定义路由规则

    MVC路由:由于路由global中注册了,在程序第一次运行时,在MVC会自动生成路由,类似于字典的格式缓存下来,但路由生成的规则又是怎样的呢? 路由生成规则是: 1>更具你定义的的顺序查找路由规 ...

  8. php 去掉多维数组的键名,去除多维数组的最外层key 保留值

    如果你是要将JSON转成PHP数组,方法如下 首先,你这个数据格式是JSON的,要先转成PHP数组. $a = json_decode($a, TRUE); json_decode第二个参数为TRUE ...

  9. allure报告---动态显示模块名和用例标题

    一.allure报告动态参数化展示模块名和用例标题 使用@pytest.mark.parametrize 参数化完成数据驱动时,如果标题写死或者使用别名的方式 这样在报告中的可读性也不高 如何更美观的 ...

最新文章

  1. windows7、windows 2008和windows 2008 R2 的系统封装介绍
  2. R向量化操作(Data Transformations)
  3. sqoop 1.4.5 增量导入hive 0.12.0
  4. hp代码改成linux代码,HP Database Archiving Software远程任意代码执行漏洞
  5. Asp.Net Core Blazor之容器部署
  6. Tp框架中模板中if条件如何使用?
  7. (14)VHDL测试激励编写(时钟)
  8. Linux——vi的使用
  9. python 两个变量同时循环_python基础篇(子非鱼)
  10. 带你快速玩转canvas——写个折线图
  11. 《算法竞赛入门经典》——刘汝佳
  12. 用Python分析北京二手房房价
  13. linux+磁盘清理工具,linux centos 磁盘清理
  14. 物联网NB-IoT技术商用正全面铺开 竞争日趋激烈
  15. java 文件上传乱码_java上传txt文件,出现中文乱码
  16. 【CodingNoBorder - 04】无际软工队 - 求职岛:技术规格说明书
  17. 压力测试 闪存_[实验]苹果今年大范围使用的TLC闪存颗粒真的是那么不堪吗?
  18. 多项式插值中的一些定理证明
  19. 【教学类-17-01】20221122《世界杯七巧板A4整页-随机参考图+七巧板+画框》(大班)
  20. 刚刚开通,感受一下此地气氛

热门文章

  1. html 表格边框1像素,一像素边框表格的几种实现方法
  2. Python Day13 面向对象基础【初级】
  3. 泵站水闸自动化系统调试方案
  4. 如何制作一个音游鬼畜视频
  5. 带你了解常见的9种大数据分析方法
  6. Arctic开源!网易数帆×华泰证券,推动湖仓一体落地
  7. 苹果帝国会随着手机补贴取消而崩溃吗?
  8. js字符串空格转换符号
  9. 计算机系的学ansys吗,学ansys软件需要什么样的电脑配置才能运行?
  10. Java 实现多线程的四种方式 超详细