我正在尝试编写自己的系统调用。它只会返回当前时间。我知道我应该做什么的概念,我确实经历了几个这样的链接:
-
在Linux 2.6 for i386上实现系统调用
-
另一个系统调用实现
但我仍然很困惑,没有得到想要的结果。内核没有进行编译,并且由于问题而崩溃。我已经在debian上试用了3.X.X 的最新稳定版本
有人能给我指一个干净的hello world
类型的程序来开发系统调用吗?
编辑
对于以下答案,以下是我的问题:
在我的linux文件夹中找不到File 3: linux-x.x.x/arch/x86/kernel/syscall_table_32.S
。我不得不即兴创作,因此修改了以下文件:linux-x.x.x/arch/x86/syscalls/syscall_64.tbl
上面提到的(1)个新文件具有不同的
<number> <64/x32/common> <name> <entry point>
模式,我的条目是"313常见">内核映像确实编译成功,但我无法调用该函数。当我用gcc编译它时,它给出了一个
undefined reference" error
。为什么?
这只是如何编写简单内核系统调用的示例。考虑下面的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进程_vm_readv系统_进程_vm_readv
311 64进程_vm_writev系统_进程_vm_writev
312 64 kcmp系统_kcmp
313 64 system_strcpy system_strcopy
3.3版本的格式为:number
abi
name
entry 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);
就在文件中CCD_ 21行之前。
文件6:在源目录的根目录下创建文件
打开Makefile
,找到定义core-y
的行,并将目录test
添加到该行的末尾。
core-y += kernel/ mm/ fs/ test/
现在编译内核。问题:make bzImage -j4
通过以root用户身份(或使用root权限)执行以下命令来安装内核:make install
重新启动系统。
要使用最近创建的系统调用,请使用:
syscall(338,dest,src);
(或内核3.3+的syscall(313,dest,src);
),而不是常规的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 %sn",src,dest);
return 0;
}
代替syscall
中的313等数字,您也可以直接使用__NR_system_strcpy
这是一个通用的例子。您需要做一些实验,看看什么适用于您的特定内核版本。
上述答案不适用于内核3.5.0和3.7.6,产生未定义的引用编译错误。为了解决这个问题,应该在system_strcpy.c中包含linux/syscalls.h,而不是linux/linking.h。此外,最好使用SYSCALL_DEFINE2(strcpy,dest,src)来定义系统调用。