Har*_*144 5 system-calls linux-kernel
出于教育目的,我想在Debian Wheezy中实现系统调用.我希望在linux-image-3.2.0 - rt-amd64包中的内核上实现它.以下是我尝试过的概述:
要获取内核源代码:
apt-get source linux-image-3.2.0-4-rt-amd64
Run Code Online (Sandbox Code Playgroud)
从那里,我得到以下文件/目录我执行的目录:
linux_3.2.41.orig.tar.xz
linux_3.2.41-2+deb7u2.dsc
linux_3.2.41-2+deb7u2.debian.tar.xz
Run Code Online (Sandbox Code Playgroud)
以及:
linux_3.2.41
Run Code Online (Sandbox Code Playgroud)
其中包含内核的源代码.
然后,为了进行必要的更改以添加系统调用,我基本上都遵循了这个页面: 如何在debian/ubuntu上编写系统调用
以下是修改后的指令的精简版本,以反映我所做的更改.
+文件1:linux-xxx/vpart_syscalls/vpart_syscalls.c
#include <linux/linkage.h>
#include <linux/kernel.h>
asmlinkage long insert_partition(char*dest, const char* src)
{
printk("<--- the syscall has been called!");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
文件2:linux-xxx/vpart_syscalls/Makefile.在上面创建的同一个测试目录中创建一个Makefile,并在其中加入以下行:
obj-y := vpart_syscalls.o
文件3:linux-xxx/arch/x86/kernel/syscall_table_32.S.现在,您必须将系统调用添加到系统调用表中.在文件中附加以下行:
.long insert_partition
文件4:linux-xxx/arch/x86/include/asm/unistd_32.h
在此文件中,所有系统调用的名称将与唯一编号相关联.在最后一个系统调用号对后,添加一行
#define __NR_insert_partition 349
Run Code Online (Sandbox Code Playgroud)
然后替换NR_syscalls值,说明系统调用的总数(现有数字加1),即在这种情况下,NR_syscalls应该是338,新值是339.
#define NR_syscalls 350
Run Code Online (Sandbox Code Playgroud)
在文件中附加我们函数的原型.
asmlinkage long insert_partition(int lenTicks, int vpid);
Run Code Online (Sandbox Code Playgroud)
就在文件中的#endif行之前.
打开Makefile并找到定义core-y的行,并将目录test添加到该行的末尾.
core-y += kernel/ mm/ fs/ test/ vpart_syscalls/
Run Code Online (Sandbox Code Playgroud)
然后我继续以与那里描述的不同的方式构建内核:
make localmodconfig
make menuconfig (making no changes)
make-kpkg clean
fakeroot make-kpkg --initrd --append-to-version=+tm kernel_image kernel_headers
cd ..
dpkg -i linux-image-3.8.*
dpkg -i linux-headers-3.8.*
Run Code Online (Sandbox Code Playgroud)
安装的内核启动很好.我制作了以下c程序来测试系统调用:
#include <stdio.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
int main(){
printk("Calling the new syscall!\n");
int ret = 100;
ret = syscall(349, 1, 2);
printf("call return value: %i\n", ret);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我编译并运行该程序时,我得到的返回值为-1.我使用dmesg检查消息,并且没有证据表明我的printk被调用了..
如果有人知道我的问题在哪里,我真的很开心!我应该说我在改变和构建内核方面没有太多经验,但我已经学到了很多东西.我阅读了Robert Loves的书 - linux内核开发和网上的几个指南.
我认为,对于 64 位内核,步骤 3 和 4 可能不正确:
File 3: linux-x.x.x/arch/x86/kernel/syscall_table_32.S.
File 4: linux-x.x.x/arch/x86/include/asm/unistd_32.h
Run Code Online (Sandbox Code Playgroud)
这里有两个文件:http://lxr.linux.no/linux+v3.2.41/arch/x86/kernel/
syscall_64.c 668 2008-12-24 14:26:58 -0800
syscall_table_32.S 8659 2012-01-04 14:55:50 -0800
Run Code Online (Sandbox Code Playgroud)
第一个使用 C 文件定义 64 位模式的系统调用表内容,并使用unistd_64.h进行宏作弊
#define __SYSCALL(nr, sym) [nr] = sym,
const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
....
#include <asm/unistd_64.h>
};
Run Code Online (Sandbox Code Playgroud)
哪里asm/unistd_64.h
#define __NR_read 0
__SYSCALL(__NR_read, sys_read)
Run Code Online (Sandbox Code Playgroud)
等等。
第二个是您更改的 - 适用于 32 位模式,并使用 asm 文件和标签 ( .long sys_call_name) 编写。
因此,您为 32 位模式定义了系统调用,并且正在使用linux-image-3.2.0-4-rt-amd64,它基本上适用于“64 位 PC”。
我认为您将测试程序编译为gcc test.c,默认为 64 位模式。您可以尝试-m32使用 gcc: 选项gcc -m32 test.c来获取 32 位应用程序(只有在您拥有正确的 32 位构建交叉环境时才有效)或在某些 32 位 Linux 上编译此测试。
或者另一个选择是执行步骤“4a”:编辑arch/x86/include/asm/unistd_64.h以添加两行:
#define __NR_insert_partition YOUR_NUMBER
__SYSCALL(__NR_insert_partition, insert_partition)
Run Code Online (Sandbox Code Playgroud)
我不确定 64 位的 NR_syscalls 是在哪里以及如何定义的。它可能是在构建过程中生成的。