20135319zl内核模块编译报告
内核模块编程学习报告
1.编写一个简单的输出信息的模块
源代码:

Makefile

编译模块

加载模块

测试模块(dmesg)

卸载模块
Sudo rmmod 1
使用dmesg查看情况

2.输出当前进程信息
源代码(作为2.c)
修改makefile中的目标文件为2.o

编译,加载并测试模块

3.进程列表读取功能(3.c)
源代码

修改makefile为3.o
编译,加载并测试模块:

4.可读写的文件节点内核模块
在/proc文件系统中创建一个文件节点exp2
源代码
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h> // for basic filesystem
#include <linux/proc_fs.h> // for the proc filesystem
#include <linux/seq_file.h> // for sequence files
#include <linux/jiffies.h> // for jiffies
#include <linux/slab.h> // for kzalloc, kfree
#include <linux/uaccess.h> // for copy_from_user
//static struct task_struct *pcurrent;
int print_current_task_info(void);
// global var
static char *str = NULL;
// seq_operations -> show
static int jif_show(struct seq_file *m, void *v)
{
//seq_printf(m, "current kernel time is %llu\n", (unsigned long long) get_jiffies_64());
seq_printf(m, "str is %s\n", str);
return 0; //!! must be 0, or will show nothing T.T
}
// file_operations -> write
static ssize_t jif_write(struct file *file, const char __user *buffer, size_t count, loff_t *f_pos)
{
//分配临时缓冲区
char *tmp = kzalloc((count+1), GFP_KERNEL);
if (!tmp)
return -ENOMEM;
//将用户态write的字符串拷贝到内核空间
//copy_to|from_user(to,from,cnt)
if (copy_from_user(tmp, buffer, count)) {
kfree(tmp);
return -EFAULT;
}
//将str的旧空间释放,然后将tmp赋值给str
kfree(str);
str = tmp;
return count;
}
// seq_operations -> open
static int jif_open(struct inode *inode, struct file *file)
{
return single_open(file, jif_show, NULL);
}
static const struct file_operations jif_fops =
{
.owner = THIS_MODULE,
.open = jif_open,
.read = seq_read,
.write = jif_write,
.llseek = seq_lseek,
.release = single_release,
};
// module init
static int __init jif_init(void)
{
struct proc_dir_entry* jif_file;
jif_file = proc_create("exp2", 0, NULL, &jif_fops);
if (NULL == jif_file)
{
return -ENOMEM;
}
return 0;
}
// module exit
static void __exit jif_exit(void)
{
printk("******************************************\n");
remove_proc_entry("exp2", NULL);
kfree(str);
}
module_init(jif_init);
module_exit(jif_exit);
MODULE_AUTHOR("why");
MODULE_LICENSE("GPL");
编译,加载模块

往新建立的exp2文件中写入字符串”zhuli”,可见结果:

5.虚拟地址转换模块
源代码:
#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("Why");
MODULE_DESCRIPTION("GET WESSAGE");
源代码中find_pgd_init()为模块初始化函数,find_pgd_exit为模块析构函数。
代码中还定义了所要传入的参数,即所指定进程的进程号pid,数据类型为int,模块参数以module_param(name,type,perm)的形式定义,其中name为参数名,type为参数的数据类型,perm是一个权限值,控制谁可以存取模块参数在sysfs中的表示。此处还要注意的是要对内核模块的初始化函数和析构函数进行声明,即指明哪个函数是内核模块的初始化函数,哪个是内核模块的析构函数。
module_init()指明的是模块初始化函数,module_exit()指明的是模块析构函数。
MODULE LICENSE、MODULE_AUTHOR、MODULE_DESCRIPTION 分别为模块证书、模块作者和模块描述。
选取gedit验证模块
查询当前开启的gedit的pid

查询gedit的虚拟地址

可见此时gedit的pid为5207,虚拟地址的16进制表示为0x805e604,使用计算器转换为10进制为134604292
编译,加载并测试模块,可见:(加载模块时需要做如下操作)

测试结果:

可见,输出序列为53,83,ec ,08…

