일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 셀레니움
- 스터디 관리
- 현장실습 IT
- DNS동작원리
- 값 객체
- Spring
- Executors
- 자바
- 정렬 기준
- aws ec2
- excalidraw
- 스프링 회원가입 인증
- 프로그래머스
- 위키 꾸미기
- OpenAI
- 스프링
- nurigo
- 현장실습
- 잘하고싶다..
- 개발자 디자인
- 인턴
- 숭실대
- 위키 탭
- Java
- NAVER D2
- REST
- 문자 인증
- 스트림
- ssh
- 사이드 프로젝트
- Today
- Total
뭐요
예제로 알아보는 xv6에서 시스템 호출 구현하기 (2) 본문
예제로 알아보는 xv6에서 시스템 호출 구현하기
시스템 호출 구현
지난 시간에 이어 xv6에서 시스템 호출을 구현해보자.
추적할 시스템 콜을 지정하는 정수 [mask]를 인자로 받아 리턴될 때 프로세스 아이디, 시스템 콜 이름, 리턴 값이 출력되는 시스템호출을 구현해보려고 한다.
우리의 목표
- trace 시스템 콜 추가 및 호출하는 쉘 프로그램 구현
trace 시스템호출 구현
추적할 시스템 콜을 지정하는 정수 [mask]를 인자로 받아 리턴될 때 프로세스 아이디, 시스템 콜 이름, 리턴 값이 출력되는 시스템호출을 구현해보자.
1) proc.h에서 struct proc에 int형 tracemask 변수 추가
// Per-process state
struct proc {
uint sz; // Size of process memory (bytes)
pde_t* pgdir; // Page table
char *kstack; // Bottom of kernel stack for this process
enum procstate state; // Process state
int pid; // Process ID
'
'
'
int tracemask; // add field
};
2) sysproc.c에서 sys_trace() 추가
User-level function에서 Kernel-level function으로 바로 argument를 전달할 수 없다. 따라서 xv6의 자체적인 built-in function을 사용해서 인자를 넘겨주어야 한다. 대표적으로 argint, argptr, argstr이 있다. 우리는 int형을 인자로 받을 것이기에, argint를 사용한다.
// trace (pass the integer argument (user to kernel))
int
sys_trace(void){
if(argint(0, &myproc()->tracemask) < 0){
return -1;
}
return 0;
}
3) syscall.h에서 sys_trace() 추가
#define SYS_mkdir 20
#define SYS_close 21
#define SYS_memsize 22
#define SYS_trace 23 // 추가
4) syscall.c에서 sys_trace() 추가
extern int sys_uptime(void);
extern int sys_memsize(void);
'
'
'
extern int sys_trace(void); // 추가
static int (*syscalls[])(void) = {
[SYS_close] sys_close,
[SYS_memsize] sys_memsize,
'
'
'
[SYS_trace] sys_trace, // 추가
};
5) syscall.c에서 syscall() 수정
void
syscall(void)
{
int num;
struct proc *curproc = myproc();
num = curproc->tf->eax;
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
curproc->tf->eax = syscalls[num]();
// trace
if(curproc->tracemask >> num){
cprintf("syscall traced: pid = %d, syscall = %s, %d returned\\n", curproc->pid, syscallnames[num], curproc->tf->eax);
}
} else {
cprintf("%d %s: unknown sys call %d\\n",
curproc->pid, curproc->name, num);
curproc->tf->eax = -1;
}
}
또한 syscall 이름을 불러오기 위해 char *[]을 하나 생성한다.
char *syscallnames[] = {
[SYS_fork] "fork",
[SYS_exit] "exit",
[SYS_wait] "wait",
[SYS_pipe] "pipe",
[SYS_read] "read",
[SYS_kill] "kill",
[SYS_exec] "exec",
[SYS_fstat] "fstat",
[SYS_chdir] "chdir",
[SYS_dup] "dup",
[SYS_getpid] "getpid",
[SYS_sbrk] "sbrk",
[SYS_sleep] "sleep",
[SYS_uptime] "uptime",
[SYS_open] "open",
[SYS_write] "write",
[SYS_mknod] "mknod",
[SYS_unlink] "unlink",
[SYS_link] "link",
[SYS_mkdir] "mkdir",
[SYS_close] "close",
[SYS_memsize] "memsize",
[SYS_trace] "trace",
};
6) proc.c에서 fork() 수정
자식 프로세스 생성하면서 부모 프로세스의 정보를 자식 프로세스로 복사해주는데, 우리가 만든 tracemask 또한 그래야 한다.
// copy trace mask
np->tracemask = curproc->tracemask; // 추가
7) user.h에서 trace() 추가
char* sbrk(int);
int sleep(int);
int uptime(void);
int memsize(void); // 새로운 시스템 호출 추가
int trace(int); // 새로운 시스템 호출 추가
8) usys.S에서 trace() 추가
SYSCALL(sleep)
SYSCALL(uptime)
SYSCALL(memsize) // 새로운 시스템 호출 추가
SYSCALL(trace) // 새로운 시스템 호출 추가
9) ssu_trace.c 파일 생성
#include "types.h"
#include "stat.h"
#include "user.h"
int main(int argc, char *argv[]){
int pid;
int mask = atoi(argv[1]);
int flag;
int wpid;
// argv 초기화
char *tmpArgv[argc-2];
int idx = 0;
for(int i = 2 ; i < argc; i++){
tmpArgv[idx++] = argv[i];
}
pid = fork();
if(pid < 0){
printf(1, "init: fork failid\\n");
exit();
}
if(pid == 0){
flag = trace(mask);
if(flag == 0){
exec(tmpArgv[0], tmpArgv);
}else{
printf(1, "trace failed");
}
exit();
}
while((wpid = wait()) >= 0 && wpid != pid){
printf(1, "zombie!\\n");
}
}
10) 실행 결과

간단하게 실행의 흐름을 말해보면 fork 후 자식 프로세스에서 trace 시스템 호출을 통해 인자로받은 mask 값을 넘겨준다. 성공적으로 trace()가 호출되었으면 인자로 받은 명령어를 실행한다.
이후 memsize()처럼 작동 확인을 위해 쉘 프로그램을 등록했다.
'Operating System > xv6' 카테고리의 다른 글
예제로 알아보는 xv6에서 시스템 호출 구현하기 (1) (0) | 2023.02.28 |
---|---|
xv6에서 로그인 구현 (0) | 2023.02.28 |
xv6에서 hcat 쉘 프로그램 작성 (0) | 2023.02.28 |
xv6에서 helloworld 쉘 프로그램 작성 (0) | 2023.02.28 |
[xv6] writing 1 byte into a region of size 0 에러 (2) | 2022.09.11 |