프로그램과 프로세스

프로그램이란? 컴퓨터에서 동작하는 관련된 명령 및 데이터를 하나로 묶은 것

  • 컴파일러형 언어는 소스 코드를 빌드해서 만들어진 실행 파일을 프로그램이라고 한다.
  • 스크립트 언어는 소스 코드 그자체가 프로그램이 된다.
  • 커널도 프로그램의 일종이다.

프로세스란? 실행되어서 동작 중인 프로그램을 말한다.

커널

커널은 하드웨어 도움을 받아 프로세스가 장치에 직접 접근할 수 없도록 한다.
일반적인 CPU에는 커널 모드사용자 모드 두 종류의 모드가 있다고 한다.(대략적)
커널을 이용한 저장 장치에 간접적으로 접근하기

프로세스는 사용자 모드로 동작하므로 장치에 직접 접근할 수 없다. 그래서 프로세스는 커널을 통해서 간접적으로 장치에 접근한다.

커널은 커널 모드로 동작하면서 다른 프로세스에서는 불가능한 장치 제어, 시스템 자원 관리 및 배분 기능을 제공한다.

시스템 콜

시스템 콜이란? 프로세스가 커널에 처리를 요청하는 방법이다.
시스템 콜의 종류는 다음과 같다.

  • 프로세스 생성, 삭제
  • 메모리 확보, 해제
  • 통신 처리
  • 파일 시스템 조작
  • 장치 조작

시스템 콜을 통하지 않고 프로세스에서 직접 CPU 모드를 변경하는 방법은 존재하지 않는다.

시스템 콜 호출 확인해 보기

프로세스가 어떤 시스템 콜을 호출하는지 strace 명령어로 확인할 수 있다.

go 언어로 실습

hello.go 파일 생성(touch hello.go) -> hello.go에 코드 작성(vi hello.go)

package main

import (
	"fmt"
)

func main() {
	fmt.Println("hello world")
}

위의 hello.go 파일을 빌드 후 strace를 사용해서 어떤 시스템 콜을 호출하는지 확인한다.

go build hello.go
strace -o hello.log ./hello


시스템 콜이 몇번 일어났는지 확인하는 방법은 로그 파일에서 = 기호가 포함된 줄을 세면 된다.

grep '=' hello.log | wc -l


내 환경에서는 171번의 시스템 콜이 호출되었다.

python으로 실습

Go 언어 뿐만아니라 어떤 프로그래밍 언어라도 프로그램은 커널에 처리를 요청하려면 시스템 콜을 호출한다.

hello.py 생성(touch hello.py) -> hello.py작성(vi hello.py)

#!/user/bin/python3
print("hello world")

-> 작성 후 실행 권한 부여(chmod +x hello.py)


go언어로 작성한 것과 마찬가지로 write() 시스템 콜을 호출 하는 것을 확인할 수 있다.

단, strace 출력 내용은 용량이 커지기 마련이므로 파일 시스템의 남은 공간에 주의해야한다.

시스템 콜을 처리하는 시간 비율

논리 CPU가 실행하고 있는 명령 비율은 sar 명령어로 확인할 수 있다.

sar -P 0 1 1 명령어를 통해 CPU 코어 0이 어떤 종류의 처리를 실행하고 있는지 알아본다.

sar 명령어 의미

  • -P 0 → CPU 0번 코어만 측정
  • 1 → 1초 간격으로
  • 1 → 1번만 측정

sar 명령어

sar 명령어의 결과는 아래와 같다.

항목의미결과
%user사용자 공간에서 실행된 CPU 사용량1.01%
%nicenice로 낮은 우선순위 실행한 프로세스의 CPU 사용량0.00%
%system커널(System) 공간에서 실행된 CPU 사용량 (시스템 콜 포함)0.00%
%iowaitI/O(디스크, 네트워크) 대기 시간 비율0.00%
%steal가상화 환경에서 다른 VM이 가져간 CPU 비율0.00%
%idle사용되지 않은 (놀고 있는) CPU 시간 비율98.99%

