ubuntu12.04下添加系统调用+编译内核

这学期修了《Linux内核设计与实现》的学位课,老师讲完第5章系统调用后,表示无论如何都要我们实践添加一个系统调用。于是我在虚拟机上64位的ubuntu12.04lts环境下开始添加系统调用。

首先,更新:

sudo apt-get update
sudo apt-get upgrade

由于ubuntu本身不带Linux源码,所以我们可以通过以下命令来很方便的把Linux的源码安装到/usr/src目录下:

sudo apt-get install linux-source

现在ubuntu的/usr/src下,这里默认安装的linux-source-3.2.0,进入该文件夹把linux-source-3.2.0.tar.bz2解压到某个文件夹下,这里我解压到了/home/gouchaoer路径下。

为了编译内核我们还需要gcc,以及ncurses开发包:

sudo apt-get install gcc
sudo apt-get install libncurses5-dev

接下来我们开始添加sys_hello系统调用。

在Linux源码根目录下我们找到arch/x86/kernel/syscall_table_32.S,打开并且在结尾加上:

.long sys_hello

打开arch/x86/include/asm/unistd_32.h,该文件包含了所有系统调用的宏,这里我加上自己新添加的系统调用的宏:

#define __NR_hello 349

在arch/x86/include/asm/unistd_64.h里面添加:

#define __NR_hello 312
__SYSCALL(__NR_hello, sys_hello)

打开include/linux/syscalls.h,然后加入新的系统调用的原型:

asmlinkage long sys_hello(void);

在Linux源代码根目录新建一个hello文件夹并且新建一个hello.c文件放入该文件夹,内容为:

//file: hello.c,简单的输出字符串
#include <linux/kernel.h>
asmlinkage long sys_hello(void)
{
printk("Hello Syscall!\n");
return 0;
}

在hello文件夹中新建一个名为Makefile的文档,内容是:

0hj-y:=hello.o

最后打开linux源码根目录的Makefle,找到:

core-y          += kernel/ mm/ fs/ ipc/ security/ crypto/ block/

改成:

core-y          += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ hello/

这样在编译内核的时候就可以编译hello目录的c文件了。

接下来是我们开始编译Linux的内核。

先cd到linux源码根目录下,然后:

sudo make menuconfig

这个命令可以呈现一个很方便的界面供我们选择编译选项,这里我使用默认的编译选项,保存退出。

接下来编译内核:

sudo make

接下来是漫长的编译时间,我的电脑配置比较低,在虚拟机环境下花了2个小时吧。

编译期间还遇到一个错误:

Kernel: arch/x86/boot/bzImage is ready  (#1)
  Building modules, stage 2.
  MODPOST 3268 modules
ERROR: "__modver_version_show" [drivers/staging/rts5139/rts5139.ko] undefined!
WARNING: modpost: Found 4 section mismatch(es).
To see full details build your kernel with:
'make CONFIG_DEBUG_SECTION_MISMATCH=y'
make[1]: *** [__modpost] Error 1
make: *** [modules] Error 2

google一番后解决方法是不用这个模块:

sed -i s/CONFIG_RTS5139=m/CONFIG_RTS5139=n/ .config

继续make:

sudo make

内核编译完成后安装模块:

sudo make modules_install install

命令执行完后在/boot/路径下可以找到类似这样的4个文件:

config-3.2.55

initrd.img-3.2.55

System.map-3.2.55

vmlinuz-3.2.55

新的内核已经被自动写进grub了,内核的编译到此结束,所以这个时候只需要reboot系统。

rboot后,我们在某个路径下新建一个test.c的c程序来调用hello系统调用:

#include <stdio.h>
#include  <linux/kernel.h>
#include  <sys/syscall.h>
#include  <unistd.h>
 
#define __NR_hello 312 //349 if you are running a 32bit kernel and following my tutorial
 
long hello_syscall(void)
{
    return syscall(__NR_hello);
}
 
int main(int argc, char *argv[])
{
    long int a = hello_syscall();
    printf("System call returned %ld\n", a);
    return 0;
}

编译并执行:

gcc test.c -o test
./test
//System call returned 0
系统调用成功返回0。

查看内核log:

dmesg
//[5904.663629]Hello world, syscall!

系统调用向内核log输出了信息,到此我们成功的向系统添加了系统调用。

ubuntu12.04下添加系统调用+编译内核》有1个想法

发表评论

电子邮件地址不会被公开。 必填项已用*标注