System Call with Linux
system call 확인하기
- 간단한 hello world 예제이다.
- strace를 이용해 요청한 시스템 콜을 알아보자.
- strace 각각의 줄은 1개의 시스템 콜이다.
- write( ) 시스템 콜을 확인할 수 있다.
- 이외에도 많은 시스템 콜이 호출되었다.
- 대부분 main( ) 함수 앞뒤로 실행된 것들이며 프로그램의 시작과 종료 처리 중 호출된 것이다.
system call의 소요 시간 확인하기
- strace -T 옵션을 이용
- 시스템 콜 처리에 걸린 시간을 측정 가능하다.
- system 점유율이 높을 때 이 기능을 통해 부하를 찾아낸다.
실험
CPU 정보 확인하는 법
sar -P ALL 1
- 명령어를 통해 cpu 의 모드를 확인할 수 있다.
- idle
- kernel, user mode가 아닌 상태
- user, nice
- user mode인 상태
- system
- kernel mode인 상태
실험 1
- loop를 걸어서 확인해보자.
#include <stdio.h>
int main(){
for(;;);
}
- user mode에서 계속 돌아가는 것을 볼 수 있다.
- cpu 3번
실험 2
- 이번에는 getppid( ) 시스템 콜을 이용해보자.
#include <sys/types.h>
#include <unistd.h>
int main(){
for(;;)
getppid();
}
- 일정 비율로 kernel과 user mode가 실행되었음을 알 수 있다.
- 즉 사용자 모드 -> 커널 모드 -> 사용자 모드 …
system call의 wrapper 함수
system call은 보통 C언어 같은 고급 언어에서 직접 호출이 불가능하다.
아키텍처에 의존하는 어셈블리 코드를 사용해 호출된다.
getppid( ) 시스템 콜은 x86_64 아키텍처에서 다음과 같이 호출된다.
mov $0x6e, %eax // 시스템 콜 번호를 eax 레지스터에 대입
syscall
만약 wrapper 함수가 없었다면 어셈블리 언어를 사용해서 system call을 호출했을 것이다.
- 이는 이식성이 매우 낮으며 프로그램 작성 시 오래 걸린다.
고급언어로 작성된 사용자 프로그램은 단순히 시스템 콜의 wrapper 함수를 호출하면 된다.
wrapper 함수는 단순하게 시스템 콜을 요청하는 함수이다.
- trap이 걸리면 eax레지스터를 참조해 커널 모드로 함수가 실행됨.
표준 C 라이브러리
c 언어에는 표준 라이브러리가 있다.
- glibc 를 사용한다.
glibc는 system call의 wrapper 함수를 포함한다.
- posix 규격에 정의된 함수도 제공
ldd 명령을 통해 링크하는 라이브러리를 볼 수 있다.
- libc / 표준 C 라이브러리를 링크하고 있다.
- 참고로 파이썬도 내부적으로는 C 라이브러리를 사용한다.
이해가 안 간다면 다음 글을 참고해보자.