Lab 6Linux系统调用

这个实验的目的是学会配置和编译移植到ARM上的Linux内核,深入理解Linux系统调用,比较 ARMx86系统调用的不同。

配合课程

嵌入式Linux

实验目的

  1. 学习Linux内核的配置和编译;
  2. 深入理解Linux系统调用;
  3. 理解ARMx86CPU模式(系统模式、用户模式等)的不同。
  4. 掌握内核模块的编写方法。

实验器材

硬件

以下为自备(可选)器材:

软件

实验步骤

使用交叉编译工具或本机编译工具,通过Linux内核源码进行实验:

1.      寻找、下载Linux实验板卡所用的Linux内核源码;

本次实验从github上下载了linux-rpi-3.6.y源码。解压后文件夹大致内容如下:

 

2.      在内核中加入新的系统调用,具体功能没有要求,能输出调试信息即可;

首先在arch/arm/kernel中新建一个sys_mysyscall.c文件,编写系统调用函数实体,用于在后面输出内容来调试。

同时,需要在makefile文件里面加上编译出的.o文件,用于之后的编译内核。

之后需要修改中断向量表。即修改arch/arm/kernel/calls.S文件。参考以前做过的操作系统实验课程,223号调用没有被使用。于是考虑这次实验也修改223调用。修改为如下:

之后在include/uapi/asm-generic/unistd.h头文件中把之前的系统调用与宏联系在一起:

之后就可以编译了。

 

3.      修改内核代码配置,编译内核;

修改config文件,使用现在树莓派上的config文件即可编译。可以使用zcat命令查看/proc/config.gz的内容。

使用重定向修改了config文件。之后就可以进行编译了。

接着使用已有配制配制内核就可以了。

之后如同之前的操作系统实验上的,使用makemake module_install

一开始选择现在PC上编译,发现编译出来还得放到树莓派上。后来嫌麻烦就直接在树莓派上编译了,虽然速度很慢。

 

4.      将编译好的内核装载到板卡启动;

使用新的内核之前,需要备份更新一下内核和固件,当然还需要先备份一下。

然后更新固件和内核:

之后就可以reboot重启进入新的内核了。

 

5.      编写C代码,用两种方法做系统调用,测试:

a.      嵌入汇编代码,用r0传参数;

b.      syscall()函数。

使用系统调用函数syscall()的方法如下:

嵌入式汇编代码如下:

汇编函数首先保存之前的寄存器值,之后写入r0寄存器为223,之后使用bl调用syscall,最后重回现场即可。

上述两者方法都可以正确进行。运行编译结果./a.out,可以看到输出内容,使用dmesg | tail命令查看:

可以看到都正确输出了结果。

 

6.      编写内核模块,在模块加载和卸载时能通过内核打印函数输出提示信息;

编写内核模块,可以参考以前的操作糸统的实验:

#include <linux/init.h>

#include <linux/kernel.h>

#include <linux/module.h>

MODULE_LICENSE("GPL");

tatic int __init reverse_init(void)

{

    printk(KERN_INFO "Hi!\n");

    return 0;

}

static void __exit reverse_exit(void)

{

    printk(KERN_INFO "Bye!\n");

}

module_init(reverse_init);

module_exit(reverse_exit);

该模块可以在装载时输出“Hi!”,在卸载时可以输出“Bye!”。由于直接在树莓派上编译出现了问题,最后选择在PC上使用交叉编译的方法,编译出.ko文件,然后拷贝到树莓派上使用insmodlsmod测试即可。因此需要在PC上重新编写makefile

obj-m := mykernel.o

KERNEL_VER := 3.6.y

KERNEL_DIR := /media/turtle/g1t15346-h4h8-4h64-4g56-45269hfbne1/lib/modules/$(KERNEL_VER)/build

PWD := $(shell pwd)

ARGS := ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

all:

    make -C $(KERNEL_DIR) SUBDIRS=$(PWD) $(ARGS) modules

clean:

    rm *.o *.ko *.mod.c

.PHONY:clean

之后使用make编译出ko文件拷贝到树莓派上即可。

 

7.      通过insmodlsmod等命令测试内核模块。

使用insmodlsmod来测试模块是否安装成功:

然后可以在日志里查看安装模块时是否有输出(使用dmesg | tail命令):

可以看到使用insmodrmmod之后正确在日志里输出了正确结果。