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 -- 外部编译 在内核源码的目录 ...
随机推荐
- Gitlab CI-2.CI流程
参考文档: GitLab Documentation:https://docs.gitlab.com/ce/ Installation and Configuration using omnibus ...
- Geatpy遗传算法在曲线寻优上的初步探究
园子里关于遗传算法的教案不少,但基于geatpy框架的并未多见,故分享此文以作参考,还望广大园友多多指教! Geatpy出自三所名校联合团队之手,是遗传算法领域的权威框架(python),其效率之高. ...
- 07-matplotlib-箱线图
import numpy as np import matplotlib.pyplot as plt ''' 箱形图(Box-plot)又称为盒须图,盒式图,或 箱线图: 是一种用在显示一组数据分散情 ...
- “Hello World!”团队第五周第七次会议
博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七.燃尽图 八.checkout&push代码 一.会议时间 2017年11月16日 ...
- Scrum Meeting 10.22
Scrum Meeting No.2 今天的主要任务是配置安卓开发环境,并运行上一届的项目. 主流的安卓开发环境有eclipse+ADT+SDK和android studio两种.两种环境的文件架构似 ...
- python learning Network Programming.py
Socket # 用一个 Socke t表示"打开了一个网络连接" # 打开一个 Socket 需要知道目标计算机的IP地址和端口号,再指定协议类型即可. # TCP # 主动发起 ...
- 《软件工程和Python》PYTHON效能分析和Django
资料汇总网站:http://www.yzhiliao.com/my/course/55 一..作业下面两个题目任选一题: (1)运用jieba库分词(或者你喜欢的其他库),并把代码发到git上去(不发 ...
- Android开发中常见的内存泄露案例以及解决方法总结
1.单例模式引起的内存泄露 由于单例模式的静态特性,使得它的生命周期和我们的应用一样长,如果让单例无限制的持有Activity的强引用就会导致内存泄漏如错误代码示例: public class Use ...
- 关闭Centos5.5的写磁盘I/O功能
一个Linux文件默认有3个时间. atime:对此文件的访问时间. ctime:此文件inode发生变化的时间. mtime:此文件的修改时间. 如果有多个小文件(比如Web服务器的页面上有多个小图 ...
- 0422数学口袋精灵bug发现
团队成员的博客园地址: 蔡彩虹:http://home.cnblogs.com/u/caicaihong/ 曾治业:http://www.cnblogs.com/zzy999/ 蓝叶:http://w ...