Skip to content
GitLab
Explore
Projects
Groups
Topics
Snippets
Projects
Groups
Topics
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
某某某
OSKernel2024-GalaxyOS
Commits
d12200d1
Commit
d12200d1
authored
10 months ago
by
3KBz
Browse files
Options
Download
Patches
Plain Diff
update docs
parent
5d43755b
main
final1
malloc
socket
test
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
doc/final/img/signal.png
+0
-0
doc/final/img/signal.png
doc/final/决赛-信号机制.md
+126
-0
doc/final/决赛-信号机制.md
with
126 additions
and
0 deletions
+126
-0
doc/final/img/signal.png
0 → 100644
+
0
−
0
View file @
d12200d1
114 KB
This diff is collapsed.
Click to expand it.
doc/final/决赛-信号机制.md
0 → 100644
+
126
−
0
View file @
d12200d1
# 决赛:信号机制
信号用于实现进程间的通信,他有很多种来源,如外部信号,有终端Ctrl-C产生的SIGINT信号,定时器到期产生的SIGALRM信号等;还有显示请求信号,如
`kill`
函数向进程发送信号,在GalaxyOS中,信号的发送主要通过
`kill`
系统调用实现
## 信号实现原理
**信号相关数据结构**
在进程PCB中,定义了如下几个与信号相关的字段
```
c
struct
proc
{
...
struct
sigaction
sigaction
[
NSIG
];
__sigset_t
sig_pending
;
__sigset_t
sig_set
;
struct
sig_frame
*
sig_frame
;
...
};
```
成员
`sigpending`
表示进程是否有信号需要处理。成员
`sigaction`
表示信号相应的处理方法
信号的关键数据结构如下
```
c
typedef
struct
{
unsigned
long
__val
[
SIGSET_LEN
];
}
__sigset_t
;
struct
sigaction
{
union
{
__sighandler_t
sa_handler
;
// void (*sa_sigaction)(int, siginfo_t *, void *);
}
__sigaction_handler
;
__sigset_t
sa_mask
;
int
sa_flags
;
// void (*sa_restorer)(void);
};
```
**发送信号**
信号的发送通过
`kill()`
系统调用,它可以发送一个信号给指定的进程,其原型如下
```
c
int
kill
(
pid_t
pid
,
int
sig
);
```
调用
`kill()`
系统调用后,会陷入内核,调用
`sys_kill()`
,通过参数pid指定接收信号的进程,参数sig则是发送的信号,进而将信号发送给指定进程,其调用链大致过程如下,但是我们对于其处理还不够完善,日后还需要进行完善
> kill()
>
> | User Space
>
> ------------------------------------------------------------------------------------------------------------------------------------
>
> | Kernel Space
> sys_kill()
> |---> find_task_by_pid()
> |---> send_signal()
> |---> signal_wake_up()
**内核触发信号处理函数**
上面介绍了怎么发生一个信号给指定的进程,为了尽快让信号得到处理,我们把信号处理过程放置在进程从内核态返回到用户态前,如下代码所示
```
asm
# Trampoline for signal handling
#include "../include/sysnum.h"
.section sigtrampsec
.globl sig_trampoline
sig_trampoline:
.globl sig_handler
# void sig_handler(int signum, __sig_handler_t handler);
sig_handler:
jalr a1
li a7, SYS_rt_sigreturn
ecall
# Terminate the proc directly, and this is the default handler
# for any signal that's not set by user proc
.globl default_sigaction
# void term_handler(int signum);
default_sigaction:
# exit(-1);
li a0, -1
li a7, SYS_exit
ecall
```
其处理过程大致如下图

**设置信号处理程序**
信号处理程序主要实现在
`sigaction`
中,用户可以通过系统调用
`rt_sigaction`
来设置一个信号处理程序,其实现逻辑比较简单,进程管理结构中有个
`sigaction`
的字段,它是一个
`struct sigaction`
结构的数组,每个元素保存着对应信号的处理程序,所以,我们只需要根据传入参数
`signum`
获取对应的信号处理程序,然后将其设置为新的信号处理程序即可
```
c
int
sigaction
(
int
signum
,
struct
sigaction
*
act
,
struct
sigaction
*
oldact
)
{
// printf("sigaction start\n");
struct
proc
*
current
=
myproc
();
if
(
signum
<
1
||
signum
>
NSIG
)
return
-
1
;
if
(
oldact
)
*
oldact
=
current
->
sigaction
[
signum
];
if
(
act
)
current
->
sigaction
[
signum
]
=
*
act
;
// printf("sigaction ok\n");
return
0
;
}
```
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment
Menu
Explore
Projects
Groups
Topics
Snippets