验证模块功能
6.使用文件节点存储页表查询结果
源代码:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h> // for basic filesystem
#include <linux/proc_fs.h> // for the proc filesystem
#include <linux/seq_file.h> // for sequence files
#include <linux/jiffies.h> // for jiffies
#include <linux/slab.h> // for kzalloc, kfree
#include <linux/uaccess.h> // for copy_from_user
#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
static unsigned long pid=5263;
static unsigned long va=134604292;
int i=0;
unsigned long pa = 0;
//static struct task_struct *pcurrent;
int print_current_task_info(void);
static int jif_show(struct seq_file *m, void *v);
// global var
//static char *str = NULL;
// file_operations -> write
static ssize_t jif_write(struct file *file, const char __user *buffer, size_t count, loff_t *f_pos)
{
unsigned long *tmp = kzalloc((count+1), GFP_KERNEL);
if (!tmp)
return -ENOMEM;
//copy_to|from_user(to,from,cnt)
if (copy_from_user(tmp, buffer, count)) {
kfree(tmp);
return -EFAULT;
}
kfree(tmp);
//pid = *tmp;
return count;
}
// seq_operations -> open
static int jif_open(struct inode *inode, struct file *file)
{
return single_open(file, jif_show, NULL);
}
static const struct file_operations jif_fops =
{
.owner = THIS_MODULE,
.open = jif_open,
.read = seq_read,
.write = jif_write,
.llseek = seq_lseek,
.release = single_release,
};
// module init
static int __init jif_init(void)
{
struct proc_dir_entry* jif_file;
jif_file = proc_create("exp4", 0, NULL, &jif_fops);
if (NULL == jif_file)
{
return -ENOMEM;
}
return 0;
}
// module exit
static void __exit jif_exit(void)
{
printk("******************************************\n");
remove_proc_entry("exp4", NULL);
kfree(pid);
}
static int find_pgd_init(struct seq_file *m)
{
struct task_struct *pcb_tmp = NULL;
pgd_t *pgd_tmp = NULL;
pte_t *pte_tmp = NULL;
pud_t *pud_tmp = NULL;
pmd_t *pmd_tmp = NULL;
seq_printf(m,"test:va=0x%lx,pid=%ld.\n",va,pid);
rcu_read_lock();
if(!(pcb_tmp = pid_task(find_vpid(pid),PIDTYPE_PID)))
{
seq_printf(m,"can not find pro %ld .\n", pid);
return 0;
}
rcu_read_unlock();
seq_printf(m,"ye_mu_lu_biao_ji_zhi = 0x%p\n",pcb_tmp->mm->pgd);
if(!find_vma(pcb_tmp->mm,va))
{
seq_printf(m,"xu_ni_di_zhi%lxbu_cun_zai\n",va);
return 0;
}
pgd_tmp=pgd_offset(pcb_tmp->mm,va);
seq_printf(m,"\npgd=----0x%p\n",pgd_tmp);
pud_tmp=pud_offset(pgd_tmp,va);
pmd_tmp=pmd_offset(pud_tmp,va);
pte_tmp=pte_offset_kernel(pmd_tmp,va);
seq_printf(m,"\npte=----0x%p\n",pte_tmp);
seq_printf(m,"\n\n pid=%ld\nva=%lx\n\n",pid,va);
pa=(pte_val(*pte_tmp)&PAGE_MASK)|(va&~PAGE_MASK);
seq_printf(m, "xu_ni_di_zhi %lx qi_zai_nei_cun_zhong %lx.\n",va,pa);
seq_printf(m, "bu_fen_nei_rong 0x%lx is 0x%lx.\n.\n",pa,pa);
for(i=0;i<40;i=i+4)
seq_printf(m,"\t%lx\n",*(unsigned long*)((char*)pa+PAGE_OFFSET+i));
return 0;
}
// seq_operations -> show
static int jif_show(struct seq_file *m, void *v)
{
//seq_printf(m, "current kernel time is %llu\n", (unsigned long long) get_jiffies_64());
//seq_printf(m, "str is %s\n", str);
find_pgd_init(m);
return 0; //!! must be 0, or will show nothing T.T
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ny");
MODULE_DESCRIPTION("GET WESSAGE");
module_init(jif_init);
module_exit(jif_exit);
其中参数pid和va在一开始写入源代码。
编译,加载模块后,直接显示创建的文件exp4内容,可见:

模块功能实现
20135319zl内核模块编译报告的更多相关文章
- linux/module.h: No such file or directory 内核模块编译过程
1.缺少Linux kernel头文件 To install just the headers in Ubuntu: sudo apt-get install linux-headers-$(unam ...
- linux内核模块编译makefile
linux内核可加载模块的makefile 在开发linux内核驱动时,免不了要接触到makefile的编写和修改,尽管网上的makefile模板一大堆,做一些简单的修改就能用到自己的项目上,但是,对 ...
- Ubuntu 编译安装 Linux 4.0.5 内核,并修复 vmware 网络内核模块编译错误
. . . . . 今天把 Ubuntu 14.04 升级到了最新的 4.0.5 的内核版本,本来不打算记录下来的,但是升级的过程中确实遇到了一些问题,所以还是记录下来,分享给遇到同样问题的猿友. 先 ...
- ubuntu下helloworld内核模块编译
1.hello.c #include<linux/init.h> #include<linux/module.h> MODULE_LICENSE("Dual BSD/ ...
- firefly rk3288 内核模块编译
在驱动开发的过程中,常常需要对代码进行返回的调试,如果返回的编译再烧写内核,势必会浪费开发人员大量的时间和心力,加班加点那是时常的事.为此linux提供了编译内核模块的方式,无需返回烧写内核,只需in ...
- 20135323符运锦----LINUX第二次实践:内核模块编译
Linux实践二--模块 一.知识点总结 ①Linux模块是一些可以作为独立程序来编译的函数和数据类型的集合.之所以提供模块机制,是因为Linux本身是一个单内核.单内核由于所有内容都集成在一起,效率 ...
- Android内核模块编译执行
Author: GeneBlue 0X01 前言 内核驱动是漏洞的高发区,了解Android驱动代码的编写是分析.利用驱动漏洞的基础.本文以一个"hello"驱动为例,简单介绍内核 ...
- Linux 4.1内核编译报告
编译环境 Arch Linux on VirtualBox 下载内核 https://www.kernel.org/ 下载的内核压缩包,此时的最新内核版本为4.1: 解压包 # tar -xvJf l ...
- Linux 内核模块编译 Makefile
驱动编译分为静态编译和动态编译:静态编译即为将驱动直接编译进内核,动态编译即为将驱动编译成模块. 而动态编译又分为两种: a -- 内部编译 在内核源码目录内编译 b -- 外部编译 在内核源码的目录 ...
随机推荐
- 用Solidity在Truffle上构建一个HelloWorld智能合约
原文地址:石匠的blog Truffle的环境安装在前文已经整理,这次用Solidity在Truffle写一个HelloWorld以太坊智能合约,并在testrpc上进行测试.当前的软件版本信息如下: ...
- Win7-64位PowerDesigner下MySQLODBC驱动问题
操作系统:win7-64位,PowerDesigner15.1(以下简称PD), MYSQL-ODBC-64驱动.安装完MYSQL-ODBC-64却找不到相关驱动,用PD反导数据库,却找不到Mysql ...
- Docker容器和本机之间的文件传输 使用Docker部署Tomcat项目
Docker容器和本机之间的文件传输. http://blog.csdn.net/leafage_m/article/details/72082011 使用Docker部署Tomcat项目 http: ...
- 团队冲刺--six
昨天: 司宇航:合并版块,但部分有缺陷. 马佳慧:研究css. 王金萱:写注册界面. 季方: 研究爬虫,精确的处理数据. 今天: 司宇航:测试功能版块,优化功能版块. 马佳慧:优化界面 . 王金萱: ...
- ### Error building SqlSession.
org.apache.ibatis.exceptions.PersistenceException: ### Error building SqlSession.### The error may e ...
- 第二阶段每日站立会议Second Day
昨天我在手机端安装cpp后进行界面效果测试以及进一步完善 今天对图片显示的大小进行调整 遇到的问题:当图片太小时,显示一块灰色区域,不美观
- Python数据结构练习
1. 给定列表L,如[2,5,3,8,10,1],对其进行升序排序并输出. 代码: list = [2,5,8,10,1] print(list) list.sort() print(list) 2. ...
- 文献:Technology-related Disasters:A Survey toward Disaster-resilient Software Defined Networks
DISASTER的定义和影响(本文中) 定义范围: 自然灾害,比如洪水.地震等造成一定范围类的节点故障: 恶意攻击,DDOS攻击或者电磁脉冲攻击造成节点故障: 技术相关的问题,配置错误或者误操作等: ...
- bata1
目录 组员情况 组员1(组长):胡绪佩 组员3:庄卉 组员4:家灿 组员5:凯琳 组员6:翟丹丹 组员7:何家伟 组员8:政演 组员9:黄鸿杰 组员10:刘一好 组员11:何宇恒 展示组内最新成果 团 ...
- JAVA异常架构图及常见面试题
红色为检查异常,就是eclipse要提示你是try catch 还是throws. 非检查异常,就是/0,nullpointexception,数据越界访问indexOfOutBounds 异常 错误 ...