一、编译&生成&测试&删除

1.编写模块代码,查看如下

gedit 1.c(编写)
cat 1.c(查看)

MODULE_AUTHOR("Z")
MODULE_DESCRIPTION(模块用途的简单描述);
MODULE_VERSION(模块的版本字符串);
MODULE_ALIAS(模块的别名);

2.查看版本信息

3.写Makefile并查看

obj-m :这个变量是指定你要声称哪些模块模块的格式为 obj-m := <模块名>.o
modules-objs :这个变量是说明声称模块modules需要的目标文件 格式要求 <模块名>-objs := <目标文件>
切记:模块的名字不能取与目标文件相同的名字。如在这里模块名不能取成 mymod;
KDIR :这是我们正在运行的操作系统内核编译目录。也就是编译模块需要的环境
M= :指定我们源文件的位置
PWD :这是当前工作路径$(shell )是make的一个内置函数。用来执行shell命令。

4.make自动生成很多文件

5.加载、测试、删除模块

dmesg(查看内核信息)
  • 加载、测试模块

  • 卸载模块

  • 其他



dmesg | tail -12  查看内核输出信息;tail -12 显示最后12条。

modinfo查看模块信息:
sudo modinfo 1.ko depmod分析可加载模块的依赖性,并生成modules.dep文件和映射文件
modprobe Linux内核添加删除模块

二、系统调用(增加223号)

1.查看本机系统调用表地址

查看系统调用号



2.源码(详细代码略)、测试程序

测试程序
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned long x = 0;
x = syscall(223);
printf("Hello, %ld\n", x);
return 0;
}

分析

代码
static int clear_cr0(void)  //使cr0寄存器的第17位设置为0(即是内核空间可写)
{
unsigned int cr0 = 0;
unsigned int ret;
asm volatile ("movl %%cr0, %%eax":"=a"(cr0)); //将cr0寄存器的值移动到eax的寄存器中,同时输出到cr0变量中
ret = cr0;
cr0 &= 0xfffeffff; //将cr0变量的值中的第17位清0,一会将修改后的值写入cr0寄存器
asm volatile ("movl %%eax, %%cr0": :"a"(cr0)); //将cr0变量的值做为输入,输入到寄存器eax中,同时移动到寄存器cr0中
return ret;
} static int __init call_init(void)
{
sys_call_table_my = (unsigned long*)(SYS_CALL_TABLE_ADDRESS);
printk("call_init.......\n");
anything_saved = (int (*)(void))(sys_call_table_my[NUM]); //保存系统调用表中的NUM位置上的系统调用
orig_cr0 = clear_cr0(); //使内核地址空间可写
sys_call_table_my[NUM] =(unsigned long) &sys_mycall; //用自己的系统调用替换NUM位置上的系统调用
setback_cr0(orig_cr0); //使内核地址空间不可写
return 0;
}
asm volatile("movl %%eax,%%cr0"::"a"(val));
举例说明:volatile int i=10; int j = i; ... int k = i; volatile 告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的可执行码会重新从i的地址读取数据放在k中。 volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化。)。其中编译器编译优化是:由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在k中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问,不会出错。
模块加载函数static int __init call_init(void):先保存系统调用表中223位置的系统调用,然后用static int clear_cr0(void)清零cr0的第十六        位,使内核空间可写,在内核空间可写的情况下用自己的系统调用asmlinkage long sys_mycall(void)替换223位置的系统调用,在完成替换后重新将cr0第十六位置位static void setback_cr0(int val)。
模块卸载函数static void __exit call_exit(void):用static int clear_cr0(void)清零cr0的第十六位,使内核空间可写,将保存的系统调用anything_saved恢复,完成后重新将cr0第十六位置位static void setback_cr0(int val)。

3.结果

测试代码为52.c
编译gcc 52.c -o b
运行 ./b



三、增加模块,功能:存在某指定文件,则输出“open success”,否则输出“open error”

    asmlinkage long sys_mycall(void)  //定义自己的系统调用
{
struct file *fp;
fp = filp_open("/home/zhu/mm", O_RDWR, 0644); //打开指定的文件
if (IS_ERR(fp)) //如果失败,输出“error”
{
printk("open error!!!!!!!!!!!!!!!!!!!!!!!!!\n");
return 0;
}
else //成功,输出“success”
{
printk("open success!!!!!!!!!!!!!!!!!!!!!!!\n");
}
return 0;
}
make
sudo insmod XXX.ko
./test.c

四、asmlinkage

0.函数定义前加宏asmlinkage ,表示这些函数通过堆栈而不是通过寄存器传递参数。

1.gcc编译器在汇编过程中调用c语言函数时传递参数有两种方法:一种是通过堆栈,另一种是通过寄存器。缺省时采用寄存器,假如你要在你的汇编过程中调用c语言函数,并且想通过堆栈传递参数,你定义的c函数时要在函数前加上宏asmlinkage。

1.采用asmlinkage,绝对不是因为不同架构可以通用户,而是因为用户态寄存器在系统调用进入内核态时,会把用户态的寄存器全部压栈,通过合理的构造。正好满足用户态通过寄存器传递参数,内核态通过栈取参数的标准要求。这是很巧妙的安排,是高效的体现!其实还可以发现,内核只有在系统调用时才用asmlinkage,其它函数都没有。这是有意而为之的。

2.用户调用syscall的时候,参数都是通过寄存器传进来的。中间内核由把所有的参数压栈了, 所以这个asmlinkage可以通过到gcc,恰好可以用正确的调用方式取到参数。(系统调用做的工作除了函数调用,其本质就是现场保护、压栈之类的操作)

