返回值是没有拷贝成功的字节数,拷贝成功返回0。

static __always_inline unsigned long __must_check
copy_from_user(void *to, const void __user *from, unsigned long n)
{if (likely(check_copy_size(to, n, false)))n = _copy_from_user(to, from, n); return n;
}

通过/proc/hook/hook_control传入的命令行参数,总共count个字节,其中count包含命令行中输入的回车符,在做参数解析时需要将最后一个字节替换成00。

# 0a -> 00[  109.100142] Module init
[  126.618392] raw data: 0000000037ecc164: 76 66 73 5f 72 65 61 64 20 31 20 32 20 33 0a     vfs_read 1 2 3.[  772.658773] Module init
[  775.256314] raw data: 000000007f19446e: 76 66 73 5f 72 65 61 64 20 31 20 32 20 33 00     vfs_read 1 2 3.

proc_writ返回值为写成功的字节数,如果返回值为0,会一直重试写?

ssize_t (*proc_write)(struct file *, const char __user *, size_t, loff_t *);

Linux 内核中的字符串分割函数lib/string.c

#ifndef __HAVE_ARCH_STRSEP
/*** strsep - Split a string into tokens* @s: The string to be searched* @ct: The characters to search for** strsep() updates @s to point after the token, ready for the next call.** It returns empty tokens, too, behaving exactly like the libc function* of that name. In fact, it was stolen from glibc2 and de-fancy-fied.* Same semantics, slimmer shape. ;)*/
char *strsep(char **s, const char *ct)
{char *sbegin = *s;char *end;if (sbegin == NULL)return NULL;end = strpbrk(sbegin, ct); if (end)*end++ = '\0';*s = end; return sbegin;
}
EXPORT_SYMBOL(strsep);
#endif

内存拷贝函数memcpy

#ifndef __HAVE_ARCH_MEMCPY
/*** memcpy - Copy one area of memory to another* @dest: Where to copy to* @src: Where to copy from * @count: The size of the area.** You should not use this function to access IO space, use memcpy_toio()* or memcpy_fromio() instead.*/
void *memcpy(void *dest, const void *src, size_t count)
{char *tmp = dest;const char *s = src; while (count--)*tmp++ = *s++;return dest;
}
EXPORT_SYMBOL(memcpy);
#endif

Linux 内核将字符类型转换成整型/lib/string.c

/*** kstrtoint - convert a string to an int * @s: The start of the string. The string must be null-terminated, and may also*  include a single newline before its terminating null. The first character*  may also be a plus sign or a minus sign.* @base: The number base to use. The maximum supported base is 16. If base is*  given as 0, then the base of the string is automatically detected with the *  conventional semantics - If it begins with 0x the number will be parsed as a*  hexadecimal (case insensitive), if it otherwise begins with 0, it will be*  parsed as an octal number. Otherwise it will be parsed as a decimal.* @res: Where to write the result of the conversion on success.** Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.* Preferred over simple_strtol(). Return code must be checked.*/
int kstrtoint(const char *s, unsigned int base, int *res)
{long long tmp;int rv; rv = kstrtoll(s, base, &tmp);if (rv < 0)return rv; if (tmp != (int)tmp)return -ERANGE;*res = tmp;return 0;
}
EXPORT_SYMBOL(kstrtoint);

proc_interface.c

