2

我正在学习操作系统课程,第一个任务是向内核添加一些系统调用(Redhat,内核版本 2.4)。

我已经添加了我认为需要添加的所有内容,但它仍然不起作用。

我正在尝试运行测试,我注意到包装器(我在下面添加了一个示例以及它的 sys_call 代码)没有链接系统调用。我知道这一点,因为我在系统调用中放置了一个 printk 并且它们从未出现(并且测试本身并没有给出我期望的结果)。

现在据我了解添加系统调用的开发过程是:

  1. 创建一个包装器,如说明中的示例包装器函数(我们称之为服务)。
  2. 将 sys_aservice 写入 .c 文件中,该文件将转到 linux-2.4.18-14custom 文件夹中的众多文件之一。它转到的文件取决于我要添加的服务类型(例如,如果它是文件系统服务,我会将它放在 fs 中)。
  3. 在表中添加系统调用的条目/usr/src/linuxlinux-2.4.18-14custom/arch/i386/kernel/ entry.S

这是我一开始所做的,但似乎还不够(因为它似乎不起作用)。

我在网上查了一下(并阅读:如何添加系统调用),我读到我需要添加/更改以下内容才能使链接正常工作。

  1. 在 unistd.h 中为系统调用添加一行。它看起来像

    定义 __NR_aservice

  2. 将服务添加到生成文件。因此,例如,如果我将 aservice.c 放在 fs 文件夹中,我会将 aservice.c 添加到 fs 中的 makefile 中。

  3. 创建一个 aservice.h 文件,该文件将转到 linux-2.4.18-14custom/include/linux (显然所有 h 文件都在哪里?)。这个 .h 文件将包含一个叫做“存根”的东西,它是从 unistd.h 中的宏自动生成的(.h 文件必须包含它),以便用户程序可以使用您的系统调用。存根的声明如下所示: _syscallN(return type, function name, arg1 type, arg1 name ...)" 其中“N”是参数的数量。

  4. 在 aservice.c 中的每个 sys_X 函数前添加关键字“asmlinkage”(需要包含 links.h)。所以函数声明看起来像: asmlinkage int sys_aservice(...){..} 然后将 .h 文件包含在 .c 文件中。

这一切都正确吗?因为即使在执行以下操作之后,似乎仍然没有调用系统调用。

这是一个示例包装器和系统调用实现:

 int stop_monitor(int pid){
        long __res;
        __asm__ volatile (
                "movl $244, %%eax;" << 244 is the entry in the sys_call table in entry.S 
                "movl %1, %%ebx;"
                "int $0x80;"
                "movl %%eax, %0"
                : "=m" (__res)
                : "m" (pid)
                : "%eax", "%ebx"
        );
        if((unsigned long)(__res) >= (unsigned long)(-125)) {
            errno = -(__res);
            __res = -1;
        }
        return (int)(__res);
    }


asmlinkage int sys_stop_monitor(int pid){
    task_t* task = find_task_by_pid(pid);
    if(!task)
        return -ESRCH;
    if(task->flagMonitor == 0)
        return -EPERM;
    task->flagMonitor = 0;
    return 0;
}

我错过了什么?

4

1 回答 1

1

我已经测试了我为我的 micro libc 编写的这些系统调用助手:

#define MKFNS(fn,...) MKFN_N(fn,##__VA_ARGS__,9,8,7,6,5,4,3,2,1,0)(__VA_ARGS__)
#define MKFN_N(fn, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n, ...) fn##n
#define syscall(...) MKFNS(syscall,##__VA_ARGS__)

static inline long syscall0(long n){
    unsigned long r;
    asm volatile("int $128":"=a"(r):"a"(n):"memory");
    return r;
}

#define syscall1(n,a) _syscall1(n,(long)a)
static inline long _syscall1(long n, long a){
    unsigned long r;
    asm volatile("int $128":"=a"(r):"a"(n),"b"(a):"memory");
    return r;
}

#define syscall2(n,a,b) _syscall2(n,(long)a,(long)b)
static inline long _syscall2(long n, long a, long b){
    unsigned long r;
    asm volatile("int $128":"=a"(r):"a"(n),"b"(a),"c"(b):"memory");
    return r;
}

#define syscall3(n,a,b,c) _syscall3(n,(long)a,(long)b,(long)c)
static inline long _syscall3(long n, long a, long b, long c){
    unsigned long r;
    asm volatile("int $128" : "=a"(r):"a"(n),"b"(a),"c"(b),"d"(c):"memory");
    return r;
}

#define syscall4(n,a,b,c,d) _syscall4(n,(long)a,(long)b,(long)c,(long)d)
static inline long _syscall4(long n, long a, long b, long c, long d){
    unsigned long r;
    asm volatile("int $128":"=a"(r):"a"(n),"b"(a),"c"(b),"d"(c),"S"(d):"memory");
    return r;
}

#define syscall5(n,a,b,c,d,e) _syscall5(n,(long)a,(long)b,(long)c,(long)d,(long)e)
static inline long _syscall5(long n, long a, long b, long c, long d, long e){
    unsigned long __ret;
    __asm__ __volatile__ ("int $128" : "=a"(__ret) : "a"(n), "b"(a), "c"(b), "d"(c), "S"(d), "D"(e) : "memory");
    return __ret;
}

void exit(long a){asm volatile("int $128":"=a"(a):"a"(1),"b"(a):"memory");}
extern char **environ;

asm(".text\n"
".global _start\n"
"_start:\n"
"popl %ecx\n"
"movl %esp,%esi\n"
"pushl %ecx\n"
"leal 4(%esi,%ecx,4),%eax\n"
"pushl %eax\n"
"pushl %esi\n"
"pushl %ecx\n"
"movl %eax,environ\n"
"call main\n"
"pushl %eax\n"
"call exit\n"
"hlt\n"
".Lstart:\n"
".size _start,.Lstart-._start\n"
);

#define aservice(...) syscall(__NR_aservice,__VA_ARGS__)
#define write(...) syscall(__NR_write,__VA_ARGS__) //#define __NR_write 4

然后你可以运行一个简单的测试程序来确保你可以处理系统调用

int main(void){write(1,"hello world!\n",13);}

编译gcc -nostdlib -fno-builtin

这将让您测试您是否可以访问系统调用,以便您知道问题是您的系统调用还是您访问它们的方式。

于 2013-11-09T18:20:48.510 回答