본문 바로가기
CS/운영체제

[프로세스] 프로세스 연산

by DI_Lee 2021. 10. 2.

이번에는 프로세스의 생성과 복사에 대해 살펴보자.


(1) 프로세스의 구조

 

  • 프로세스는 정적 할당 영역인 코드 영역, 데이터 영역과 동적 할당 영역인 스택 영역과 힙 영역으로 구성

이때 코드 영역과 데이터 영역은 프로세스가 실행되기 직전에 위치와 크기가 결정되고 실행되는 동안 변하지 않으므로 정적 할당 영역. 스택 영역과 힙 영역은 프로세스가 실행되는 동안 만들어지는 영역으로 크기가 늘어났다 줄어들기도 하는 동적 할당 영역

 

EX ) 스파게티를 만드는 과정에 비유

 

[코드 영역]  👉🏻 요리책 (레시피가 적힌 요리책처럼 코드 영역에 프로세스의 본문이 기술)

  • 텍스트 영역이라고도 함. 프로그래머가 작성한 프로그램이 탑재되는 곳으로 탑재된 코드는 읽기전용으로 처리.

[데이터 영역] 👉🏻 재료

  • 코드가 실행되면서 사용하는 변수나 파일 등 각종 데이터를 모아놓은 곳으로 변하는 값이기 때문에 읽기와 쓰기가 가능.

[스택 영역] 👉🏻 조리 도구 ( 코드를 작동하기 위해 운영체제가 부수적으로 관리하는 데이터 영역. 사용자에게는 스택의 내용이 보이지 않는다)

  • 운영체제가 프로세스를 실행하기 위해 부수적으로 필요한 데이터를 모아놓은 곳으로 프로세스를 작동하기 위해 커널이 유지하는 자료 구조.
  • 스택은 함수 호출 시 두가지 작업을 구현하기 위해 사용 (180p ~)
    1. 스택은 변수 사용 범위에 영향을 미치는 영역을 구현할 때 사용. 즉, 지역 변수를 저장할 때 스택을 사용
    2. 호출한 함수가 종료되면 함수를 호출하기 전 코드로 되돌아와야 하는데 되돌아올 메모리의 주소를 스택에 저장

 

[+ 힙 영역] 

  • 대부분의 데이터는 데이터 영역에 할당되고 그 크기가 정해진다. 그러나 일부 데이터는 프로그램이 실행되는 동안 할당됨.
  • 이때 할당해야 할 메모리의 크기를 프로그램이 실행되는 동안 결정해야하는 경우에 유용하게 사용되는 공간

(2) 프로세스의 생성과 복사

 

[프로세스를 새로 생성하는 기존의 과정]

프로세스는 프로그램을 실행하면 운영체제가 프로그램을 메모리로 가져와 코드 영역에 넣고 프로세스 제어 블록을 생성 -> 메모리에 데이터 영역과 스택 영역을 확보한 후 프로세스를 실행

 

[이미 실행중인 프로세스로부터 복사해 새로운 프로세스를 생성하는 과정]

fork() 시스템 호출 이용

 

fork() 시스템 호출이란?

( *시스템 호출 : 1장 운영체제의 구조에서 언급(51p). 시스템 호출은 커널이 자신을 보호하기 위해 만든 인터페이스로 사용자나 응용 프로그램으로부터 컴퓨터 자원을 보호하기 위해 자원에 직접 접근하는 것을 차단. 따라서 자원을 이용하려면 시스템 호출이라는 인터페이스를 이용하여 접근)

  • 정의 : fork() 시스템 호출은 실행 중인 프로세스로부터 새로운 프로세스를 복사 하는 함수.

이때 기존의 프로세스는 부모 프로세스 가 되고 새로 생긴 프로세스는 자식 프로세스 가 되며, 두 프로세스는 부모-자식 관계 로 연결된다.

  • 동작 과정

위에서 볼 수 있듯이 fork() 시스템 호출을 하면 프로세스 제어 블록을 포함한 부모 프로세스 영역의 대부분이 자식 프로세스에 복사됨. 그러나 프로세스 구분자, 메모리 관련정보(메모리의 위치), 부모 프로세스 구분자/자식 프로세스 구분자는 변경.

 

  • 장점
  1. 프로세스 생성 속도가 빠름  → 하드디스크에서 프로그램을 새로 가져오는 것이 아니라 기존 메모리에서 복사 하기 때문에 생성속도 빠름
  2. 추가 작업 없이 자원 상속  → 부모 프로세서가 사용하던 모든 자원을 추가 작업 없이 자식 프로세스에 상속
  3. 시스템 관리의 효율성 증가  → 자식 프로세스를 종료하면 자식이 사용하던 자원을 부모 프로세스가 정리 가능

