mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 08:06:32 +00:00
新增rust ffi (#77)
* 引入cargo * 取消对Cargo.lock的跟踪 * 解决vscode报错问题 * new: rust的代码能够调用c语言的printk_color * 1、将原本run.sh的工作拆解,变为几个不同的make命令 2、在docker镜像中编译rust * 更改workflow * update workflow * new: 解决workflow无法通过编译的问题
This commit is contained in:
22
kernel/src/process/Makefile
Normal file
22
kernel/src/process/Makefile
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
CFLAGS += -I .
|
||||
|
||||
|
||||
kernel_process_objs:= $(shell find ./*.c)
|
||||
|
||||
ECHO:
|
||||
@echo "$@"
|
||||
|
||||
|
||||
$(kernel_process_objs): ECHO
|
||||
$(CC) $(CFLAGS) -c $@ -o $@.o
|
||||
|
||||
procs.o: proc.S
|
||||
$(CC) -E proc.S > _proc.s
|
||||
as $(ASFLAGS) -o procs.o _proc.s
|
||||
|
||||
all: procs.o $(kernel_process_objs)
|
||||
|
||||
|
||||
clean:
|
||||
echo "Done."
|
330
kernel/src/process/kthread.c
Normal file
330
kernel/src/process/kthread.c
Normal file
@ -0,0 +1,330 @@
|
||||
#include <common/glib.h>
|
||||
#include <common/kthread.h>
|
||||
#include <common/spinlock.h>
|
||||
#include <debug/bug.h>
|
||||
#include <sched/sched.h>
|
||||
#include <time/sleep.h>
|
||||
|
||||
static spinlock_t __kthread_create_lock; // kthread创建过程的锁
|
||||
static struct List kthread_create_list; // kthread创建任务的链表
|
||||
struct process_control_block *kthreadd_pcb = NULL; // kthreadd守护线程的pcb
|
||||
|
||||
// 枚举各个标志位是在第几位
|
||||
enum KTHREAD_BITS
|
||||
{
|
||||
KTHREAD_IS_PER_CPU = 0,
|
||||
KTHREAD_SHOULD_STOP,
|
||||
KTHREAD_SHOULD_PARK,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief kthread的创建信息(仅在创建过程中存在)
|
||||
*
|
||||
*/
|
||||
struct kthread_create_info_t
|
||||
{
|
||||
// 传递给kthread的信息
|
||||
int (*thread_fn)(void *data);
|
||||
void *data;
|
||||
int node;
|
||||
|
||||
// kthreadd守护进程传递给kthread_create的结果,
|
||||
// 成功则返回PCB,不成功则该值为负数错误码。若该值为NULL,意味着创建过程尚未完成
|
||||
struct process_control_block *result;
|
||||
|
||||
struct List list;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取pcb中的kthread结构体
|
||||
*
|
||||
* @param pcb pcb
|
||||
* @return struct kthread* kthread信息结构体
|
||||
*/
|
||||
struct kthread_info_t *to_kthread(struct process_control_block *pcb)
|
||||
{
|
||||
WARN_ON(!(pcb->flags & PF_KTHREAD));
|
||||
return pcb->worker_private;
|
||||
}
|
||||
|
||||
static struct process_control_block *__kthread_create_on_node(int (*thread_fn)(void *data), void *data, int node,
|
||||
const char name_fmt[], va_list args)
|
||||
{
|
||||
struct process_control_block *pcb = NULL;
|
||||
struct kthread_create_info_t *create = kzalloc(sizeof(struct kthread_create_info_t), 0);
|
||||
|
||||
if (create == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
BUG_ON(name_fmt == NULL);
|
||||
|
||||
create->thread_fn = thread_fn;
|
||||
create->data = data;
|
||||
create->node = node;
|
||||
create->result = NULL;
|
||||
list_init(&create->list);
|
||||
|
||||
spin_lock(&__kthread_create_lock);
|
||||
list_append(&kthread_create_list, &create->list);
|
||||
spin_unlock(&__kthread_create_lock);
|
||||
// kdebug("to wakeup kthread daemon..., current preempt=%d, rflags=%#018lx", current_pcb->preempt_count,
|
||||
|
||||
// todo: 使用completion优化这里
|
||||
while (kthreadd_pcb == NULL) // 若kthreadd未初始化,则等待kthreadd启动
|
||||
;
|
||||
// 唤醒kthreadd守护进程
|
||||
process_wakeup_immediately(kthreadd_pcb);
|
||||
|
||||
// 等待创建完成
|
||||
// todo: 使用completion机制以降低忙等时间
|
||||
while (create->result == NULL)
|
||||
pause();
|
||||
// 获取结果
|
||||
pcb = create->result;
|
||||
if (!IS_ERR(create->result))
|
||||
{
|
||||
// 为内核线程设置名字
|
||||
char pcb_name[PCB_NAME_LEN];
|
||||
va_list get_args;
|
||||
va_copy(get_args, args);
|
||||
// 获取到字符串的前16字节
|
||||
int len = vsnprintf(pcb_name, name_fmt, PCB_NAME_LEN, get_args);
|
||||
if (len >= PCB_NAME_LEN)
|
||||
{
|
||||
//名字过大 放到full_name字段中
|
||||
struct kthread_info_t *kthread = to_kthread(pcb);
|
||||
char *full_name = kzalloc(1024, 0);
|
||||
vsprintf(full_name, name_fmt, get_args);
|
||||
kthread->full_name = full_name;
|
||||
}
|
||||
// 将前16Bytes放到pcb的name字段
|
||||
process_set_pcb_name(pcb, pcb_name);
|
||||
va_end(get_args);
|
||||
}
|
||||
|
||||
kfree(create);
|
||||
return pcb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 让当前内核线程退出,并返回result参数给kthread_stop()函数
|
||||
*
|
||||
* @param result 返回值
|
||||
*/
|
||||
void kthread_exit(long result)
|
||||
{
|
||||
struct kthread_info_t *kt = to_kthread(current_pcb);
|
||||
kt->result = result;
|
||||
kt->exited = true;
|
||||
process_do_exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在当前结点上创建一个内核线程
|
||||
*
|
||||
* @param thread_fn 该内核线程要执行的函数
|
||||
* @param data 传递给 thread_fn 的参数数据
|
||||
* @param node 线程的任务和线程结构都分配在这个节点上
|
||||
* @param name_fmt printf-style format string for the thread name
|
||||
* @param arg name_fmt的参数
|
||||
* @return 返回一个pcb或者是ERR_PTR(-ENOMEM)
|
||||
*
|
||||
* 请注意,该宏会创建一个内核线程,并将其设置为停止状态。您可以使用wake_up_process来启动这个线程。
|
||||
* 新的线程的调度策略为SCHED_NORMAL,并且能在所有的cpu上运行
|
||||
*
|
||||
* 当内核线程被唤醒时,会运行thread_fn函数,并将data作为参数传入。
|
||||
* 内核线程可以直接返回,也可以在kthread_should_stop为真时返回。
|
||||
*/
|
||||
struct process_control_block *kthread_create_on_node(int (*thread_fn)(void *data), void *data, int node,
|
||||
const char name_fmt[], ...)
|
||||
{
|
||||
struct process_control_block *pcb;
|
||||
va_list args;
|
||||
va_start(args, name_fmt);
|
||||
pcb = __kthread_create_on_node(thread_fn, data, node, name_fmt, args);
|
||||
va_end(args);
|
||||
return pcb;
|
||||
}
|
||||
/**
|
||||
* @brief 内核线程的包裹程序
|
||||
* 当内核线程被运行后,从kernel_thread_func跳转到这里。
|
||||
* @param _create 内核线程的创建信息
|
||||
* @return int 内核线程的退出返回值
|
||||
*/
|
||||
static int kthread(void *_create)
|
||||
{
|
||||
struct kthread_create_info_t *create = _create;
|
||||
// 将这几个信息从kthread_create_info中拷贝过来。以免在kthread_create_info被free后,数据丢失从而导致错误。
|
||||
int (*thread_fn)(void *data) = create->thread_fn;
|
||||
void *data = create->data;
|
||||
|
||||
int retval = 0;
|
||||
|
||||
struct kthread_info_t *self = to_kthread(current_pcb);
|
||||
|
||||
self->thread_fn = thread_fn;
|
||||
self->data = data;
|
||||
|
||||
// todo: 增加调度参数设定
|
||||
// todo: 当前内核线程继承了kthreadd的优先级以及调度策略,需要在这里进行更新
|
||||
|
||||
// 设置当前进程为不可被打断
|
||||
current_pcb->state = PROC_UNINTERRUPTIBLE;
|
||||
|
||||
// 将当前pcb返回给创建者
|
||||
create->result = current_pcb;
|
||||
|
||||
current_pcb->state &= ~PROC_RUNNING; // 设置当前进程不是RUNNING态
|
||||
io_mfence();
|
||||
|
||||
// 发起调度,使得当前内核线程休眠。直到创建者通过process_wakeup将当前内核线程唤醒
|
||||
sched();
|
||||
|
||||
retval = -EINTR;
|
||||
// 如果发起者没有调用kthread_stop(),则该kthread的功能函数开始执行
|
||||
if (!(self->flags & (1 << KTHREAD_SHOULD_STOP)))
|
||||
{
|
||||
retval = thread_fn(data);
|
||||
}
|
||||
kthread_exit(retval);
|
||||
}
|
||||
|
||||
static void __create_kthread(struct kthread_create_info_t *create)
|
||||
{
|
||||
pid_t pid = kernel_thread(kthread, create, CLONE_FS | CLONE_SIGNAL);
|
||||
io_mfence();
|
||||
if (IS_ERR((void *)pid))
|
||||
{
|
||||
// todo: 使用complete机制完善这里
|
||||
|
||||
create->result = (struct process_control_block *)pid;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief kthread守护线程
|
||||
*
|
||||
* @param unused
|
||||
* @return int 不应当退出
|
||||
*/
|
||||
int kthreadd(void *unused)
|
||||
{
|
||||
kinfo("kthread daemon started!");
|
||||
struct process_control_block *pcb = current_pcb;
|
||||
kthreadd_pcb = current_pcb;
|
||||
current_pcb->flags |= PF_NOFREEZE;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
current_pcb->state = PROC_INTERRUPTIBLE;
|
||||
// 所有的创建任务都被处理完了
|
||||
if (list_empty(&kthread_create_list))
|
||||
sched();
|
||||
|
||||
spin_lock(&__kthread_create_lock);
|
||||
// 循环取出链表中的任务
|
||||
while (!list_empty(&kthread_create_list))
|
||||
{
|
||||
|
||||
// 从链表中取出第一个要创建的内核线程任务
|
||||
struct kthread_create_info_t *create =
|
||||
container_of(kthread_create_list.next, struct kthread_create_info_t, list);
|
||||
list_del_init(&create->list);
|
||||
spin_unlock(&__kthread_create_lock);
|
||||
|
||||
__create_kthread(create);
|
||||
|
||||
spin_lock(&__kthread_create_lock);
|
||||
}
|
||||
spin_unlock(&__kthread_create_lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 内核线程调用该函数,检查自身的标志位,判断自己是否应该执行完任务后退出
|
||||
*
|
||||
* @return true 内核线程应该退出
|
||||
* @return false 无需退出
|
||||
*/
|
||||
bool kthread_should_stop(void)
|
||||
{
|
||||
struct kthread_info_t *self = to_kthread(current_pcb);
|
||||
if (self->flags & (1 << KTHREAD_SHOULD_STOP))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 向kthread发送停止信号,请求其结束
|
||||
*
|
||||
* @param pcb 内核线程的pcb
|
||||
* @return int 错误码
|
||||
*/
|
||||
int kthread_stop(struct process_control_block *pcb)
|
||||
{
|
||||
int retval;
|
||||
struct kthread_info_t *target = to_kthread(pcb);
|
||||
target->flags |= (1 << KTHREAD_SHOULD_STOP);
|
||||
process_wakeup(pcb);
|
||||
// 等待指定的内核线程退出
|
||||
// todo: 使用completion机制改进这里
|
||||
while (target->exited == false)
|
||||
usleep(5000);
|
||||
retval = target->result;
|
||||
|
||||
// 释放内核线程的页表
|
||||
process_exit_mm(pcb);
|
||||
process_release_pcb(pcb);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置pcb中的worker_private字段(只应被设置一次)
|
||||
*
|
||||
* @param pcb pcb
|
||||
* @return bool 成功或失败
|
||||
*/
|
||||
bool kthread_set_worker_private(struct process_control_block *pcb)
|
||||
{
|
||||
if (WARN_ON_ONCE(to_kthread(pcb)))
|
||||
return false;
|
||||
|
||||
struct kthread_info_t *kt = kzalloc(sizeof(struct kthread_info_t), 0);
|
||||
if (kt == NULL)
|
||||
return false;
|
||||
pcb->worker_private = kt;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化kthread机制(只应被process_init调用)
|
||||
*
|
||||
* @return int 错误码
|
||||
*/
|
||||
int kthread_mechanism_init()
|
||||
{
|
||||
kinfo("Initializing kthread mechanism...");
|
||||
spin_init(&__kthread_create_lock);
|
||||
list_init(&kthread_create_list);
|
||||
// 创建kthreadd守护进程
|
||||
kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_SIGNAL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 释放pcb指向的worker private
|
||||
*
|
||||
* @param pcb 要释放的pcb
|
||||
*/
|
||||
void free_kthread_struct(struct process_control_block *pcb)
|
||||
{
|
||||
struct kthread_info_t *kthread = to_kthread(pcb);
|
||||
if (!kthread)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pcb->worker_private = NULL;
|
||||
kfree(kthread->full_name);
|
||||
kfree(kthread);
|
||||
}
|
28
kernel/src/process/preempt.h
Normal file
28
kernel/src/process/preempt.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#if ARCH(X86_64)
|
||||
#include <arch/x86_64/current.h>
|
||||
#else
|
||||
#error Unsupported architecture!
|
||||
#endif
|
||||
#include "proc-types.h"
|
||||
|
||||
/**
|
||||
* @brief 增加自旋锁计数变量
|
||||
*
|
||||
*/
|
||||
#define preempt_disable() \
|
||||
do \
|
||||
{ \
|
||||
++(current_pcb->preempt_count);\
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief 减少自旋锁计数变量
|
||||
*
|
||||
*/
|
||||
#define preempt_enable() \
|
||||
do \
|
||||
{ \
|
||||
--(current_pcb->preempt_count);\
|
||||
}while(0)
|
144
kernel/src/process/proc-types.h
Normal file
144
kernel/src/process/proc-types.h
Normal file
@ -0,0 +1,144 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/wait_queue.h>
|
||||
|
||||
// 进程最大可拥有的文件描述符数量
|
||||
#define PROC_MAX_FD_NUM 16
|
||||
|
||||
// 进程的内核栈大小 32K
|
||||
#define STACK_SIZE 32768
|
||||
|
||||
// 进程的运行状态
|
||||
// 正在运行
|
||||
#define PROC_RUNNING (1 << 0)
|
||||
// 可被中断
|
||||
#define PROC_INTERRUPTIBLE (1 << 1)
|
||||
// 不可被中断
|
||||
#define PROC_UNINTERRUPTIBLE (1 << 2)
|
||||
// 挂起
|
||||
#define PROC_ZOMBIE (1 << 3)
|
||||
// 已停止
|
||||
#define PROC_STOPPED (1 << 4)
|
||||
|
||||
// 内核代码段基地址
|
||||
#define KERNEL_CS (0x08)
|
||||
// 内核数据段基地址
|
||||
#define KERNEL_DS (0x10)
|
||||
// 用户代码段基地址
|
||||
#define USER_CS (0x28)
|
||||
// 用户数据段基地址
|
||||
#define USER_DS (0x30)
|
||||
|
||||
// 进程初始化时的数据拷贝标志位
|
||||
#define CLONE_FS (1UL << 0) // 在进程间共享打开的文件
|
||||
#define CLONE_SIGNAL (1UL << 1)
|
||||
#define CLONE_VM (1UL << 2) // 在进程间共享虚拟内存空间
|
||||
|
||||
#define PCB_NAME_LEN 16
|
||||
|
||||
struct thread_struct
|
||||
{
|
||||
// 内核层栈基指针
|
||||
ul rbp; // in tss rsp0
|
||||
// 内核层代码指针
|
||||
ul rip;
|
||||
// 内核层栈指针
|
||||
ul rsp;
|
||||
|
||||
ul fs, gs;
|
||||
|
||||
ul cr2;
|
||||
// 异常号
|
||||
ul trap_num;
|
||||
// 错误码
|
||||
ul err_code;
|
||||
};
|
||||
|
||||
// ========= pcb->flags =========
|
||||
// 进程标志位
|
||||
#define PF_KTHREAD (1UL << 0) // 内核线程
|
||||
#define PF_NEED_SCHED (1UL << 1) // 进程需要被调度
|
||||
#define PF_VFORK (1UL << 2) // 标志进程是否由于vfork而存在资源共享
|
||||
#define PF_KFORK (1UL << 3) // 标志在内核态下调用fork(临时标记,do_fork()结束后会将其复位)
|
||||
#define PF_NOFREEZE (1UL << 4) // 当前进程不能被冻结
|
||||
|
||||
/**
|
||||
* @brief 进程控制块
|
||||
*
|
||||
*/
|
||||
struct process_control_block
|
||||
{
|
||||
// 进程的状态
|
||||
volatile long state;
|
||||
// 进程标志:进程、线程、内核线程
|
||||
unsigned long flags;
|
||||
int64_t preempt_count; // 持有的自旋锁的数量
|
||||
long signal;
|
||||
long cpu_id; // 当前进程在哪个CPU核心上运行
|
||||
char name[PCB_NAME_LEN];
|
||||
|
||||
// 内存空间分布结构体, 记录内存页表和程序段信息
|
||||
struct mm_struct *mm;
|
||||
|
||||
// 进程切换时保存的状态信息
|
||||
struct thread_struct *thread;
|
||||
|
||||
// 连接各个pcb的双向链表
|
||||
struct List list;
|
||||
|
||||
//todo:给pcb中加一个spinlock_t成员
|
||||
//进程自旋锁
|
||||
// spinlock_t alloc_lock;
|
||||
|
||||
// 地址空间范围
|
||||
// 用户空间: 0x0000 0000 0000 0000 ~ 0x0000 7fff ffff ffff
|
||||
// 内核空间: 0xffff 8000 0000 0000 ~ 0xffff ffff ffff ffff
|
||||
uint64_t addr_limit;
|
||||
|
||||
long pid;
|
||||
long priority; // 优先级
|
||||
int64_t virtual_runtime; // 虚拟运行时间
|
||||
|
||||
// 进程拥有的文件描述符的指针数组
|
||||
// todo: 改用动态指针数组
|
||||
struct vfs_file_t *fds[PROC_MAX_FD_NUM];
|
||||
|
||||
// 链表中的下一个pcb
|
||||
struct process_control_block *next_pcb;
|
||||
// 父进程的pcb
|
||||
struct process_control_block *parent_pcb;
|
||||
|
||||
int32_t exit_code; // 进程退出时的返回码
|
||||
uint32_t policy; // 进程调度策略标志位
|
||||
wait_queue_node_t wait_child_proc_exit; // 子进程退出等待队列
|
||||
|
||||
/* PF_kTHREAD | PF_IO_WORKER 的进程,worker_private不为NULL*/
|
||||
void *worker_private;
|
||||
};
|
||||
|
||||
// 将进程的pcb和内核栈融合到一起,8字节对齐
|
||||
union proc_union
|
||||
{
|
||||
struct process_control_block pcb;
|
||||
ul stack[STACK_SIZE / sizeof(ul)];
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
struct tss_struct
|
||||
{
|
||||
unsigned int reserved0;
|
||||
ul rsp0;
|
||||
ul rsp1;
|
||||
ul rsp2;
|
||||
ul reserved1;
|
||||
ul ist1;
|
||||
ul ist2;
|
||||
ul ist3;
|
||||
ul ist4;
|
||||
ul ist5;
|
||||
ul ist6;
|
||||
ul ist7;
|
||||
ul reserved2;
|
||||
unsigned short reserved3;
|
||||
// io位图基地址
|
||||
unsigned short io_map_base_addr;
|
||||
} __attribute__((packed)); // 使用packed表明是紧凑结构,编译器不会对成员变量进行字节对齐。
|
36
kernel/src/process/proc.S
Normal file
36
kernel/src/process/proc.S
Normal file
@ -0,0 +1,36 @@
|
||||
#include"../common/asm.h"
|
||||
|
||||
/**
|
||||
* @brief 导出内核线程的执行引导程序
|
||||
* 目的是还原执行现场(在kernel_thread中伪造的)
|
||||
* 执行到这里时,rsp位于栈顶,然后弹出寄存器值
|
||||
* 弹出之后还要向上移动7个unsigned long的大小,从而弹出额外的信息(详见pt_regs)
|
||||
*/
|
||||
|
||||
ENTRY(kernel_thread_func)
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
popq %r12
|
||||
popq %r11
|
||||
popq %r10
|
||||
popq %r9
|
||||
popq %r8
|
||||
popq %rbx
|
||||
popq %rcx
|
||||
popq %rdx
|
||||
popq %rsi
|
||||
popq %rdi
|
||||
popq %rbp
|
||||
popq %rax
|
||||
movq %rax, %ds
|
||||
popq %rax
|
||||
movq %rax, %es
|
||||
popq %rax
|
||||
addq $0x20, %rsp
|
||||
popfq
|
||||
addq $0x10, %rsp
|
||||
movq %rdx, %rdi
|
||||
callq *%rbx
|
||||
movq %rax, %rdi
|
||||
callq process_do_exit
|
1229
kernel/src/process/process.c
Normal file
1229
kernel/src/process/process.c
Normal file
File diff suppressed because it is too large
Load Diff
226
kernel/src/process/process.h
Normal file
226
kernel/src/process/process.h
Normal file
@ -0,0 +1,226 @@
|
||||
/**
|
||||
* @file process.h
|
||||
* @author longjin
|
||||
* @brief 进程
|
||||
* @date 2022-01-29
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <common/cpu.h>
|
||||
#include <common/glib.h>
|
||||
#include <syscall/syscall.h>
|
||||
#include "ptrace.h"
|
||||
#include <common/errno.h>
|
||||
#include <filesystem/VFS/VFS.h>
|
||||
#include <common/wait_queue.h>
|
||||
#include <mm/mm-types.h>
|
||||
|
||||
#if ARCH(I386) || ARCH(X86_64)
|
||||
#include <arch/x86_64/current.h>
|
||||
#else
|
||||
#error Unsupported architecture!
|
||||
#endif
|
||||
|
||||
#include "proc-types.h"
|
||||
|
||||
// 设置初始进程的PCB
|
||||
#define INITIAL_PROC(proc) \
|
||||
{ \
|
||||
.state = PROC_UNINTERRUPTIBLE, \
|
||||
.flags = PF_KTHREAD, \
|
||||
.preempt_count = 0, \
|
||||
.signal = 0, \
|
||||
.cpu_id = 0, \
|
||||
.mm = &initial_mm, \
|
||||
.thread = &initial_thread, \
|
||||
.addr_limit = 0xffffffffffffffff, \
|
||||
.pid = 0, \
|
||||
.priority = 2, \
|
||||
.virtual_runtime = 0, \
|
||||
.fds = {0}, \
|
||||
.next_pcb = &proc, \
|
||||
.parent_pcb = &proc, \
|
||||
.exit_code = 0, \
|
||||
.wait_child_proc_exit = 0, \
|
||||
.worker_private = NULL, \
|
||||
.policy = SCHED_NORMAL \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 任务状态段结构体
|
||||
*
|
||||
*/
|
||||
|
||||
// 设置初始进程的tss
|
||||
#define INITIAL_TSS \
|
||||
{ \
|
||||
.reserved0 = 0, \
|
||||
.rsp0 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), \
|
||||
.rsp1 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), \
|
||||
.rsp2 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), \
|
||||
.reserved1 = 0, \
|
||||
.ist1 = 0xffff800000007c00, \
|
||||
.ist2 = 0xffff800000007c00, \
|
||||
.ist3 = 0xffff800000007c00, \
|
||||
.ist4 = 0xffff800000007c00, \
|
||||
.ist5 = 0xffff800000007c00, \
|
||||
.ist6 = 0xffff800000007c00, \
|
||||
.ist7 = 0xffff800000007c00, \
|
||||
.reserved2 = 0, \
|
||||
.reserved3 = 0, \
|
||||
.io_map_base_addr = 0 \
|
||||
}
|
||||
|
||||
#define GET_CURRENT_PCB \
|
||||
"movq %rsp, %rbx \n\t" \
|
||||
"andq $-32768, %rbx\n\t"
|
||||
|
||||
/**
|
||||
* @brief 切换进程上下文
|
||||
* 先把rbp和rax保存到栈中,然后将rsp和rip保存到prev的thread结构体中
|
||||
* 然后调用__switch_to切换栈,配置其他信息,最后恢复下一个进程的rax rbp。
|
||||
*/
|
||||
|
||||
#define switch_proc(prev, next) \
|
||||
do \
|
||||
{ \
|
||||
__asm__ __volatile__("pushq %%rbp \n\t" \
|
||||
"pushq %%rax \n\t" \
|
||||
"movq %%rsp, %0 \n\t" \
|
||||
"movq %2, %%rsp \n\t" \
|
||||
"leaq switch_proc_ret_addr(%%rip), %%rax \n\t" \
|
||||
"movq %%rax, %1 \n\t" \
|
||||
"pushq %3 \n\t" \
|
||||
"jmp __switch_to \n\t" \
|
||||
"switch_proc_ret_addr: \n\t" \
|
||||
"popq %%rax \n\t" \
|
||||
"popq %%rbp \n\t" \
|
||||
: "=m"(prev->thread->rsp), "=m"(prev->thread->rip) \
|
||||
: "m"(next->thread->rsp), "m"(next->thread->rip), "D"(prev), "S"(next) \
|
||||
: "memory"); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief 初始化系统的第一个进程
|
||||
*
|
||||
*/
|
||||
void process_init();
|
||||
|
||||
/**
|
||||
* @brief fork当前进程
|
||||
*
|
||||
* @param regs 新的寄存器值
|
||||
* @param clone_flags 克隆标志
|
||||
* @param stack_start 堆栈开始地址
|
||||
* @param stack_size 堆栈大小
|
||||
* @return unsigned long
|
||||
*/
|
||||
unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned long stack_start, unsigned long stack_size);
|
||||
|
||||
/**
|
||||
* @brief 根据pid获取进程的pcb
|
||||
*
|
||||
* @param pid
|
||||
* @return struct process_control_block*
|
||||
*/
|
||||
struct process_control_block *process_get_pcb(long pid);
|
||||
|
||||
/**
|
||||
* @brief 将进程加入到调度器的就绪队列中
|
||||
*
|
||||
* @param pcb 进程的pcb
|
||||
*/
|
||||
int process_wakeup(struct process_control_block *pcb);
|
||||
|
||||
/**
|
||||
* @brief 将进程加入到调度器的就绪队列中,并标志当前进程需要被调度
|
||||
*
|
||||
* @param pcb 进程的pcb
|
||||
*/
|
||||
int process_wakeup_immediately(struct process_control_block *pcb);
|
||||
|
||||
/**
|
||||
* @brief 使当前进程去执行新的代码
|
||||
*
|
||||
* @param regs 当前进程的寄存器
|
||||
* @param path 可执行程序的路径
|
||||
* @param argv 参数列表
|
||||
* @param envp 环境变量
|
||||
* @return ul 错误码
|
||||
*/
|
||||
ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[]);
|
||||
|
||||
/**
|
||||
* @brief 释放进程的页表
|
||||
*
|
||||
* @param pcb 要被释放页表的进程
|
||||
* @return uint64_t
|
||||
*/
|
||||
uint64_t process_exit_mm(struct process_control_block *pcb);
|
||||
|
||||
/**
|
||||
* @brief 进程退出时执行的函数
|
||||
*
|
||||
* @param code 返回码
|
||||
* @return ul
|
||||
*/
|
||||
ul process_do_exit(ul code);
|
||||
|
||||
/**
|
||||
* @brief 当子进程退出后向父进程发送通知
|
||||
*
|
||||
*/
|
||||
void process_exit_notify();
|
||||
|
||||
/**
|
||||
* @brief 初始化内核进程
|
||||
*
|
||||
* @param fn 目标程序的地址
|
||||
* @param arg 向目标程序传入的参数
|
||||
* @param flags
|
||||
* @return int
|
||||
*/
|
||||
|
||||
pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
|
||||
|
||||
int process_fd_alloc(struct vfs_file_t *file);
|
||||
|
||||
int process_release_pcb(struct process_control_block *pcb);
|
||||
|
||||
/**
|
||||
* @brief 切换页表
|
||||
* @param prev 前一个进程的pcb
|
||||
* @param next 下一个进程的pcb
|
||||
*
|
||||
*/
|
||||
#define process_switch_mm(next_pcb) \
|
||||
do \
|
||||
{ \
|
||||
asm volatile("movq %0, %%cr3 \n\t" ::"r"(next_pcb->mm->pgd) \
|
||||
: "memory"); \
|
||||
} while (0)
|
||||
// flush_tlb();
|
||||
|
||||
// 获取当前cpu id
|
||||
#define proc_current_cpu_id (current_pcb->cpu_id)
|
||||
|
||||
extern unsigned long head_stack_start; // 导出内核层栈基地址(定义在head.S)
|
||||
extern ul _stack_start;
|
||||
extern void ret_from_intr(void); // 导出从中断返回的函数(定义在entry.S)
|
||||
|
||||
extern struct tss_struct initial_tss[MAX_CPU_NUM];
|
||||
extern struct mm_struct initial_mm;
|
||||
extern struct thread_struct initial_thread;
|
||||
extern union proc_union initial_proc_union;
|
||||
extern struct process_control_block *initial_proc[MAX_CPU_NUM];
|
||||
|
||||
/**
|
||||
* @brief 给pcb设置名字
|
||||
*
|
||||
* @param pcb 需要设置名字的pcb
|
||||
* @param pcb_name 保存名字的char数组
|
||||
*/
|
||||
void process_set_pcb_name(struct process_control_block *pcb, const char *pcb_name);
|
37
kernel/src/process/ptrace.h
Normal file
37
kernel/src/process/ptrace.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef __PTRACE_H__
|
||||
|
||||
#define __PTRACE_H__
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
struct pt_regs
|
||||
{
|
||||
unsigned long r15;
|
||||
unsigned long r14;
|
||||
unsigned long r13;
|
||||
unsigned long r12;
|
||||
unsigned long r11;
|
||||
unsigned long r10;
|
||||
unsigned long r9;
|
||||
unsigned long r8;
|
||||
unsigned long rbx;
|
||||
unsigned long rcx;
|
||||
unsigned long rdx;
|
||||
unsigned long rsi;
|
||||
unsigned long rdi;
|
||||
unsigned long rbp;
|
||||
unsigned long ds;
|
||||
unsigned long es;
|
||||
unsigned long rax;
|
||||
unsigned long func;
|
||||
unsigned long errcode;
|
||||
unsigned long rip;
|
||||
unsigned long cs;
|
||||
unsigned long rflags;
|
||||
unsigned long rsp;
|
||||
unsigned long ss;
|
||||
};
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user