实验20.实现系统调用

已完成实验

已完成实验链接

简介

实验 20. 实现系统调用

总结

  • 进程结构体新增 pid 成员变量

  • pid 采用静态全局变量,锁控制+1,确保唯一

  • 进程初始化是就分配好 pid

  • 添加 getpid,本质调用 syscall,参数入栈,再执行 int 0x80

  • 添加 0x80 中断,根据参数 0 调用系统调用函数表的函数

  • 初始化系统调用函数表,表项 0 就是获取 pid

主要代码

thread.h

在这里插入图片描述

thread.c

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

syscall.c

// 文件: syscall.c
// 时间: 2024-08-01
// 来自: ccj
// 描述: 用户系统调用,压入0x80和参数,执行int 0x80


#include "syscall.h"

/// 无参数的系统调用
// 1. push ${NUMBER}
// 2. int 0x80
// 3. pop ${NUMBER}
// 4. eax的值给到retval
#define _syscall0(NUMBER)                                         \
    ({                                                            \
        int retval;                                               \
        asm volatile("pushl %[number]; int $0x80; addl $4, %%esp" \
                     : "=a"(retval)                               \
                     : [number] "i"(NUMBER)                       \
                     : "memory");                                 \
        retval;                                                   \
    })

// 一个参数的系统调用
#define _syscall1(NUMBER, ARG0)                                                  \
    ({                                                                           \
        int retval;                                                              \
        asm volatile("pushl %[arg0]; pushl %[number]; int $0x80; addl $8, %%esp" \
                     : "=a"(retval)                                              \
                     : [number] "i"(NUMBER), [arg0] "g"(ARG0)                    \
                     : "memory");                                                \
        retval;                                                                  \
    })

// 两个参数的系统调用
#define _syscall2(NUMBER, ARG0, ARG1)                                  \
    ({                                                                 \
        int retval;                                                    \
        asm volatile(                                                  \
            "pushl %[arg1]; pushl %[arg0]; "                           \
            "pushl %[number]; int $0x80; addl $12, %%esp"              \
            : "=a"(retval)                                             \
            : [number] "i"(NUMBER), [arg0] "g"(ARG0), [arg1] "g"(ARG1) \
            : "memory");                                               \
        retval;                                                        \
    })

// 三个参数的系统调用
#define _syscall3(NUMBER, ARG0, ARG1, ARG2)                                              \
    ({                                                                                   \
        int retval;                                                                      \
        asm volatile(                                                                    \
            "pushl %[arg2]; pushl %[arg1]; pushl %[arg0]; "                              \
            "pushl %[number]; int $0x80; addl $16, %%esp"                                \
            : "=a"(retval)                                                               \
            : [number] "i"(NUMBER), [arg0] "g"(ARG0), [arg1] "g"(ARG1), [arg2] "g"(ARG2) \
            : "memory");                                                                 \
        retval;                                                                          \
    })

/// @brief 返回当前任务pid
/// @return
uint32_t getpid() { return _syscall0(SYS_GETPID); }

kernel.s

在这里插入图片描述

syscall-init.c

// 文件: syscall-init.c
// 时间: 2024-08-01
// 来自: ccj
// 描述: 初始化系统调用函数表,0x80中断根据参数执行表的函数


#include "syscall-init.h"
#include "syscall.h"
#include "stdint.h"
#include "print.h"
#include "thread.h"

#define syscall_nr 32
typedef void* syscall;

// 系统调用处理数组
syscall syscall_table[syscall_nr];

/// @brief 返回当前任务的pid
/// @param
/// @return
uint32_t sys_getpid(void) { return running_thread()->pid; }

/// @brief 初始化系统调用
/// @param
void syscall_init(void) {
    put_str("[syscall] syscall_init start\n");

    syscall_table[SYS_GETPID] = sys_getpid;

    put_str("[syscall] syscall_init done\n");
}

init.c

在这里插入图片描述

main.c

// 文件: main.c
// 时间: 2024-07-19
// 来自: ccj
// 描述: 内核从此处开始

#include "print.h"
#include "init.h"
#include "thread.h"
#include "interrupt.h"
#include "console.h"
#include "process.h"
#include "syscall.h"
#include "syscall-init.h"

// 两个内核线程
void k_thread_a(void*);
void k_thread_b(void*);
// 两个用户进程
void u_prog_a(void);
void u_prog_b(void);
int prog_a_pid = 0, prog_b_pid = 0;


int main(void) {
    put_str("I am kernel\n");

    init_all();

    process_execute(u_prog_a, "user_prog_a");
    process_execute(u_prog_b, "user_prog_b");

    console_put_str("main_pid:0x");
    console_put_int(sys_getpid());
    console_put_char('\n');

    thread_start("k_thread_a", 31, k_thread_a, "argA ");
    thread_start("k_thread_b", 31, k_thread_b, "argB ");

    intr_enable();  // 打开中断,使时钟中断起作用
    while (1) {};
    return 0;
}


// 内核线程函数
void k_thread_a(void* arg) {
    console_put_str("thread_a_pid:0x");
    console_put_int(sys_getpid());
    console_put_char('\n');

    console_put_str("prog_a_pid:0x");
    console_put_int(prog_a_pid);
    console_put_char('\n');

    while (1) {}
}
void k_thread_b(void* arg) {
    console_put_str("thread_b_pid:0x");
    console_put_int(sys_getpid());
    console_put_char('\n');

    console_put_str("prog_b_pid:0x");
    console_put_int(prog_b_pid);
    console_put_char('\n');
    
    while (1) {}
}

// 测试用户进程
void u_prog_a(void) {
    prog_a_pid = getpid();
    while (1) {}
}
void u_prog_b(void) {
    prog_b_pid = getpid();
    while (1) {}
}

在这里插入图片描述

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值