简单的系统调用实现示例?

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 添加系统调用的方法。

  1. 为您的系统调用选择一个名称。例如,mysyscall.
  2. 选择一个系统调用号。arch/arm/include/asm/unistd.h中,注意每个系统调用如何有一个分配给它的特定编号 (__NR__SYSCALL_BASE+<number>)。为您的系统调用选择一个未使用的编号。让我们选择系统调用号 223。然后添加:

    #define __NR_mysyscall (__NR_SYSCALL_BASE+223

    索引 223 在该头文件中的位置。这会将数字 223 分配给您在 ARM 架构上的系统调用。

  3. 修改特定于架构的系统调用table。在linux/arch/arm/kernel/calls.S中,将系统调用223对应的行改为:

    CALL(sys_mysyscall)

  4. 添加你的函数原型。假设你想添加一个非架构特定的系统调用。编辑文件:include/linux/syscalls.h 并添加系统调用的原型:

    asmlinkage long sys_mysyscall(struct dummy_struct *buf);

    如果你想专门为 ARM 添加它,那么除了在这个文件中执行以下操作:arch/arm/kernel/sys_arm.c.

  5. 在某处实现你的系统调用。 随意创建一个文件。例如,在 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。

  1. 编译你的新内核并测试。你没有修改你的C库,所以你不能用[=调用你的系统调用25=]。您需要使用 syscall() 函数,该函数将系统调用号作为其第一个参数:
struct dummy_struct *buf = calloc(1, sizeof(buf));   
int res = syscall(223, buf);

请注意,这是针对 ARM 的。对于其他架构,该过程将非常相似。

编辑:不要忘记将系统调用文件添加到 kernel/ 中的 Makefile。