这只是示例如何编写简单的内核系统调用。考虑以下 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-xxx目录。
文件 1:linux-xxx/test/system_strcpy.c
在 linux-xxx 中创建一个目录,命名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-xxx/test/Makefile在上面
创建Makefile
的同一test
目录中创建一个,并将这一行放入其中:
obj-y := system_strcpy.o
文件 3:linux-xxx/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 进程_vm_writev sys_process_vm_writev
312 64 kcmp sys_kcmp
313 64 系统_strcpy 系统_strcpy
3.3 版本的格式为:
number
abi
name
entry point
文件4:linux-xxx/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-xxx/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;
}
代替 313 等数字syscall
,也可以直接使用__NR_system_strcpy
这是一个通用的例子。您将需要做一些实验来查看适用于您的特定内核版本的方法。