2017-07-24 61 views
6

我在摆弄系统调用。我添加了两个新的并验证他们使用呼叫syscall在执行系统调用时,您如何将系统调用号码公开给userland?

我想将系统调用号码放在头文件中,以便用户空间不必明确地知道系统调用号码。

arch/x86/syscalls/syscall_64.tbl我:

317  64  krun_read_msrs     sys_krun_read_msrs 
318  64  krun_reset_msrs     sys_krun_reset_msrs 

有些grepping暗示的kbuild已经自动生成宏为新的系统调用:

$ ag __NR_krun * 
arch/x86/include/generated/uapi/asm/unistd_64.h 
321:#define __NR_krun_read_msrs 317 
322:#define __NR_krun_reset_msrs 318 

的文件名显示,我不需要手动添加条目,但这与Linux Kernel文档不得不说的相反:

Some architectures (e.g. x86) have their own architecture-specific syscall tables, but several other architectures share a generic syscall table. Add your new system call to the generic list by adding an entry to the list in include/uapi/asm-generic/unistd.h: 

#define __NR_xyzzy 292 
__SYSCALL(__NR_xyzzy, sys_xyzzy) 

那么,我的系统调用是x86_64特定的,因为他们读取和写入仅在英特尔芯片中找到的MSR。所以在此之后,我开始研究是否可以找到我的amd64系统的arch-specific header。

你会期望它在arch/x86_64之下,但是在那里根本没有包含。所以我认为x86_64继承自x86。既然如此,具体拱头应该是:

arch/x86/include/uapi/asm/unistd.h 

如果打开了,它只是一个小包装派遣基础上拱:

# ifdef __i386__                 
# include <asm/unistd_32.h>              
# elif defined(__ILP32__)              
# include <asm/unistd_x32.h>             
# else                   
# include <asm/unistd_64.h>              
# endif 

所以这大概是设计来接up /usr/include/x86_64-linux-gnu/asm/unistd.h,但这还不包括我的新系统调用号码。

我希望headers_install目标安装新的标题(也许),但可惜它没有。

我很困惑。我应该手动添加我的新系统调用到文件吗?如果是这样的文件?如果不是,我如何将自动生成的__NR_*宏暴露给标准位置的用户空间?

谢谢

+2

如果您在库中实现包装函数以调用系统调用,则不一定需要。毕竟,这是C库在POSIXy系统上所做的大部分工作。您可以让库头文件公开系统调用号(适用于当前体系结构)。要为所有Linux用户提供新的系统调用,您需要将补丁上传到Linux内核(通过LKML)以及GNU C库或特定的发行版,以便将更改添加到他们的系统头文件中。 –

+0

是的,这不是真的可行,因为系统调用不适合一般用途。 –

+0

什么(不可行),将系统调用封装到函数中? (如果你的意思是把它推到上游,我同意)。但你真的应该考虑把系统调用包装到函数中去;即使像头文件中的静态内联函数一样,根据拱和字大小(使用预处理器宏)选择适当的系统调用号。提供* extra *头文件以及修改后的内核(或内核修改)要比在标准头文件中包含额外的项目容易得多。 –

回答

1

那么,我有一个部分的答案。部分原因是因为它是Debian特有的。

如果您在内核源代码中使用make deb-pkg目标,则会在父目录中创建.deb包。如果你安装了这些,那么你的头文件会被安装到系统中。

这样做了上述我的内核后:

$ grep krun /usr/include 
/usr/include/asm/unistd_64.h:#define __NR_krun_read_msrs 317 
/usr/include/asm/unistd_64.h:#define __NR_krun_reset_msrs 318 
2

内核构建过程分配实际的系统调用号是内核构建过程的一部分...所以你没有得到实际的最终数字,但仅限于已经构建的内核。构建你的内核,你会在构建的头文件中看到实际的分配。恐怕你已经试图在一个干净的内核源代码中搜索它们,这就是你找不到合适的包含文件的原因。

在另一侧,hidding实际系统呼叫号码是很常见的,它是由一些包装例程,其包括上述的内核头完成的,并使用#define d符号来表示的呼叫号码,以使__SYSCAL(...)实际呼叫。这通常甚至是必要的,因为每个系统调用通常具有不同的接口。您使用的所有正常系统调用都在stdlib中包含了它们的包装器,但不包含新包装器。这里有两种方法:修补标准C库以包含(并在/usr/include的某处为函数原型编写标准头文件)在所有程序中包含包装文件mySysCall.o(此名称在您方便时)在你要使用新的系统调用的地方。