프로세스
프로세스의 정의 및 특성
프로세스란?
- 프로세스는 실행 중인 프로그램의 인스턴스로 설명됩니다.
- 프로세스는 실행흐름이지만, 관리가 되어지는 실행흐름들. 스케쥴링 단위.
- 독립된 가상 메모리를 가지고 사용함. 서로 침범해서는 안돼.
Q. 사용해보면 프로세스>> CPU 이던데..?
- 물리적으로는 1번에 1개만 수행하는데, 컨텍스트 스위칭으로 동시에 실행되는것처럼 보여짐.
- 프로그램의 메모리에 올라가지 않아도 프로세스가 있을수있음.
- 여기에는 프로그램의 명령, 사용된 메모리 및 액세스된 시스템 리소스가 포함됩니다.
UNIX 프로세스
- UNIX 프로세스는 다른 프로세스로부터 보호됩니다:
- 자체 메모리를 가짐
- 전용 CPU에서 실행되는 것처럼 보임
- 사용하는 시스템 서비스가 전용으로 제공됨
- 이러한 환경을 유지하기 위해 하드웨어 지원이 필요합니다
실행 파일 형식
실행 파일 형식
- 각 실행 파일은 특정 실행 파일 형식으로 저장됩니다.
- 실행 파일 형식은 다음 정보를 제공합니다:
- 프로그램에 필요한 환경 정보
- 프로그램 코드 자체
- 기타 메타데이터
- 많은 현대 시스템에서 ELF 형식을 사용합니다. (Windows는 PE, macOS는 Mach-O를 사용)
- ELF 실행 파일과 라이브러리는 두 가지 유형의 정보를 포함합니다:
- 객체를 로드하고 실행하는 데 필요한 정보
- 객체를 링크하는 데 필요한 정보
로딩
- 로딩은 실행 파일이나 공유 라이브러리를 메모리로 이동하는 과정입니다.
- 리눅스에서 커널은 로딩을 시작하고, ld-linux.so가 이를 마무리합니다:
- 커널은 ELF 실행 파일의 여러 부분을 제자리에 이동시킴
- 로더를 제자리에 이동시킴
- 커널은 로더를 호출하여 메모리 내 프로그램 데이터를 변경함
- 로더는 프로그램의 시작 지점으로 점프
프로세스의 메모리 레이아웃