CPU 0이 열심히 놀고 있는 것을 확인할 수 있다.

사용자 모드

CPU에게 일을 시킨 뒤에 sar 결과를 다시 확인해보면 아래와 같다.
우선 무한 반복을 하는 inf-loop.py를 작성하고
tasket명령어를 통해서 CPU 0이 inf-loop.py를 동작하도록 하고 sar 결과를 확인한다.

#!/usr/bin/python3
while True:
        pass

사용자 모드 sar

  1. taskset -c 0 ./inf-loop.py & 실행 의미
    • taskset -c <논리 CPU 번호> <명령어> : <명령어>를 인수로 지정한 명령어를 -c <논리 CPU 번호> 인수로 지정한 CPU에서 실행한다.
    • taskset -c 0 : CPU 0번에서만 inf-loop.py 실행
    • & : 백그라운드 실행 (터미널을 계속 사용할 수 있음)
    • inf-loop.py : 무한 루프가 있는 Python 스크립트 실행
  2. sar 명령어의 결과
    • 사용자 공간에서 실행된 CPU 사용량(%user)이 100임을 알 수 있다.

inf-loop.py 프로그램 실행 상황
운영체제는 CPU가 실행되는 모드를 사용자 모드(User Mode)커널 모드(Kernel Mode) 두 가지로 나눠서 관리 한다.
inf-loop.py에서 while 문 내에서 pass문은 아무 작업을 하지 않기 때문에 파일 입출력, 네트워크 등 시스템 호출 작업이 없다. 그래서 CPU는 사용자 모드에서만 100% 작동을 하게 되는 것이다.

무한 루프를 돌렸기 때문에 sar 명령어를 사용하고 프로세스를 종료시켜줘야한다.
kill <프로세스 ID>

커널 모드

부모 프로세스의 프로세스 ID를 얻는 시스템 콜을 발생(getppid())시켜서 sar 명령어를 확인해 본다.

#!/usr/bin/python3

import os

while True:
    os.getppid()

커널 모드 sar

계속해서 시스템 콜을 발생시켰기 때문에 %system이 많아 진 것을 확인할 수 있다.
syscall-inf-loop.py

sar 명령어를 사용하는 이유 : 모니터링

시스템이 예상대로 동작하는지 확인하기 위해서 sar 명령어를 비롯한 다양한 도구를 사용하여 시스템 통계 정보를 수집하는 것이다.
시스템 통계 정보를 수집하고 관리하는 구조를 모니터링(monitoring)이라고 부른다.
(모니터링 도구 : 프로메테우스, 자빅스, 데이터독 등)
숫자의 나열만 보는 것은 모니터링후 문제 해결하는데 효율적이지 않기 때문에 대시 보드 기능도 자주 사용하게 된다.

시스템 콜 소요 시간

strace의 -T 옵션을 사용하면 시스템 콜 처리에 걸린 시간을 마이크로 초 수준으로 정밀하게 측정이 가능하다.

strace -T -o hello.log ./hello

이후 cat hello.log를 확인한다면 아래와 같은 출력을 확인할 수 있다.

이 시스템 콜이 실행되는 데 17마이크로 초(µs)가 걸린 것을 확인할 수 있다.

이렇게 시스템 콜 소요시간을 사용하는 경우는
특정 시스템 콜이 얼마나 오래 걸리는지 측정을 통해서 성능 최적화를 할 수 도 있기 때문이다.

추가적으로 -tt 옵션을 통해서 시스템 콜이 호출된 시각을 측정할 수 도 있다.

-T, -tt 옵션 들을 통해서 어떤 시스템 콜이 얼마나 걸리고 언제 실행되는지를 파악해서 분석할 수 있게 된다.


라이브러리


💡 틈틈히 조금씩 읽고 작성할 예정입니다.

profile
개발하는 다람쥐

0개의 댓글