#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/uaccess.h>#define MAX_PARAM 5
#define MAX_STRING_LEN 64static struct proc_dir_entry *parent;
static struct proc_dir_entry *node;// single_open的回调函数,实现了seq_operaions的show实例
static int show_proc_info(struct seq_file *p, void *v)
{seq_printf(p, "%s\n", "Seq_printf test string");return 0;
}static int hook_open(struct inode *inode, struct file *file)
{return single_open(file, show_proc_info, NULL);
}static void get_param(char *buffer, int *argc, char (*argv)[MAX_STRING_LEN])
{unsigned int index = 0;char *token = NULL;while ((token = strsep(&buffer, " ")) != NULL) {memcpy(argv[index], token, MAX_STRING_LEN);index++;}   *argc = index;
}static ssize_t hook_write(struct file *file, const char __user *buffer,size_t count, loff_t *pos)
{int number;char *tmp = NULL;int argc, ret = 0;char argv[MAX_PARAM][MAX_STRING_LEN];tmp = (char *)kmalloc(PAGE_SIZE, GFP_KERNEL);if (!tmp) {ret = -ENOMEM;goto out;}   memset((char*)tmp, 0, PAGE_SIZE);ret = copy_from_user(tmp, buffer, count);if (ret) {ret = -EFAULT;goto out;}// 用户态输入的buffer还包含回车符,替换成\0tmp[count -1] = '\0';print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,16, 1, tmp, count, true);get_param(tmp, &argc, argv);if (argc >= MAX_PARAM) {ret = EINVAL;goto out;}printk("argc -> %d argv[0] -> %s argv[1] -> %s\n",argc, argv[0], argv[1]);if (kstrtoint(argv[1], 0, &number)) {printk("Trans string to int failed\n");goto out;}printk("argc -> %d number -> %d\n", argc, number);out:kfree(tmp);return count;
}static int hook_release(struct inode *inode, struct file *file)
{return single_release(inode, file);
}// .proc_read初始化为seq_read,如果自己实现,将会导致seq_printf失效。
static const struct proc_ops hook_fops = {.proc_open = hook_open,.proc_read = seq_read,.proc_write = hook_write,.proc_release = hook_release,
};int proc_interface_init(void)
{parent = proc_mkdir("hook", NULL);if (IS_ERR(parent)) {printk("Create /proc/hook dir failed\n");return -1;}node = proc_create("hook_control", 0, parent, &hook_fops);if (IS_ERR(node)) {printk("Create /proc/hook/hook_control failed\n");goto out;}return 0;
out:remove_proc_entry("hook", NULL);return -1;
}void proc_interface_exit(void)
{proc_remove(parent);
}

module.c

#include <linux/module.h>extern int proc_interface_init(void);
extern void proc_interface_exit(void);static int __init proc_fs_init(void)
{int ret = 0;printk("Module init\n");ret = proc_interface_init();    if (ret != 0) {return -1; }   return 0;
}static void __exit proc_fs_exit(void)
{proc_interface_exit();printk("Module exit\n");
}module_init(proc_fs_init);
module_exit(proc_fs_exit);MODULE_LICENSE("GPL");

Makefile

obj-m := proc_control.oproc_control-y += module.o
proc_control-y += proc_interface.oBASEINCLUDE ?= /lib/modules/`uname -r`/buildall:$(MAKE) -C $(BASEINCLUDE) M=$(PWD) modules;clean:$(MAKE) -C $(BASEINCLUDE) M=$(PWD) clean;rm -f *.ko;

查看内核打印信息

[ 1562.028889] raw data: 00000000c77375f0: 76 66 73 5f 72 65 61 64 20 31 20 31 20 31 00     vfs_read 1 1 1.
[ 1562.028892] argc -> 4 argv[0] -> vfs_read argv[1] -> 1
[ 1562.028893] argc -> 4 number -> 1

