这次的作业里面要求修改 Linux 内核代码,统计系统调用执行的次数。看 《Linux Kernel Development》 的第一版(我买的早,所以是第一版),在 entry.S 里面加了几行代码,然后实现个系统调用把统计数据提供给用户空间进程,还是很简单的。
先说点题外话,《Linux Kernel Development》 一年前没有学过 Linux 编程的时候看不懂,现在再看感觉好多了,是本内核入门非常不错的书。
不过发现了点奇怪的现象。(无知,所以才觉得奇怪啊)测试程序里面用 C 库提供的 syscall 来调用自己写的系统调用,无论调用多少次,自己的那个调用的执行次数统计始终为 0。但是如果使用 _syscall
宏来调用自己的系统调用,每次调用统计次数都会增加。(我在 2.6.20 的内核 asm/unistd.h
中没有找到 _syscall
宏,拿了老版本代码里面的宏来用。)看 glibc 的 syscall
代码没有看懂(glibc 真是复杂,看的头大,不过倒是知道了什么是 weak symbol)。拿了 LKD 的第二版再来看,看到里面提到一句 Linux 的系统调用在 x86 上现在有了一种新的出发机制,名字就叫 sysenter。sysenter 进入内核的代码在 sysenter.c 里,我只改了 entry.S 所以如果用户空间进程以 sysenter 进入内核则系统调用的统计数据当然不会有变化。问题应该就是出在这里了。
于是就开始 Google 了,找到一些文章,ibm developer works 的介绍,ChinaUnix 的一篇文章。马上来 fix 它。
想起去年暑假 IBM 的工程师凌棕说的一句话了,工程师只要找到问题,接下来就好解决了,难就难在怎样找到问题。再一次体会到了,不过这次运气还行,找到问题过程还算顺利。