简单的系统调用实现示例?
Simple System Call Implementation example?
有趣的是,我在网上找不到任何简单的例子。你能分享一个简单的例子吗?我试图通过分析一个例子来理解以下内容。
⦁ Typically,
⦁ a number associated with each system call
⦁ Number used as an index to a table: System Call table
⦁ Table keeps addresses of system calls (routines)
⦁ System call runs and returns
⦁ Caller does not know system call implementation
⦁ Just knows interface
这取决于您要为哪种架构添加系统调用,或者是否要为所有架构添加系统调用。我将解释一种为 ARM 添加系统调用的方法。
- 为您的系统调用选择一个名称。例如,
mysyscall
.
选择一个系统调用号。 在arch/arm/include/asm/unistd.h
中,注意每个系统调用如何有一个分配给它的特定编号 (__NR__SYSCALL_BASE+<number>
)。为您的系统调用选择一个未使用的编号。让我们选择系统调用号 223。然后添加:
#define __NR_mysyscall (__NR_SYSCALL_BASE+223
索引 223 在该头文件中的位置。这会将数字 223 分配给您在 ARM 架构上的系统调用。
修改特定于架构的系统调用table。在linux/arch/arm/kernel/calls.S
中,将系统调用223对应的行改为:
CALL(sys_mysyscall)
添加你的函数原型。假设你想添加一个非架构特定的系统调用。编辑文件:include/linux/syscalls.h
并添加系统调用的原型:
asmlinkage long sys_mysyscall(struct dummy_struct *buf);
如果你想专门为 ARM 添加它,那么除了在这个文件中执行以下操作:arch/arm/kernel/sys_arm.c
.
在某处实现你的系统调用。 随意创建一个文件。例如,在 kernel/
目录中。您至少需要:
#include <linux/syscalls.h>
...
SYSCALL_DEFINE1(mysyscall, struct dummy_struct __user *, buf)
{
/* Implement your syscall */
}
注意宏,SYSCALL_DEFINE1
。最后的数字应该对应于你的系统调用有多少个输入参数。在这种情况下,我们的系统调用只有 1 个参数,因此您使用 SYSCALL_DEFINE1
。如果它有两个参数,您将使用 SYSCALL_DEFINE2
,等等
不要忘记将对象 (.o) 文件添加到您放置它的目录中的 Makefile。
- 编译你的新内核并测试。你没有修改你的C库,所以你不能用[=调用你的系统调用25=]。您需要使用
syscall()
函数,该函数将系统调用号作为其第一个参数:
struct dummy_struct *buf = calloc(1, sizeof(buf));
int res = syscall(223, buf);
请注意,这是针对 ARM 的。对于其他架构,该过程将非常相似。
编辑:不要忘记将系统调用文件添加到 kernel/ 中的 Makefile。
有趣的是,我在网上找不到任何简单的例子。你能分享一个简单的例子吗?我试图通过分析一个例子来理解以下内容。
⦁ Typically,
⦁ a number associated with each system call
⦁ Number used as an index to a table: System Call table
⦁ Table keeps addresses of system calls (routines)
⦁ System call runs and returns
⦁ Caller does not know system call implementation
⦁ Just knows interface
这取决于您要为哪种架构添加系统调用,或者是否要为所有架构添加系统调用。我将解释一种为 ARM 添加系统调用的方法。
- 为您的系统调用选择一个名称。例如,
mysyscall
. 选择一个系统调用号。 在
arch/arm/include/asm/unistd.h
中,注意每个系统调用如何有一个分配给它的特定编号 (__NR__SYSCALL_BASE+<number>
)。为您的系统调用选择一个未使用的编号。让我们选择系统调用号 223。然后添加:#define __NR_mysyscall (__NR_SYSCALL_BASE+223
索引 223 在该头文件中的位置。这会将数字 223 分配给您在 ARM 架构上的系统调用。
修改特定于架构的系统调用table。在
linux/arch/arm/kernel/calls.S
中,将系统调用223对应的行改为:CALL(sys_mysyscall)
添加你的函数原型。假设你想添加一个非架构特定的系统调用。编辑文件:
include/linux/syscalls.h
并添加系统调用的原型:asmlinkage long sys_mysyscall(struct dummy_struct *buf);
如果你想专门为 ARM 添加它,那么除了在这个文件中执行以下操作:
arch/arm/kernel/sys_arm.c
.在某处实现你的系统调用。 随意创建一个文件。例如,在
kernel/
目录中。您至少需要:
#include <linux/syscalls.h>
...
SYSCALL_DEFINE1(mysyscall, struct dummy_struct __user *, buf)
{
/* Implement your syscall */
}
注意宏,SYSCALL_DEFINE1
。最后的数字应该对应于你的系统调用有多少个输入参数。在这种情况下,我们的系统调用只有 1 个参数,因此您使用 SYSCALL_DEFINE1
。如果它有两个参数,您将使用 SYSCALL_DEFINE2
,等等
不要忘记将对象 (.o) 文件添加到您放置它的目录中的 Makefile。
- 编译你的新内核并测试。你没有修改你的C库,所以你不能用[=调用你的系统调用25=]。您需要使用
syscall()
函数,该函数将系统调用号作为其第一个参数:
struct dummy_struct *buf = calloc(1, sizeof(buf));
int res = syscall(223, buf);
请注意,这是针对 ARM 的。对于其他架构,该过程将非常相似。
编辑:不要忘记将系统调用文件添加到 kernel/ 中的 Makefile。