这只是一个示例如何编写一个简单的内核系统调用。
考虑以下 C 函数 system_strcpy(),它简单地将一个字符串复制到另一个:类似于 strcpy() 所做的。
#include<stdio.h>
long system_strcpy(char* dest, const char* src)
{
int i=0;
while(src[i]!=0)
dest[i]=src[i++];
dest[i]=0;
return i;
}
在写之前先获取内核源码tar并解压得到linux-x.x.x目录。
文件 1:linux-x.x.x/test/system_strcpy.c
在 linux-x.x.x 中创建一个目录,命名为test,并将此代码保存为文件system_strcpy.c。
#include<linux/linkage.h>
#include<linux/kernel.h>
asmlinkage long system_strcpy(char*dest, const char* src)
{
int i=0;
while(src[i]!=0)
dest[i]=src[i++];
dest[i]=0;
return i;
}
文件 2:linux-x.x.x/test/Makefile
在您在上面创建的同一 test 目录中创建一个 Makefile 并将此行放入其中:
obj-y := system_strcpy.o
文件 3:linux-x.x.x/arch/x86/kernel/syscall_table_32.S
现在,您必须将系统调用添加到系统调用表中。
将以下行追加到文件中:
.long system_strcpy
注意:对于内核 3.3 及更高版本。
*参考:linux-3.3.xx/arch/x86/syscalls/syscall_64.tbl*
在其中,现在在以下一系列行的末尾添加:
310 64 process_vm_readv sys_process_vm_readv
311 64 process_vm_writev sys_process_vm_writev
312 64 kcmp sys_kcmp
313 64 system_strcpy system_strcpy
3.3 版本的格式为:
numberabinameentry point
文件 4:linux-x.x.x/arch/x86/include/asm/unistd_32.h
注意:此部分对于 3.3 及更高版本的内核是多余的
在此文件中,所有系统调用的名称都将与一个唯一编号相关联。在最后一个系统调用号对之后,添加一行
#define __NR_system_strcpy 338
(如果 337 是与系统调用号码对中的最后一个系统调用相关联的号码)。
然后替换 NR_syscalls 值,将系统调用的总数表示为(现有数字加 1),即在这种情况下,NR_syscalls 应该是 338,而新值是 339。
#define NR_syscalls 339
文件 5:linux-x.x.x/include/linux/syscalls.h
将我们函数的原型附加到文件中。
asmlinkage long system_strcpy(char *dest,char *src);
就在文件中#endif 行之前。
文件 6:源目录根目录下的 Makefile。
打开Makefile 并找到定义core-y 的行并将目录test 添加到该行的末尾。
core-y += kernel/ mm/ fs/ test/
现在编译内核。问题:
make bzImage -j4
通过以 root 身份(或具有 root 权限)执行以下命令来安装内核:
make install
重启系统。
要使用最近创建的系统调用,请使用:
syscall(338,dest,src);(或 syscall(313,dest,src); 用于内核 3.3+)而不是常规的 strcpy 库函数。
#include "unistd.h"
#include "sys/syscall.h"
int main()
{
char *dest=NULL,*src="Hello";
dest=(char*)malloc(strlen(src)+1);
syscall(338,dest,src);//syscall(313,dest,src); for kernel 3.3+
printf("%s \n %s\n",src,dest);
return 0;
}
syscall中的313等数字也可以直接用__NR_system_strcpy代替
这是一个通用示例。您需要进行一些试验,看看哪些方法适用于您的特定内核版本。