프로그램에서 프로세스로
- 실행 파일이 메모리로 로드되어 프로세스가 됩니다.
- 프로세스의 메모리 레이아웃은 ELF 섹션을 모방합니다.
- 시스템은 로드된 레이아웃에 추가 의미를 부여합니다.
- 대부분의 POSIX 시스템은 동일하거나 유사한 레이아웃을 사용합니다.
기본 레이아웃
- 현대 시스템은 또한:
- ELF 파일에 나타나지 않는 프로그램 코드인 공유 라이브러리를 매핑
- 매핑된 섹션의 위치를 무작위화
- 그러나 논리적 레이아웃은 동일하게 유지됩니다.
- 특히 섹션의 순서는 유지됩니다.
텍스트 섹션
- 텍스트 섹션은 실제 프로그램 명령어를 포함합니다.
- 어셈블러는 ELF .text 섹션에 바이너리 기계 명령어를 배치합니다.
- 커널은 텍스트를 프로세스의 메모리에 복사하고, 로더는 이를 실행할 준비를 합니다.
데이터 & BSS 섹션
- 데이터 섹션은 컴파일 시 초기값이 정의된 변수와 상수를 포함합니다.
- 링커는 이 데이터를 ELF .data 섹션에 삽입하고, 커널은 이를 프로세스의 메모리에 로드합니다.
- BSS 섹션은 컴파일 시 값이 정의되지 않은 변수를 포함합니다.
- 커널은 프로그램을 로드할 때 BSS를 위한 공간을 만듭니다.
스택과 힙
- 스택: 함수 호출에 대한 지역 변수를 포함
- 힙: 명시적으로 할당된 메모리를 포함
- 스택과 힙은 모두 성장할 수 있습니다.
- 따라서 힙과 스택 사이에 매핑되지 않은 공간이 존재합니다.
ELF 구조와 프로세스의 구조 비교
ELF 구조
ELF 파일이란?
- ELF(Executable and Linking Format)는 실행 파일, 객체 코드, 공유 라이브러리 및 코어 덤프에 사용되는 표준 파일 형식입니다.
- 주로 UNIX 및 UNIX-like 시스템에서 사용됩니다.
ELF 파일의 주요 섹션
-
텍스트 섹션 (.text)
- 실제 프로그램 코드가 포함되어 있습니다.
- 프로세서가 실행하는 기계 명령어가 포함됩니다.
-
데이터 섹션 (.data)
- 컴파일 시 초기값이 정의된 변수와 상수들이 포함됩니다.
- 문자열 상수, 전역 변수 등과 같은 데이터가 포함됩니다.
-
BSS 섹션 (.bss)
- 초기값이 정의되지 않은 변수들이 포함됩니다.
- 예를 들어, 초기화되지 않은 전역 변수 등이 포함됩니다.
ELF 파일의 추가 섹션
- 헤더: 파일의 전반적인 구조와 정보를 정의합니다.
- 심볼 테이블: 프로그램의 변수와 함수 심볼에 대한 정보를 포함합니다.
- 섹션 헤더 테이블: 파일에 포함된 각 섹션에 대한 정보를 포함합니다.
- 프로그램 헤더 테이블: 실행 파일의 메모리 매핑 정보 등을 포함합니다.
프로세스의 구조
프로세스란?
- 프로세스는 실행 중인 프로그램의 인스턴스입니다.
- 프로세스는 실행 파일을 메모리에 로드한 후, 운영체제가 이를 관리합니다.
프로세스의 주요 메모리 영역
-
텍스트 섹션
- 실행 파일의 .text 섹션이 메모리로 로드되어 실행됩니다.
- 프로그램의 기계 명령어가 포함되어 있으며, 실행 시 실제로 프로세서가 실행합니다.
-
데이터 섹션
- 실행 파일의 .data 섹션이 메모리로 로드됩니다.
- 초기값이 설정된 전역 변수와 상수가 포함됩니다.
-
BSS 섹션
- 실행 파일의 .bss 섹션이 메모리로 로드됩니다.
- 초기값이 설정되지 않은 전역 변수들이 포함됩니다.
추가 메모리 영역
-
힙 (Heap)
- 동적 메모리 할당을 위해 사용됩니다.
- malloc()과 같은 함수 호출로 런타임 중에 메모리를 할당합니다.
-
스택 (Stack)
- 함수 호출 시 지역 변수와 반환 주소를 저장합니다.
- 함수 호출 시마다 새로운 스택 프레임이 생성됩니다.
프로세스 환경
- 프로세스 제어 블록 (PCB)
- 프로세스의 상태, 레지스터 값, 프로그램 카운터, 메모리 관리 정보 등을 포함합니다.
- 운영체제가 프로세스를 관리하기 위해 사용합니다.
비교
공통점
- 텍스트 섹션: ELF 파일의 .text 섹션은 프로세스의 텍스트 섹션으로 로드되어 프로그램 명령어를 실행합니다.
- 데이터 섹션: ELF 파일의 .data 섹션은 프로세스의 데이터 섹션으로 로드되어 초기값이 설정된 변수를 포함합니다.
- BSS 섹션: ELF 파일의 .bss 섹션은 프로세스의 BSS 섹션으로 로드되어 초기값이 설정되지 않은 변수를 포함합니다.
차이점
-
메모리 레이아웃
- ELF 파일은 파일 형식으로 디스크에 저장되며, 프로세스로 로드되면 메모리 레이아웃이 달라집니다.
- 프로세스는 추가적인 메모리 영역(스택, 힙)을 포함하며, 동적 메모리 할당과 함수 호출을 위한 공간이 필요합니다.
-
실행 환경
- ELF 파일은 단순히 실행 파일을 저장하는 형식이지만, 프로세스는 운영체제에 의해 관리되는 실행 중인 엔티티입니다.
- 프로세스는 PCB와 같은 제어 구조를 통해 운영체제에 의해 관리됩니다.
운영체제와의 상호작용
- ELF 파일
- 파일 시스템에 저장되고, 실행 시 로더에 의해 메모리로 로드됩니다.
- 프로세스
- 실행 파일이 로드된 후, 운영체제의 스케줄러, 메모리 관리자, 시스템 호출 인터페이스와 상호작용합니다.
이 비교를 통해 ELF 파일이 단순히 프로그램의 실행 파일 형식인 반면, 프로세스는 실행 중인 프로그램으로서 더 복잡한 메모리 구조와 운영체제와의 상호작용을 포함하는 것을 알 수 있습니다.
프로세스 환경
프로세스 환경
- 프로세스는 메모리 외에도 복잡한 환경을 가집니다.
- 커널 서비스:
- 생명 주기:
커널 서비스
- 커널은 프로세스를 대신하여 서비스를 수행합니다.
- POSIX 시스템은 다음을 제공합니다:
- 이를 시행하기 위해 하드웨어 지원이 필요합니다.
- 따라서 프로세스는 시스템 호출을 통해 커널에 접근을 요청해야 합니다.
커널/사용자 공간 분리
- 커널은 POSIX 시스템의 모든 공유 자원을 관리합니다:
- 메모리
- 파일
- 하드웨어 장치 (마우스, 키보드, 디스플레이 등)
- 커널은 이들을 제어하기 위해 슈퍼바이저 모드에서 실행됩니다.
- 프로세스는 사용자 모드에서 실행되며, 이를 사용자 공간(userspace)이라 부릅니다.
프로세스 생명 주기
- 프로세스의 메모리 공간은 커널에 의해 생성됩니다.
- 프로세스는 커널에 의해 생성됩니다.
- 프로세스가 완료되면, 자원은 정리되어야 합니다:
- fork() 시스템 호출
- 버츄얼 메모리 공간이 만들어지는데, A프로세스의 버츄얼 메모리 스페이스를 복사해서 만들어줌. 빈 깡통 공간이 아님!
- 모든 프로세스마다 3개의 파일이 만들어져. stdin,stdout,error 이렇게 3개. 0,1,2 는 예약된 프로세스
시스템 호출
-
각 시스템콜 마다 번호가 매핑되어있음. ex) 오픈은 1번 등등
-
번호를 통해서 OS 에 요청할거임.
-
레지스터에 저장을 한다.
-
시스템콜을 할때는 스택을 사용할 수 없어 => 즉, arg 의 제한이 있어. cpu의 레지스터 개수는 정해져있으니. 이 개수만큼만 사용가능.
-
특정 레지스터에 약속된 값을 저장해놓고, interupt 를 실행.
-
Ex) OS님 제가 read syscall 하고 싶습니다.
보호 도메인
- 슈퍼바이저 모드와 사용자 모드는 보호 도메인입니다.
- 보호 도메인 간의 전환에는 하드웨어 지원이 필요합니다.
- 따라서 시스템 호출은 단순한 함수일 수 없습니다.
- x86_64 리눅스 시스템에서 시스템 호출은 소프트웨어 인터럽트를 통해 접근합니다.
함수 호출
- 일반 함수 호출:
- 함수 인수를 특정 레지스터나 스택에 배치
- 현재 프로그램 카운터를 스택에 배치
- 프로그램 카운터를 호출된 함수의 첫 번째 명령어로 변경
- 함수 완료 시:
- 반환 값을 특정 레지스터에 배치
- 이전 프로그램 카운터를 스택에서 가져옴
- 프로그램 카운터를 호출 위치로 변경
시스템 호출 호출
- 시스템 호출은 특별한 호출 방식을 가집니다:
- 시스템 호출 번호를 특정 레지스터에 배치
- 시스템 호출 인수를 다른 레지스터에 배치
- syscall 프로세서 명령어를 호출
- 그 후 CPU 하드웨어:
- 시스템 호출 실행 후:
- 반환 값을 특정 레지스터에 배치
- sysret 프로세서 명령어를 호출
- CPU 하드웨어:
프로세스 생명 주기
프로세스 생성
- fork() 시스템 호출: 부모 프로세스를 복제하여 새로운 프로세스를 생성.
- 새로운 프로세스 ID(PID) 생성.
- 부모 프로세스의 메모리 공간을 복사하여 새로운 프로세스에 할당.
- fork()는 호출 프로세스를 복제하여 다음을 수행:
- 새로운 프로세스 ID (PID)와 커널 구조 생성
- 새로운 메모리 공간 생성
- 현재 프로세스의 전체 내용을 새로운 메모리 공간으로 복사
- fork() 호출에서 두 프로세스 모두 실행을 반환
- 원래 프로세스에서 fork()는 새로운 PID를 반환
- 새로운 프로세스에서 fork()는 0을 반환
프로세스 가족
- 모든 POSIX 프로세스는 부모 프로세스를 가짐
- 프로세스는 fork() 또는 posix_spawn()을 호출하여 자식 프로세스를 가질 수 있음
- 부모 프로세스가 종료되면, 프로세스는 고아가 됨
- 고아 프로세스는 init에 의해 채택됨
- 모든 프로세스의 가족은 트리를 형성
fork()/exec() 모델
- fork된 프로세스는 생성자의 동일한 프로그램을 실행해야 함
- POSIX는 새로운 프로그램을 실행하는 exec() 시스템 호출 제공
- 많은 시스템에서 다음을 위한 단일 호출 제공:
- 새로운 프로세스 생성
- 해당 프로세스에서 새로운 프로그램 실행
- 현대 POSIX 시스템은 이를 위해 posix_spawn() 제공
프로세스 종료
- 프로세스는 다음 시점에 종료:
- exit() 시스템 호출을 호출할 때
- main()에서 반환될 때
- 특정 신호를 받고 처리하지 못할 때 (예: SIGSEGV)
- 첫 두 경우에는 선택한 값을 반환:
- exit()의 정수 인수
- main()의 정수 반환 값
- 세 번째 경우에는 신호에 의해
프로그램 실행
- exec() 시스템 호출: 새로운 프로그램을 현재 프로세스 주소 공간에 로드하여 실행.
- 현재 프로세스의 이미지가 새로운 프로그램 이미지로 대체됨.
시스템 리소스와의 상호작용
파일 시스템
- 프로세스는 파일을 열고 읽거나 쓸 수 있음.
- 파일 디스크립터를 통해 열린 파일을 추적.
시스템 호출
- 프로세스는 커널 서비스에 접근하기 위해 시스템 호출을 사용.
- 시스템 호출은 하드웨어 인터럽트를 통해 커널 모드로 전환됨.
신호 (Signals)
- 프로세스 간 또는 커널이 프로세스에 신호를 보낼 수 있음.
- 신호는 특정 이벤트(예: 종료, 예외 등)를 프로세스에 알림.
프로세스 환경 변수
- 프로세스는 실행 시 환경 변수(environ)를 가짐.
- getenv()와 setenv() 함수를 통해 환경 변수를 읽거나 설정할 수 있음.
작업 디렉토리
- 프로세스는 현재 작업 디렉토리를 가짐.
- chdir() 시스템 호출로 현재 작업 디렉토리를 변경할 수 있음.
프로세스 종료
- exit() 시스템 호출: 프로세스가 종료될 때 호출.
- 메모리, 파일 디스크립터 등 모든 자원을 정리하고 해제.
- wait() 시스템 호출: 부모 프로세스가 자식 프로세스의 종료를 기다림.
요약
- 프로세스가 뭔지
- 프로세스가 실행될때 주변 환경이 어떻게 되는지
- ELF 파일 포멧
- fork 가 되서 불러지는 모양들