(3) 프로세스의 전환

fork() 시스템 호출을 이용해 이미 실행중인 프로세스로부터 복사해 새로운 프로세스를 생성한 뒤, 복사된 프로세스를 새로운 프로세스로 전환하는 과정 을 살펴보자.

exec() 시스템 호출이란?

  • 정의 : exec() 는 프로세스는 그대로 둔 채 내용만 바꾸는 시스템 호출 로, 현재의 프로세스가 완전히 다른 프로세스로 전환된다.

  • 목적 : 프로세스의 구조체를 재활용하기 위함. 이미 만들어진 프로세스 제어 블록, 메모리 영역, 부모-자식 관계를 그대로 사용할 수 있어서 편리

 

  • 동작 과정

 

exec() 시스템 호출을 하면 코드 영역에 있는 기존의 내용을 지우고 새로운 코드로 바꾸고 데이터 영역이 새로운 변수로 채워지며 스택 영역이 리셋 된다. 프로세스 제어 블록의 경우 내용 중 프로세스 구분자, 부모/자식 프로세스 구분자, 메모리 관련 사항은 변하지 않지만 프로그램 카운터 레지스터 값을 비롯한 각종 레지스터와 사용한 파일 정보가 모두 리셋

→ 마치 프로세스를 처음 시작하는 것처럼 내용이 정리 

 


(4) 프로세스의 계층 구조

fork()와 exec() 시스템 호출을 사용한 프로세스의 복사와 전환은 프로세스의 생성 과정과 계층 구조를 이해하는데 중요한 열쇠

 

  • 유닉스의 프로세스 계층 구조 정의

유닉스에서 커널이 처음 메모리에 올라와 부팅(운영체제를 메모리에 올리는 과정)이 되면 커널 관련 프로세스를 여러 개 만드는데 그중 init 프로세스가 전체 프로세스의 출발점

→ 즉, 프로세스의 효율적인 관리를 위해 init 프로세스에 fork()와 exec() 시스템 호출을 이용하여 나머지 프로세스들을 init 프로세스의 자식으로 만듦 으로써 위의 그림과 같이 트리 구조 를 이루게 됨. (init 프로세스의 자식으로는 login 프로세스, shell 프로세스 등이 존재)

 

  • 프로세스 계층 구조의 장점

1)  여러 작업의 동시 처리

→  ex) login 프로세스 : 여러 사용자가 동시에 접속한다면 fork() 시스템 호출로 login 프로세스를 여러 개 만들어 사용자에게 나누어 줌으로써 여러 사용자를 동시 처리 할 수 있음 -> shell 프로세스(사용자가 운영체제에 명령을 내리고 결과를 받을 수 있게함) 생성.

But, login 프로세스를 없애고 새로운 shell 프로세스 만드는 것 = 비효율적.

따라서 exec() 시스템 호출로 login 프로세스 -> shell 프로세스 로 !!

그러면 자원을 효율적으로 관리할 뿐 아니라, 기존의 부모-자식 관계도 유지

또한, shell 프로세스에서 명령어로 응용프로그램을 실행할 때도 fork()와 exec() 시스템 호출을 이용.

 

2)  용이한 자원 회수

→ 프로세스 계층 구조는 프로세스를 부모 – 자식 관계로 만들면 자식 프로세스가 작업을 마쳤을 때 사용하던 자원을 부모 프로세스가 회수하면 되는 구조로 프로세스 간의 책임 관계가 분명해져서 시스템을 관리하기 수월

 

  • 고아 프로세스

프로세스가 종료된 후에도 비정상적으로 남아있는 프로세스 = 고아 프로세스 / 좀비 프로세스

 

- 고아 프로세스 : 부모 프로세스가 자식보다 먼저 죽는 경우

- 좀비 프로세스 : 자식 프로세스가 종료 했음에도 부모가 뒤처리를 하지 않을 때 발생

컴퓨터에 이런 고아/좀비 프로세스가 많아지면 자원이 낭비되어 효율적인 운영에 방해

 

→ 따라서 운영체제는 반환되지 못한 자원을 회수하는 자원 회수를 주기적 으로 해야함.

(exit() 또는 return()문은 자식 프로세스가 작업이 끝났음을 부모 프로세스에 알려 부모프로세스가 미루어왔던 자원 정리나 자식 프로세스와의 동기화를 할 수 있음.)

 

 

 


 

자료 출처 : [쉽게 배우는 운영체제], 저자 조성호

책을 읽고 직접 정리한 내용입니다.

'CS > 운영체제' 카테고리의 다른 글

[스레드] 스레드의 개념 및 멀티스레드  (0) 2021.10.02