重新编译Linux内核踩的坑
来源:互联网 发布:知乎日报的rss 编辑:程序博客网 时间:2024/06/11 22:07
比较有意义的一次实验,坑都写在讨论与心得里。
实验目的
学习重建Linux内核。
学习Linux内核的系统调用,理解、掌握Linux系统调用的实现框架、用户界面、参数传递、进入/返回过程。阅读Linux内核源代码,通过添加一个简单的系统调用实验,进一步理解Linux操作系统处理系统调用的统一流程。了解Linux操作系统缺页处理,进一步掌握task_struct结构的作用。
实验内容
在现有的系统中添加一个不用传递参数的系统调用。这个系统调用的功能是实现统计操作系统缺页总次数、当前进程的缺页次数及每个进程的"脏"页面数,严格来说这里讲的"缺页次数"实际上是页错误次数,即调用do_page_fault函数的次数。实验主要内容:
- 在linux操作系统环境下重建内核
- 添加系统调用的名字
- 利用标准C库进行包装
- 添加系统调用号
- 在系统调用表中添加相应表项
- 修改统计缺页次数相关的内核结构和函数
- sys_mysyscall的实现
- 编写用户态测试程序
实验指导
完成实验后回答问题:
- 多次运行test程序,每次运行test后记录下系统缺页次数和当前进程缺页次数,给出这些数据。test程序打印的缺页次数是否就是操作系统原理上的缺页次数?有什么区别?
- 除了通过修改内核来添加一个系统调用外,还有其他的添加或修改一个系统调用的方法吗?如果有,请论述。
- 对于一个操作系统而言,你认为修改系统调用的方法安全吗?请发表你的观点。
实验报告
一、实验环境
二、实验内容和结果及分析
1、实验设计思路
本实验的前半部分按照老师的实验指导来就可以了,只要不发生误操作,就没有什么太大的问题。因此,这里主要对统计程序的设计思路做详细说明:
在实验指导中给出了pf和pfcount,所以实现缺页次数并不难,直接打印即可。那么怎么去统计脏页数呢?经过查阅资料发现task_struct中有一个数据成员叫做nr_dirtied,遍历所有进程,循环打印这个数据成员即可。
2、实验步骤及截图
3、测试程序运行结果截图
首先我们可以查看当前的内核版本:
再对比之前的内核版本:
说明成功吧4.10.0的内核换成了4.8.0。
然后去var/log/kern.log中查看程序输出结果:
可以看见,总的缺页次数是489725,当前进程的缺页次数是72,脏页数的部分截图如上(比较多,这里只截取了一部分)。
4、结果分析
5、源程序
首先是统计总的缺页次数、当前进程缺页次数以及各个进程脏页数的程序,这个程序比较特别的地方是要用task_struct中的nr_dirtied,如下所示:
/***********************************
*Project Name:实验2统计程序
*Author:
*Student ID:
*Last Modified: 2017/12.23
************************************/
externunsignedlong pfcount;//必须先申明其他地方定义的pfcount
asmlinkageint sys_mysyscall(void){
struct task_struct*p=NULL;//用来遍历进程
printk("<1>OSLab2 total page fault: %lu times\n",pfcount);//所有缺页次数
printk("<1>OSLab2 current process's page fault: %lu times\n",current->pf);//当前进程缺页次数
for(p=&init_task;(p=next_task(p))!=&init_task;){//循环打印各个进程脏页数
printk("<1>OSLab2 dirty page: %d\n pages",p->nr_dirtied);
}
return0;
}
然后是用户态程序这个程序比较简单,我没有输出到终端,而是直接/var/log/kern.log查看的,所以只需要调用223号系统调用即可:
/***********************************
*Project Name:实验2用户程序
*Author:
*Student ID:
*Last Modified: 2017/12.23
************************************/
#include <unistd.h>
#include <sys/syscall.h>
#define __NR_ mysyscall 223
int main(){
syscall(223);
}
三、讨论、心得(20分)
相比之下这个实验比实验1简单了不少,但是比较麻烦,需要很小心地操作,因为如果中间出了什么问题,再编译一遍内核可不是闹着玩的。为了顺利做出这个实验,在实验过程中我每做一步都比较小心,但还是出了很多问题。最后成功完成这个实验是在一个周五的晚上,我熬到了凌晨4点钟,守着机器把内核编译完,然后又解决了"客户机禁用CPU"的错误,才做成功的,重启成功的那一刻我简直都不想睡觉了,很激动。
下面是做这个实验的一些收获:
(1)libncurses5-dev是用来干嘛的?
在make menuconfig的时候会出现终端下的字符菜单,这个软件包就是为此提供支持作用的。
(2)怎么在启动时加载编译好的内核?
因为我客户机的内核是4.10,但是编译的却是4.8,而Ubuntu每次重启默认会启动最新的内核,也就是说每次机器都会加载4.10,而不是我编译好的4.8,这个问题开始很困扰我,我在网上搜到的做法是去改启动项,改grub文件等等。这样导致了很多错误,但后来发现其实只需要在虚拟机启动的时候按住Esc键就可以到启动菜单里去了,然后就能选择需要加载的内核版本了。如下图:
(3)重启后出现"客户机禁用CPU"的情况怎么办?
内核加载正常,本以为大功告成,但是VMWare却告诉我"客户机禁用CPU",经过查资料,发现这主要是配置文件的问题,需要手动进行修改,打开真机上安装虚拟机时留下的vmx文件,在里面加入这句话:
再重启就正常了。
(4)pf初始化的正确位置。这个实验中tsk->pf=0;这句代码的位置十分关键,如果加入的位置不当,做出来的缺页次数会很离谱(比如当前进程缺页数会有好几万)。
正确的位置如下图所示:
这是因为arch_dup_task_struct(tsk,orig)函数的关系,如果看一下这个函数怎么实现的话就会知道:
它直接把orig赋给了tsk,所以如果pf在上面初始化,子进程的pf就还是父进程的,不满足要求。
(5)最后是一个小经验:由于这个实验失败率比较高,所以make的时候如果追求速度的话可以用make -j2或者make -j4(甚至更高的CPU核心数,如果机器性能允许的话),虽然这样做在makefile的依赖关系写得不够好的情况下可能有风险,但是linux内核的makefile肯定是写得比较完美的,所以为了顺利完成实验,尽情地用多核编译吧!
最后回答几个问题:
1.多次运行test程序,每次运行test后记录下系统缺页次数和当前进程缺页次数,给出这些数据。test程序打印的缺页次数是否就是操作系统原理上的缺页次数?有什么区别?
答:我运行了10次test程序,结果记录如下:
次数
系统缺页数
当前进程缺页数
1
462445
73
2
464264
74
3
505757
73
4
506182
73
5
506698
73
6
512899
73
7
513841
73
8
514260
73
9
517156
73
10
518152
73
可以看到,每运行一次,系统缺页次数就会增加,而当前进程缺页次数则(几乎)保持不变。
test打印的缺页数不是操作系统原理上的缺页数,区别在于:...
2.除了通过修改内核来添加一个系统调用外,还有其他的添加或修改一个系统调用的方法吗?如果有,请论述。
答:...
3.对于一个操作系统而言,你认为修改系统调用的方法安全吗?请发表你的观点。
答:...
- 重新编译Linux内核踩的坑
- 重新编译linux内核
- linux 内核重新编译
- linux重新编译内核
- 重新编译Linux内核
- linux重新编译内核
- linux重新编译内核
- 如何重新编译linux内核
- 重新编译Kali Linux内核
- Debian Linux的 kernel(内核)的重新编译
- 录制了内核重新编译的视频,in linux-0.11
- linux为什么要重新编译内核
- 重新编译Linux内核必要性及其准备工作
- 重新编译Linux内核必要性及其准备工作
- 重新编译内核指南
- ubuntu重新编译内核
- 重新编译内核步骤
- 第一章-任务1:Linux内核的重新编译,安装,重启
- C#详解类型基础
- JavaWeb思维导图
- linux基本目录结构
- Windows下用Tensorflow中Android示例实现实时目标检测
- ASP浏览器版本检测+操作系统判断检测
- 重新编译Linux内核踩的坑
- python: return 函数
- Leetcode 刷题 Binary Search Easy难度经验总结
- 清澄A1051. DNA序列
- javascript兼容获取scrollLeft和scrollTop
- Sun的逆向之路(二)——FiF口语训练的刷分剖析
- 设计模式——模板方法模式
- 19. Remove Nth Node From End of List
- ssh框架思维导图