procfs 命令行参数解析相关推荐

  1. 【Qt】通过QtCreator源码学习Qt(六):命令行参数解析实现

    参考下大神的命令行参数解析是如何是实现的 //使用const char []代替宏定义字符串,我以前都是用const QString,想想好傻 const char SETTINGS_OPTION[] ...

  2. python命令行参数解析OptionParser类用法实例

    python命令行参数解析OptionParser类用法实例 本文实例讲述了python命令行参数解析OptionParser类的用法,分享给大家供大家参考. 具体代码如下:     from opt ...

  3. 3gpp文件头文件解析_居于LLVM 的命令行参数解析

    在写命令行程序的时候经常需要解析各种命令行参数.打印help信息等,觉得非常的麻烦.今天介绍一种超级棒的命令参数解析的方法:居于LLVM 的命令行参数解析,有了它妈妈再也不用担心我不会解析命令行参数^ ...

  4. Python命令行参数解析模块------argparse

      首先,argparse 是python自带的命令行参数解析包,可以用来方便地读取命令行参数,当你的代码需要频繁地修改参数的时候,使用这个工具可以将参数和代码分离开来,让你的代码更简洁,适用范围更广 ...

  5. 编程模板-R语言脚本写作:最简单的统计与绘图,包安装、命令行参数解析、文件读取、表格和矢量图输出

    写在前面 个人认为:是否能熟悉使用Shell(项目流程搭建)+R(数据统计与可视化)+Perl/Python等(胶水语言,数据格式转换,软件间衔接)三门语言是一位合格生物信息工程师的标准. 之前分享过 ...

  6. Python中最好用的命令行参数解析工具

    Python 做为一个脚本语言,可以很方便地写各种工具.当你在服务端要运行一个工具或服务时,输入参数似乎是一种硬需(当然你也可以通过配置文件来实现). 如果要以命令行执行,那你需要解析一个命令行参数解 ...

  7. python 命令行参数-Python 中最好用的命令行参数解析工具

    Python 做为一个脚本语言,可以很方便地写各种工具.当你在服务端要运行一个工具或服务时,输入参数似乎是一种硬需(当然你也可以通过配置文件来实现). 如果要以命令行执行,那你需要一个命令行参数解析的 ...

  8. linux shell中的命令自动补全(compgen complete)与 命令行参数解析

    linux shell中的命令自动补全(compgen complete)与 命令行参数解析 标签: shell脚本 2013-12-31 21:56 6661人阅读 评论(6) 收藏 举报 分类: ...

  9. GO标准库—命令行参数解析FLAG

    评论有人提到没有例子,不知道讲的是什么.因此,为了大家能够更好地理解,特意加了一个示例.其实本文更多讲解的是 flag 的实现原理,加上示例之后,就更好地知道怎么使用了.建议阅读 <Go语言标准 ...

最新文章

  1. mysql-plus 动态修改全局sql, 进行数据隔离, 多租户, 多字段修改
  2. DevExpress v17.2新版亮点—ASP.NET篇(二)
  3. 输入分钟输出小时python_输出键,值对如何使1小时内的时间在使用Python的MapReduce中的reducer中结束?...
  4. XML类型的SQL参数
  5. python sys.modules
  6. jq自动获取html的值,jquery如何获取class值?
  7. 我可以获得标记为--assume-unchanged的文件列表吗?
  8. FISCO BCOS 智能合约 可视化数据库 Mysql MariaDB
  9. ftp导入oracle,ftp向linux虚拟机传oracle安装包
  10. 用户故事与敏捷方法笔记---搜集故事
  11. DOSBox安装及使用教程
  12. 前端 js 基于react ts的excel文件模板下载 文件导入、导出
  13. JAVA设计模式笔记(简单工厂模式)
  14. cad lisp 二次抛物线_cad画二次抛物线
  15. 张飞老师硬件第六部视频整理——电源——开关电源
  16. 1-计算机系统概述(CO)
  17. 浙大和上海交大计算机系哪个好,不考虑区位,浙江大学和上海交通大学哪个更好一些?...
  18. 基于FPGA的数字视频信号处理器设计(中)
  19. oracle一直在更新注册表,联想10代cpu电脑装win7后卡在正在更新注册表设置解决方法...
  20. 口腔专科医院系统:要抠出用户的需求

热门文章

  1. 动量风险因子 matlab,期货市场存在较强的时间序列动量效应
  2. 如何为使用Python语言而辩论
  3. PCB板材知识及标准
  4. 死磕Ubuntu18(完)
  5. bzoj AC100~~~
  6. 【 ros wiki 】英文教程 18:Reading messages from a bag file 翻译
  7. 第 5 章 ROS 常用组件 2 —— TF 坐标变换_多坐标变换 tf03_tfs(重难点)
  8. 【Docker技术入门与实践(第2版)】Docker入门_学习笔记
  9. 【Web安全】应用层拒绝服务攻击
  10. 非常难得的iPad版房地产售楼助手应用