允许用户自定义信号处理函数 (#112)

* new: 用户注册信号处理函数,能够进入自定义的handler

* 修复忘了传信号的数字给用户的处理函数的bug

* new:sigreturn

* 删除注释
This commit is contained in:
login
2022-12-17 16:27:50 +08:00
committed by GitHub
parent 0e0c187484
commit 6efd474033
12 changed files with 566 additions and 100 deletions

View File

@ -11,6 +11,15 @@ ifeq ($(ARCH), __x86_64__)
libc_sub_dirs += sysdeps/x86_64
endif
libc_objs:= $(shell find ./*.c)
ECHO:
@echo "$@"
$(libc_objs): ECHO
$(CC) $(CFLAGS) -c $@ -o $@.o
clean:
cargo clean
rm -rf $(GARBAGE)
@ -20,7 +29,7 @@ clean:
cd .. ;\
done
libc: unistd.o fcntl.o malloc.o errno.o printf.o stdlib.o ctype.o string.o dirent.o time.o libc_rust
libc: $(libc_objs) libc_rust
@list='$(libc_sub_dirs)'; for subdir in $$list; do \
echo "make all in $$subdir";\
cd $$subdir;\
@ -28,36 +37,6 @@ libc: unistd.o fcntl.o malloc.o errno.o printf.o stdlib.o ctype.o string.o diren
cd ..;\
done
unistd.o: unistd.c
$(CC) $(CFLAGS) -c unistd.c -o unistd.o
fcntl.o: fcntl.c
$(CC) $(CFLAGS) -c fcntl.c -o fcntl.o
malloc.o: malloc.c
$(CC) $(CFLAGS) -c malloc.c -o malloc.o
errno.o: errno.c
$(CC) $(CFLAGS) -c errno.c -o errno.o
printf.o: printf.c
$(CC) $(CFLAGS) -c printf.c -o printf.o
stdlib.o: stdlib.c
$(CC) $(CFLAGS) -c stdlib.c -o stdlib.o
ctype.o: ctype.c
$(CC) $(CFLAGS) -c ctype.c -o ctype.o
string.o: string.c
$(CC) $(CFLAGS) -c string.c -o string.o
dirent.o: dirent.c
$(CC) $(CFLAGS) -c dirent.c -o dirent.o
time.o: time.c
$(CC) $(CFLAGS) -c time.c -o time.o
libc_rust:
rustup default nightly
cargo +nightly build --release --target ./x86_64-unknown-none.json

View File

@ -1,4 +1,5 @@
#pragma once
#include <libc/src/unistd.h>
#define SIGHUP 1
#define SIGINT 2
@ -37,4 +38,52 @@
/* These should not be considered constants from userland. */
#define SIGRTMIN 32
#define SIGRTMAX MAX_SIG_NUM
#define SIGRTMAX MAX_SIG_NUM
typedef void (*__sighandler_t) (int);
// 注意该结构体最大16字节
union __sifields {
/* kill() */
struct
{
pid_t _pid; /* 信号发送者的pid */
} _kill;
};
// 注意该结构体最大大小为32字节
#define __SIGINFO \
struct \
{ \
int32_t si_signo; /* signal number */ \
int32_t si_code; \
int32_t si_errno; \
uint32_t reserved; /* 保留备用 */ \
union __sifields _sifields; \
}
typedef struct
{
union {
__SIGINFO;
uint64_t padding[4]; // 让siginfo占用32字节大小
};
} siginfo_t;
typedef struct
{
uint64_t set;
} sigset_t;
struct sigaction
{
// sa_handler和sa_sigaction二选1
__sighandler_t sa_handler;
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
uint64_t sa_flags;
void (*sa_restorer)(void);
};
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
int signal(int signum, __sighandler_t handler);

View File

@ -0,0 +1,44 @@
#include <libc/src/include/signal.h>
#include <libc/src/printf.h>
#include <libc/src/stddef.h>
#include <libsystem/syscall.h>
#pragma GCC push_options
#pragma GCC optimize("O0")
void __libc_sa_restorer()
{
// 在这里发起sigreturn,请注意由于内核需要读取到原来的do_signal时保存的栈帧因此这里不能发生函数调用会导致函数压栈只能够这样来完成sigreturn
__asm__ __volatile__("int $0x80 \n\t" ::"a"(SYS_RT_SIGRETURN) : "memory");
}
#pragma GCC pop_options
/**
* @brief 设置信号处理动作(简单版本)
*
* @param signum
* @param handler
* @return int
*/
int signal(int signum, __sighandler_t handler)
{
struct sigaction sa = {0};
sa.sa_handler = handler;
// 由于DragonOS必须由用户程序指定一个sa_restorer因此这里设置为libc的sa_restorer
sa.sa_restorer = &__libc_sa_restorer;
// printf("handler address: %#018lx\n", handler);
// printf("restorer address: %#018lx\n", &__libc_sa_restorer);
sigaction(SIGKILL, &sa, NULL);
}
/**
* @brief 设置信号处理动作
*
* @param signum 信号
* @param act 处理动作不可为NULL
* @param oldact 返回的旧的处理动作若为NULL则不返回
* @return int 错误码遵循posix
*/
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
{
return syscall_invoke(SYS_SIGACTION, (uint64_t)signum, (uint64_t)act, (uint64_t)oldact, 0, 0, 0, 0, 0);
}

View File

@ -15,20 +15,22 @@
#define SYS_BRK 9
#define SYS_SBRK 10
#define SYS_REBOOT 11 // 重启
#define SYS_CHDIR 12 // 切换工作目录
#define SYS_REBOOT 11 // 重启
#define SYS_CHDIR 12 // 切换工作目录
#define SYS_GET_DENTS 13 // 获取目录中的数据
#define SYS_EXECVE 14 // 执行新的应用程序
#define SYS_WAIT4 15 // 等待进程退出
#define SYS_EXIT 16 // 进程退出
#define SYS_MKDIR 17 // 创建文件夹
#define SYS_EXECVE 14 // 执行新的应用程序
#define SYS_WAIT4 15 // 等待进程退出
#define SYS_EXIT 16 // 进程退出
#define SYS_MKDIR 17 // 创建文件夹
#define SYS_NANOSLEEP 18 // 纳秒级休眠
#define SYS_CLOCK 19 // 获取当前cpu时间
#define SYS_CLOCK 19 // 获取当前cpu时间
#define SYS_PIPE 20
#define SYS_MSTAT 21 // 获取系统的内存状态信息
#define SYS_MSTAT 21 // 获取系统的内存状态信息
#define SYS_UNLINK_AT 22 // 删除文件夹/删除文件链接
#define SYS_KILL 23 // kill一个进程(向这个进程发出信号)
#define SYS_KILL 23 // kill一个进程(向这个进程发出信号)
#define SYS_SIGACTION 24 // 设置进程的信号处理动作
#define SYS_RT_SIGRETURN 25 // 从信号处理函数返回
/**
* @brief 用户态系统调用函数
@ -44,4 +46,5 @@
* @param arg7
* @return long
*/
long syscall_invoke(uint64_t syscall_id, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t arg7);
long syscall_invoke(uint64_t syscall_id, uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4,
uint64_t arg5, uint64_t arg6, uint64_t arg7);