实现insmod 模块名.ko 参数1=值 参数2=值 参数3=值.......

目标:

实现模块读取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会一直打印?????。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值