Section 5. 애플리케이션의 동작
5.1 ls 커맨드의 동작
리눅스에서 구동되는 커맨드 라인 애플리케이션의 대부분은 libc를 이용하고 있다. libc는 커널의 시스템 콜을 이용해 디바이스에 액세스한다.
ls
에 파일을 지정하면 해당 파일명이, 디렉터리를 지정하면 해당 디렉터리에 들어있는 파일명 리스트가, 옵션으로 -l
을 붙이면 파일의 퍼미션(허가권), 소유권, 크기, 타임스탬프(데이터 입력 날짜와 시간) 등의 상세 정보가 표시된다. 이건 뭐 Chapter 1의 Section 1에서 이미 언급을 했었다.
5.2 strace로 동작 추적
strace
는 인수로 지정한 커맨드가 사용하는 시스템 콜이나 신호를 표시해준다. 이로써 대상 커맨드의 상세한 동작을 파악하거나 개발 시에는 디버그 정보도 손에 넣을 수 있다.
strace ls /dev/null
을 실행하면 매우 긴 실행문을 볼 수 있다. 이 책에서 설명하는 순으로 일부 발췌해보면 다음과 같다.
1) 우선 프로그램을 실행하는 시스템 콜 execve를 이용해 /bin/ls를 실행한다.
2) open 시스템 콜을 호출하여 파일에 O_RDONLY flag를 부여하고 파일을 연다. =3
은 open 시스템 콜이 성공했을 때 반환되는 파일 디스크립터 값이다. 그 후 파일 디스크립터를 읽어오는 read 시스템 콜에 open 시스템 콜에서 반환된 파일 디스크립터 값을 지정하여 실행한다.
3) stat, lstat, fstat로 파일 /dev/null 상태를 확인한다.
4) 파일이나 디바이스를 메모리에 매핑하는 mmap2 시스템 콜을 호출한다. 반환되는 값은 매핑된 위치 정보이다. 그 후, ls 실행 결과, 여기에서는 /dev/null밖에 찾지 못했으므로 /dev/null과 write 시스템 콜을 사용해 쓰기를 실행한다. 마지막으로 close 시스템 콜로 표준 출력을 닫고 munmap 시스템 콜로 메모리상에 매핑된 /dev/null의 영역도 언매핑, 파일 디스크립터 '2'를 닫고 exit_group 시스템 콜을 실행하여 프로세스 중인 모든 스레드로부터 exit한다.
다음 과정을 통해 ls /dev/null
뿐인데도 상당히 많은 시스템 콜이 호출되었다는 것을 알 수 있다. 이를 통해 하드디스크(디바이스)에 있는 파일 리스트의 정보를 얻고 디스플레이(디바이스)에 그 결과를 표시하려면 커널에 준비된 시스템 콜이 반드시 필요하다는 것을 알 수 있다.