System call
- mechanism used by an application program to request service from the OS.
- Request service throughout Interrupt(0x08 arm기준) (그림2)
- 그림 2를 보면, RTC(Real Time Clock), PIC(Interrupt controller), software(error, system call)의 interrupt가 CPU에 전해지고, CPU는 kernel을 통해 interrupt vector 을 찾아 해당 interrupt handler함수를 수행한다.
- PIC으로 device의 일반적인 interrupt가 전달됨
- System call 은 대부분 POSIX API에 정의되어 있음. API가 시스템콜을 수행해준다.
- API
- 서로 다른 layer가 서로 소통하기 위한 definition sets
- higher level SW 와 lower level SW사이의 abstraction를 위한 방식
- API없이 Macro로 직접 system call를 호출할 수 있다.
|
그림1 system call interface |
|
그림2 principal of interrupt handling |
|
그림3 system call flow |
그림3을 보자
- application에서 fork()라는 API를 호출하면, 해당 API에서는 system call 함수를 직접 호출한다. 여기서 parameter인 __NR_fork는 system call number이다.
- syscall 함수는 syscall.h에 나와 있으며, system call interface역할을 하는 녀석이다. 이녀석이 interrupt를 일으키고, interrupt vector 0x08(arm 기준)을 찾아간다. 여기서 system call 의 parameter 은 predefined register에 주로 저장되며, 넘치면 stack에 저장된다.
- Interrupt Vector은 interrupt table에서 system call에 맞는 System call handler을 찾아가도록 해준다.
- System call handler는 System Call Table에서 System call number에 맞는 system call 함수를 찾아 가도록 해준다.
- 실제 System call이 여기서 수행된다.
|
그림4 Adding new System call |
이번에는 그림4를 보고 system call 추가하는 방법을 공부해보자.
- unistd.h
- system call을 새로 정의하는 곳으로, system call number을 할당할 때에는 unistd.h에 안쓰는 번호로 할당하도록 한다.
- calls.S
- System call Table이 존재하는 곳이다. 여기에 CALL(sys_emb)등을 통해 system call table에 새로운 system call을 등록한다.
- kernel/
- 실제 system call 함수를 만들고 여기에 위치한다.
- Recompile
- 커널 컴파일을 수행하여 system call을 kernel에 등록한다.
|
그림5 unistd.h |
|
그림6 calls.s |
|
그림7 new system call |
|
그림8 new system call |
그림7,8 을 보자. 해당 함수는 kernel에 삽입 될 실제 system call 함수이다.
- asmlinkage
- c언어 함수가 assembly 코드와 link할 경우에 사용하는 명령어이다. 이 명령어를 사용하면 해당 함수는 register이 아닌 stack으로 변수를 관리하게 된다.
- calls.s는 어셈블리 언어로, stack으로 변수를 관리하는 녀석이기에, sync를 위해 이 명령어가 필요하다.
- copy_from_user(void *to, const void __user *from, unsigned long n) / copy_to_user(void __user *to, const void *from, unsigned long n)
- 그림8에서 해당 함수는 실제 커널에 존재하며, parameter은 user space로부터 넘어온 녀석이다. 그런데 커널에서 사용하는 메모리는 user memory와 다르기 때문에 이를 호환시킬 함수가 필요하다.
- copy_from_user은 user로부터 받아온 user영역의 메모리 주소를 통해 해당 값을 kernel memory에 copy하고, 해당 주소를 parameter을 통해 받아온다. copy_to_user은 이와 반대로, kernel memory의 주소를 통해 해당 값을 copy하여 유저의 메모리 address에 이를 대입시킨다.
|
그림 9 Makefile in kernel |
|
그림 10 application |
그림9는 kernel 내에서 생성한 system call을 컴파일하기 위한 makefile이고, 그림10은 application에서 POSIX API없이 매크로를 통해 system call 함수를 바로 호출 시키기 위한 코드이다. 366은 수행하고자하는 system call number이며, parameter을 추가하여 값을 system call 함수에 보낼 수 있다.
댓글
댓글 쓰기