3.内核前面的那些统一处理很重要,这样后端真正的的syscall 实现函数就可以得到统一的调用方式了,而不是之间面对不同的abi。确实比较方便了。不然每个syscall函数里面都要自己去处理不同abi,多很多重复代码。

4.也可以考虑在这个统一的处理的时候,把参数全部按照一定的规范放到寄存器。 但这个方法不能在所有的cpu架构上面都做的到。

5.“统一”要比这个“寄存器传参”要重要。

6.从用户切换到内核,要做大量的处理。相比较其他部分,参数的开销不算什么。

20135337——Linux实践二:模块的更多相关文章

  1. Linux及安全实践二——模块

    Linux及安全实践二--模块 一.模块的编译.生成.测试.删除 1.编写模块代码 编写:gedit 3.c 2.编写Makefile obj-m :这个变量是指定你要声称哪些模块模块的格式为 obj ...

  2. LINUX实践之模块

    模块实践 --关于模块代码部分 ---首先是.c代码: 一定会用到的函数有这几个:module_init().module_exit().MODULE_LICENSE() 会用到的头文件:module ...

  3. Linux实践二:模块

    一.基本模块的实现: 1.进程遍历打印输出 2.简单地编写一个新的系统调用(替换空的系统调用号) 基本模块学到的知识点: 1.相关指令 make oldconfig 配置内核 make 编译内核 ma ...

  4. 20135218 Linux 实践二 编译模块

    20135218 姬梦馨 1.编写模块代码 模块构造函数:执行insmod或modprobe指令加载内核模块时会调用的初始化函数.函数原型必须是module_init(),括号内是函数指针 模块析构函 ...

  5. Linux实践:模块

    标签(空格分隔): 20135321余佳源 一.实践原理 Linux模块是一些可以作为独立程序来编译的函数和数据类型的集合.之所以提供模块机制,是因为Linux本身是一个单内核.单内核由于所有内容都集 ...

  6. 【实践报告】Linux实践二

    3.编译并安装内核与模块 sudo make bzImage –j3         编译内核 sudo make modules –j3         编译模块 sudo make modules ...

  7. 20135337——linux实践三:ELF文件格式分析(32位系统)

    ELF文件格式分析 可重定位文件 十六进制形式显示内容 显示各个段.符号表相关信息 查看各个段信息 elf文件头信息 段表 符号表信息 查看堆栈 具体分析 1.ELF文件头信息(小字节优先,均十六进制 ...

  8. 20135337——Linux实践三:程序破解

    程序破解 查看 运行 反汇编,查看汇编码 对反汇编代码进行分析: 在main函数的汇编代码中可以看出程序在调用"scanf"函数请求输入之后,对 [esp+0x1c] 和 [esp ...

  9. 20135337——Linux实践三:ELF文件格式(64位系统,简单分析)

    ELF文件格式简单分析 (具体分析见上一篇ELF文件格式32位系统) ELF-header 第一行: 457f 464c :魔数: 0201 :64位系统,小端法 01 :文件头版本 剩余默认0: 第 ...

随机推荐

  1. Hadoop2.7.6_03_HDFS原理

    1. HDFS前言 l  设计思想 分而治之:将大文件.大批量文件,分布式存放在大量服务器上,以便于采取分而治之的方式对海量数据进行运算分析: l  在大数据系统中作用: 为各类分布式运算框架(如:m ...

  2. emacs org-mode文件转html文件

    Table of Contents 1. 发布站点 by emacs org-mode 1.1 org-mode 自带的导出方法 1.2 批量导出 1.3 css 美化 1.4 导出html 1. 发 ...

  3. 罗马数字转整数的golang实现

    罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I V X L C D M 例如, 罗马数字 2 写做 II ,即为两个并列的 1.12 写做 XII ,即为 X + ...

  4. pb中遍历查询数据库数据问题(数据库为 sql server)

    指针可以实现但是不推荐 例如:(部分代码) for ll_a = 1 to ll_count    ll_b = ll_i +  ll_a  //插入行行号先下移一位    dw_main.inser ...

  5. BSOJ 4591 -- 【JLOI2015】城池攻占

    Description 小铭铭最近获得了一副新的桌游,游戏中需要用m个骑士攻占n个城池. 这n个城池用1到n的整数表示.除1号城池外,城池i会受到另一座城池fi的管辖,其中fi 每个城池有一个防御值h ...

  6. 无根树的计数——prufer序列

    参考博客https://www.cnblogs.com/dirge/p/5503289.html (1)prufer数列是一种无根树的编码表示,类似于hash. 一棵n个节点带编号的无根树,对应唯一串 ...

  7. C#的深拷贝和浅拷贝

    也许会有人这样解释C# 中浅拷贝与深拷贝区别: 浅拷贝是对引用类型拷贝地址,对值类型直接进行拷贝. 不能说它完全错误,但至少还不够严谨.比如:string 类型咋说? 其实,我们可以通过实践来寻找答案 ...

  8. luogu P5151 HKE与他的小朋友

    嘟嘟嘟 看到\(i\)变成了\(A_i\),我突然想起了置换这个东西.于是马上到网上学了一遍轮换乘法. 手模后发现轮换乘法满足结合律,但不满足交换律. 于是就可以快速幂啦. 需要注意的是每一次相乘是\ ...

  9. QT数据类型

    typedef signed char        int8_t;typedef short              int16_t;typedef int                int3 ...

  10. WordPress数据库及各表结构分析

    默认WordPress一共有以下11个表.这里加上了默认的表前缀 wp_ . wp_commentmeta:存储评论的元数据wp_comments:存储评论wp_links:存储友情链接(Blogro ...