一、基本模块的实现:

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实践二:模块的更多相关文章

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

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

  2. LINUX实践之模块

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

  3. 20135337——Linux实践二:模块

    一.编译&生成&测试&删除 1.编写模块代码,查看如下 gedit 1.c(编写) cat 1.c(查看) MODULE_AUTHOR("Z") MODUL ...

  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. linux内核分析实践二学习笔记

    Linux实践二--内核模块的编译 标签(空格分隔): 20135328陈都 理解内核的作用 Linux内核[kernel]是整个操作系统的最底层,它负责整个硬件的驱动,以及提供各种系统所需的核心功能 ...

  8. Linux课程实践二:编译模块实现内核数据操控

    一.内核模块原理 1. Linux内核增加功能 Linux内核整体结构很庞大,包含了很多的组件,现在有两种方法将需要的功能包含进内核当中: - 静态加载:将所有的功能都编译进Linux内核. - 动态 ...

  9. 《linux内核设计与实现》实践之模块及深入

     <linux内核设计与实现>实践之模块及深入 写在前面的话. 基础模块部分我已经做完了,设计到的知识点无非就是,编写模块代码,编写Makefile文件,加载模块和卸载模块部分.由于大家都 ...

随机推荐

  1. Sql Server 只有MDF文件恢复数据库的方法以及2008清除日志文件

    首先建立同名的空数据库,然后停止数据库服务运行,将MDF文件覆盖后启动服务,并修改和执行下面的语句. alter database JinMa_NYGL set EMERGENCY alter dat ...

  2. 关于plist文件的那些事

    今天遇到新生问一个问题,就是用自己定义了一个plist文件,然后可以往里面写东西,但是写过再次运行的时候里面的数据总是最后一次写入的数据.后来就专门研究了一下plist文件. 大家都知道当你创建一个项 ...

  3. 【转】vue项目打包部署——nginx代理访问

    我又来了,今天部署了下vue项目,使用nginx做了代理,这样可以解决跨域的问题,这里做一个简单讲解. 1.先看vue项目打包(我这里使用的是vscode开发工具) 这里是我的项目结构: 打包之前需要 ...

  4. 【洛谷】【搜索+剪枝】P1731 [NOI1999]生日蛋糕

    [题目背景:] 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体. [题目描述:] 设从下往上数第i(1<=i<=M)层蛋糕是半径为Ri ...

  5. 使用ElasticSearch服务从MySQL同步数据实现搜索即时提示与全文搜索功能

    最近用了几天时间为公司项目集成了全文搜索引擎,项目初步目标是用于搜索框的即时提示.数据需要从MySQL中同步过来,因为数据不小,因此需要考虑初次同步后进行持续的增量同步.这里用到的开源服务就是Elas ...

  6. PHP 使用 ElasticSearch

    环境 php 7.2elasticsearch 6.2 下载elasticsearch-php 6 下载 安装 elasticsearch 下载源文件,解压,重新建一个用户,将目录的所属组修改为此用户 ...

  7. kubernetes statefulset kafka 部署后, 外部访问超时问题解决

    k8s 内部的kafka要映射到外网,直接把 kafka 通过 expose 把pod 映射成服务,使用nodeport 连接,出现超时问题, 解决思路: 1.  查看zk中,kafka的注册信息,P ...

  8. 转载 .Net多线程编程—任务Task https://www.cnblogs.com/hdwgxz/p/6258014.html

    .Net多线程编程—任务Task   1 System.Threading.Tasks.Task简介 一个Task表示一个异步操作,Task的创建和执行是独立的. 只读属性: 返回值 名称 说明 ob ...

  9. PAT A1124 Raffle for Weibo Followers (20 分)——数学题

    John got a full mark on PAT. He was so happy that he decided to hold a raffle(抽奖) for his followers ...

  10. B-Tree外存数据结构 _(外存储器—磁盘)第一部分

    1.外存储器—磁盘 计算机存储设备一般分为两种:内存储器(main memory)和外存储器(external memory).内存存取速度快,但容量小,价格昂贵,而且不能长期保存数据(在不通电情况下 ...