Linux实践二:模块
一、基本模块的实现:
1.进程遍历打印输出
2.简单地编写一个新的系统调用(替换空的系统调用号)
基本模块学到的知识点:
1.相关指令
make oldconfig 配置内核
make 编译内核
make modules_instal 编译安装内核模块
make install 引导新编译的内核
uname –a 查看内核版本
lsmod 查看加载的模块
insmod 加载模块
rmmod 卸载模块
dmesg 显示开机信息
基础模块一:系统调用(替换空的233)
文件Makefile
obj-m :=syscall.o
PWD := $(shell pwd)
KDIR:=/lib/modules/4.4.0-21-generic/build
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
uname -r 显示当前使用的内核信息,确定自己当前linux的内核版本是多少
测试代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned long x = 0;
x = syscall(223); //测试223号系统调用
printf("Hello, %ld\n", x);
return 0;
}

make -C $(LINUX_KERNEL_PATH) 指明跳转到内核源码目录下读取那里的Makefile
M=$(CURRENT_PATH) 表明返回到当前目录继续执行当前的Makefile。
头文件module.h,必须包含此文件;
头文件kernel.h,包含常用的内核函数;
头文件init.h包含宏_init和_exit,允许释放内核占用的内存。
基础模块二:进程遍历

二、深入
学习一:页表模块
基本思路:
1.研究学习学姐的实践指导书,由于新版本的Ubuntu需要的是四级页表,根据百度的一些知识,将学姐的代码由二级页表修改成四级页表
(重点是理解页表结构)
2.进一步修改页表,修改权限,使得用户态的可以变成内核态(研究中)。
对于页的保护通常设置一个存取控制字段。当这个字段占一位时,用于规定该页中的内 容允许写还是读;如果存取控制字段占两位,那么它可以表示存取控制为读写、只读和 只运行三种。当进程写一个只读页时,系统就会通过中断来报错。
模块参数以module_param(name,type,perm)的形式定义,其中name为参数名,type为参数的数据类型,perm是一个权限值,控制谁可以存取模块参数在sysfs中的表示。
页全局目录(Page Global Directory)
• 页上级目录(Page Upper Directory)
• 页中间目录(Page Middle Directory)
• 页表(Page Table)
页全局目录包含若干页上级目录的地址,页上级目录又依次包含若干页中间目录的地址,而页中间目录又包含若干页表的地址。每一个页表项指向一个页框。线性地址因此被分成五个部分。图中没有显示位数,因为每一部分的大小与具体的计算机体系结构有关。
#include <linux/module.h>
#include <asm/pgtable.h>
#include <linux/version.h>
#include <asm/page.h>
#include <linux/gfp.h>
#include <linux/page-flags.h>
#include <linux/sched.h>//find_task_by_vpid
#include <linux/mm.h>//find_vma MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("CONVERT USER VIRTUAL ADDRESS TO PHYADDRESS"); static int pid;
static unsigned long va; module_param(pid,int,0644);
module_param(va,ulong,0644); static int find_pgd_init(void)
{
unsigned long pa=0;
struct task_struct *pcb_tmp=NULL;
pgd_t *pgd_tmp=NULL;
pud_t *pud_tmp=NULL;
pmd_t *pmd_tmp=NULL;
pte_t *pte_tmp=NULL; printk(KERN_ALERT "test:va=0x%lx,pid=%d.\n",va,pid); rcu_read_lock();
if( !( pcb_tmp = pid_task(find_vpid(pid), PIDTYPE_PID) ) )
{
rcu_read_unlock();
printk(KERN_ALERT "Can't find the task %d.\n",pid);
return 0;
}
rcu_read_unlock(); printk("The page index_table address = 0x%p\n\n",pcb_tmp->mm->pgd); printk(KERN_ALERT "pgd=0x%p\n",pcb_tmp->mm->pgd);
if(!find_vma(pcb_tmp->mm,va))
{
printk(KERN_ALERT "virt_addr 0x%lx not available.\n",va);
return 0;
}
pgd_tmp=pgd_offset(pcb_tmp->mm,va);
printk(KERN_ALERT "pgd_tmp=0x%p\n",pgd_tmp);
printk(KERN_ALERT "pgd_val(*pgd_tmp)=0x%lx\n\n",pgd_val(*pgd_tmp));
if(pgd_none(*pgd_tmp))
{
printk(KERN_ALERT "Not mapped in pgd.\n");
return 0;
} pud_tmp=pud_offset(pgd_tmp,va);
pmd_tmp=pmd_offset(pud_tmp,va); pte_tmp=pte_offset_kernel(pmd_tmp,va);
if(pte_none(*pte_tmp))
{
printk(KERN_ALERT "Not mapped in pte.\n");
return 0;
}
if(!pte_present(*pte_tmp))
{
printk(KERN_ALERT "pte not in RAM,maybe swaped.\n");
return 0;
}
pa=(pte_val(*pte_tmp)&PAGE_MASK)|(va&~PAGE_MASK);
printk(KERN_ALERT "Virtual address: 0x%lx in RAM is 0x%lx.\n",va,pa);
printk(KERN_ALERT "Part content in 0x%lx is 0x%lx.\n",pa,*(unsigned long*)((char *)pa+PAGE_OFFSET));
int i;
printk("some content:\n");
for(i=0;i<40;i=i+4)
{
printk("%lx\n",*(unsigned long*)((char*)pa+PAGE_OFFSET+i));
}
return 0;
} static void find_pgd_exit(void)
{
printk(KERN_ALERT "Goodbye.\n");
} module_init(find_pgd_init);
module_exit(find_pgd_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("weiwei"); MODULE_DESCRIPTION("GET WESSAGE");

- 页全局目录(Page Global Directory)
- 页上级目录(Page Upper Directory)
- 页中间目录(Page Middle Directory)
- 页表(Page Table)
页全局目录包含若干页上级目录的地址,页上级目录又依次包含若干页中间目录的地址,而页中间目录又包含若干页表的地址。每一个页表项指向一个页框。线性地址因此被分成五个部分。


修改权限的思路,查看页表的读写,u/s的值,然后通过相关的设置函数进行修改
|
函数名称 |
说明 |
|
pte_user( ) |
读 User/Supervisor 标志。 |
|
pte_read( ) |
读 User/Supervisor 标志(表示 80x86 处理器上的页不受读的保护)。 |
|
pte_write( ) |
读 Read/Write 标志。 |
|
pte_exec( ) |
读 User/Supervisor 标志( 80x86 处理器上的页不受代码执行的保护)。 |
|
pte_dirty( ) |
读 Dirty 标志。 |
|
pte_young( ) |
读 Accessed 标志。 |
|
pte_file( ) |
读 Dirty 标志(当 Present 标志被清除而 Dirty 标志被设置时,页属于一个非线性磁盘文件映射)。 |
设置页表项中各标志的值的函数:
|
函数名称 |
说明 |
|
mk_pte_huge( ) |
设置页表项中的 Page Size 和 Present 标志。 |
|
pte_wrprotect( ) |
清除 Read/Write 标志。 |
|
pte_rdprotect( ) |
清除 User/Supervisor 标志。 |
|
pte_exprotect( ) |
清除 User/Supervisor 标志。 |
|
pte_mkwrite( ) |
设置 Read/Write 标志。 |
|
pte_mkread( ) |
设置 User/Supervisor 标志。 |
|
pte_mkexec( ) |
设置 User/Supervisor 标志。 |
|
pte_mkclean( ) |
清除 Dirty 标志。 |
|
pte_mkdirty( ) |
设置 Dirty 标志。 |
|
pte_mkold( ) |
清除 Accessed 标志(把此页标记为未访问)。 |
|
pte_mkyoung( ) |
设置 Accessed 标志(把此页标记为访问过)。 |
|
pte_modify(p,v) |
把页表项 p 的所有访问权限设置为指定的值 v 。 |
|
ptep_set_wrprotect() |
与 pte_wrprotect( ) 类似,但作用于指向页表项的指针。 |
|
ptep_set_access_flags( ) |
如果 Dirty 标志被设置为 1 则将页的访问权设置为指定的值,并调用flush_tlb_page() 函数。 |
|
ptep_mkdirty( ) |
与 pte_mkdirty( ) 类似,但作用于指向页表项的指针。 |
|
ptep_test_and_clear_dirty( ) |
与 pte_mkclean( ) 类似,但作用于指向页表项的指针并返回 Dirty 标志的旧值。 |
|
ptep_test_and_clear_young( ) |
与 pte_mkold( ) 类似,但作用于指向页表项的指针并返回 Accessed标志的旧值。 |
学习二:系统调用
学习三:进程模块
Linux实践二:模块的更多相关文章
- Linux及安全实践二——模块
Linux及安全实践二--模块 一.模块的编译.生成.测试.删除 1.编写模块代码 编写:gedit 3.c 2.编写Makefile obj-m :这个变量是指定你要声称哪些模块模块的格式为 obj ...
- LINUX实践之模块
模块实践 --关于模块代码部分 ---首先是.c代码: 一定会用到的函数有这几个:module_init().module_exit().MODULE_LICENSE() 会用到的头文件:module ...
- 20135337——Linux实践二:模块
一.编译&生成&测试&删除 1.编写模块代码,查看如下 gedit 1.c(编写) cat 1.c(查看) MODULE_AUTHOR("Z") MODUL ...
- 20135218 Linux 实践二 编译模块
20135218 姬梦馨 1.编写模块代码 模块构造函数:执行insmod或modprobe指令加载内核模块时会调用的初始化函数.函数原型必须是module_init(),括号内是函数指针 模块析构函 ...
- Linux实践:模块
标签(空格分隔): 20135321余佳源 一.实践原理 Linux模块是一些可以作为独立程序来编译的函数和数据类型的集合.之所以提供模块机制,是因为Linux本身是一个单内核.单内核由于所有内容都集 ...
- 【实践报告】Linux实践二
3.编译并安装内核与模块 sudo make bzImage –j3 编译内核 sudo make modules –j3 编译模块 sudo make modules ...
- linux内核分析实践二学习笔记
Linux实践二--内核模块的编译 标签(空格分隔): 20135328陈都 理解内核的作用 Linux内核[kernel]是整个操作系统的最底层,它负责整个硬件的驱动,以及提供各种系统所需的核心功能 ...
- Linux课程实践二:编译模块实现内核数据操控
一.内核模块原理 1. Linux内核增加功能 Linux内核整体结构很庞大,包含了很多的组件,现在有两种方法将需要的功能包含进内核当中: - 静态加载:将所有的功能都编译进Linux内核. - 动态 ...
- 《linux内核设计与实现》实践之模块及深入
<linux内核设计与实现>实践之模块及深入 写在前面的话. 基础模块部分我已经做完了,设计到的知识点无非就是,编写模块代码,编写Makefile文件,加载模块和卸载模块部分.由于大家都 ...
随机推荐
- 实验吧web解题记录
自以为sql注入掌握的还是比较系统的,然而,做了这些题之后才发现,大千世界无奇不有,真是各种猥琐的思路...还是要多学习学习姿势跟上节奏 登录一下好吗?? http://ctf5.shiyanbar. ...
- 8.1Python面向对象编程(一)
目录 目录 前言 (一)基本概念 ==1.面向过程与面向对象== ==2.类与对象== (二)类属性的相关操作 ==1.定义一个经典类== ==2.对象属性的操作== ==3.类属性的操作== ==4 ...
- ccf--20160403---路径解析
本题思路如下: 具体的细节如下:首先去掉字符串中重复出现的/,然后遇到..,就删除栈的最后一个元素,.忽略 下面是代码和题目: 问题描述 试题编号: 201604-3 试题名称: 路径解析 时间限制: ...
- swift class的动态派发
一.测试代码 class BaseCallClass{ func NormalCall(){} @objc func OcCall(){} @objc dynamic func OcDynamicCa ...
- 注册OCX失败/ 找不到指定的模块
错误信息:模块“*.OCX”加载失败,请确定二进制保存在指定的路径中,或者调试它以检查该二进制或相关的.dll文件是否有问题 对于电脑新手,关于OCX或DLL缺失是一件令人十分头疼的事,如果不幸遇到此 ...
- butter
题目描述 农夫John发现做出全威斯康辛州最甜的黄油的方法:糖.把糖放在一片牧场上,他知道N(1<=N<=500)只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油.当然,他将付出额外的费 ...
- php 请求另一个服务器接口返回数据
<?php /** * Created by PhpStorm. * User: thinkpad * Date: 2015/7/17 0017 * Time: 13:24 */ class A ...
- e 的由来
https://www.zhihu.com/question/20296247 对数的发现 很多科学家发现对数螺线在自然界中广泛存在.从大如星系.台风,到小如花朵.海螺……宇宙中到处都是对数螺线的身影
- gensurf
我来做个福利吧,首先将模糊文件.fis,加载到workspace中,这个大家都会,利用上面说的那个例子a = readfis('tipper');gensurf(a)这样默认的就是前两个输入的曲线,要 ...
- 理解Path对路径进行操作的API
阅读目录 一:理解normalize方法 二:理解join方法 三:理解dirname方法 四:理解basename方法 五:理解extname方法 回到顶部 一:理解normalize方法 该方法将 ...