티스토리 뷰

728x90
반응형

본 내용은 학교 강의를 통해 개인적으로 공부한 내용입니다. 책은 쉽게 배우는 운영체제(한빛아카데미)를 참고했습니다. 조언은 언제든지 감사합니다 !

 

 

프로세스 메모리 구조


 

 

코드 영역

프로그램의 코드 본문이 저장되는 영역으로 읽기 전용(수정 불가)이다.

데이터 영역

프로그램이 사용하는 변수나 파일 등의 각종 데이터를 저장하는 곳이다. 변수 중에서도 전역 변수가 할당되는 영역이다.

힙 영역

동적으로 할당되는 변수 영역이다. c언어의 기준으로 malloc() 함수나 calloc() 함수에 의해 생성된 변수들이 이 곳에 할당된다.

동적 할당은 프로세스의 메모리 관리를 효율적으로 하기 위한 필수 요소다.

스택 영역

함수 호출이 발생할 경우 함수 호출의 전반적인 처리와 리턴 값을 가지고 있다. 그리고 이러한 함수에서 사용되는 지역 변수를 저장한다.

힙이나 스택 영역은 프로그램이 실행하는 동안 크기가 결정되는 동적 할당 영역이다. 입력 값에 의한 함수의 호출 횟수나 동적으로 생성되는 변수들의 크기는 런타임 시에 결정되기 때문이다.

반면에 프로그램 코드 자체나 전역 변수의 경우 실행되기 전에도 크기가 이미 정해져 있다. 또한 바뀔 일도, 바뀌어서도 안된다. 따라서 컴파일 시에 위치와 크기가 결정되는 정적 할당 영역이다.

추가로 힙 영역은 데이터를 낮은 주소 -> 높은 주소로 쌓아 올리고,

스택 영역은 높은 주소 -> 낮은 주소로 쌓아 올린다.

 

 

 

시스템 호출


시스템 호출(system call)은 운영 체제인 커널이 사용자에게 자신의 자원을 사용할 수 있도록 만든 인터페이스다. 즉, 사용자가 커널에 접근할 수 있는 유일한 수단이 시스템 호출이다.

이러한 시스템 호출을 만든 이유는 사용자나 응용 프로그램으로부터 컴퓨터의 자원을 직접적으로 접근하는 것을 막아 보호하기 위함이다.

 

                        

시스템 호출의 처리

  1. 사용자 모드에 있는 응용 프로그램이 커널의 기능을 사용할 수 있도록 한다.
  2. 시스템 호출을 하면 사용자 모드에서 커널 모드로 바뀐다.
  3. 커널에서 시스템 호출을 처리하면 커널 모드에서 사용자 모드로 돌아가 작업을 계속한다.

 

시스템 호출의 유형

  1. 프로세서 제어(process Control)
  2. 파일 조작(file manipulation)
  3. 장치 관리(Device Management)
  4. 정보 유지(Information maintenance)
  5. 통신(Communication)


fork()

실행 중인 프로세스로부터 새로운 프로세스를 복사하는 시스템 호출 함수다. 새로운 프로그램을 실행하는 속도보다 훨씬 빠르다.

실행하던 프로세스는 부모 프로세스, 새로 생긴 프로세스는 자식 프로세스로 부모-자식 관계의 계층 구조가 형성된다.


<프로세스의 변화>

-프로세스 구분자(PID)가 변한다.

-자식 프로세스가 생성되는 메모리 위치가 다르므로 메모리 관련 정보가 바뀐다.

-부모 프로세스에는 CPID(Child PID), 자식 프로세스에는 PPID(Parents PID)가 바뀐다. 만약 자식 프로세스가 없으면 -1로 값이 설정된다.


<장점>

-하드디스크로부터 프로그램을 새로 가져오지 않고 기존 메모리에서 복사하기 때문에 자식 프로세스의 생성 속도가 빠르다.

-추가 작업 없이 자원을 상속할 수 있다.

-자식 프로세스가 종료하면 그 자원을 부모 프로세스가 정리할 수 있어 시스템이 효율적으로 관리된다.


exec()

기존의 프로세스를 새로운 프로세스로 전환하는 시스템 호출 함수다. 프로세스는 그대로 둔 채 내용만 바꾼다.

이 시스템 호출을 사용하면 프로세스의 구조체를 재활횽할 수 있다.


<프로세스의 변화>

-코드 영역에 있는 기존의 내용을 지우고 새로운 코드로 바꾼다.

-데이터 영역이 새로운 변수로 채워지고 스택 영역이 리셋된다.

-프로그램 카운터 레지스터 값을 비롯한 각종 레지스터와 사용한 파일 정보가 모두 리셋된다.


<장점>

-새로운 프로세스 제어 블록을 만들고 메모리 자리를 확보하는 과정이 필요없다.

-기존의 PID를 그대로 사용하기 때문에 부모-자식의 계층 구조가 유지된다.

-위와 같은 이유 때문에 메모리 청소를 위한 상위 프로세스와의 새로운 부모-자식 관계를 만들지 않아도 된다.


exit()

작업의 종료를 알려주는 시스템 호출로, 자식 프로세스가 끝났음을 부모 프로세스에게 알려주어 부모 프로세스가 자원을 빨리 거둬갈 수 있게 만든다.

또한 인자 전달을 통해 자식 프로세스가 어떤 상태로 종료되었는지를 알려줄 수 있다.

exit() 호출을 하기 위한 C언어의 return() 문을 사용하는 이유도 프로세스의 처리 과정들을 보다 정확하고 확실히 함으로써 오류를 줄이고 프로그램의 성능을 더 좋게 만들 수 있다.


wait()

자식 프로세스가 끝나기를 기다리는 시스템 호출이다. 주로 부모 프로세스와 자식 프로세스 간 동기화에 사용되는데, 이 이유는 자식 프로세스보다 부모 프로세스가 먼저 종료되는 경우를 막기 위함이다.

이럴 경우 자식 프로세스의 자원을 정리할 부모 프로세스가 없어지고, 돌아갈 곳도 없어지는 미아 프로세스가 발생하기 때문에 시스템의 자원이 낭비되고 성능이 저하된다.


프로세스 계층 구조

위의 그림은 유닉스의 프로세스 계층 구조다.

유닉스에서 커널이 처음 메모리에 올라와 부팅이 되면 커널 관련 프로세스를 여러 개 만드는데, 그 중 init 프로세스는 전체 프로세스의 출발점이 된다. 이 init 프로세스는 이후에 생성되는 모든 프로세스를 자신의 자식 프로세스로 만들어 트리 구조를 이룬다. 이러한 구조는 동시에 여러 작업을 처리하고 종료된 프로세스의 자원을 회수하는데 용이하다.

예를들어 위의 사용자 1, 2, 3이 있는데, 이를 fork() 시스템 호출로 만드는 것이다. 그런 다음 login 프로세스를 처리하게 하고 이후부터 exec() 시스템 호출을 이용해 login 프로세스를 shell 프로세스로 전환시킨다. 그럼 각각의 사용자가 독립적으로 shell 프로세스를 이용할 수 있기 때문에 여러 작업을 처리할 수 있게 된다.

또한 이런 식으로 프로세스를 생성, 복제, 전환하면 모든 프로세스가 계층 구조를 이루게 되고, 부모 프로세스를 가지게 되므로 프로세스 종료 시 부모 프로세스가 자원을 회수할 수 있게 된다. 때문에 운영체제가 직접 자원을 회수하는 일이 적어져 효율적인 시스템 운영이 가능하다.

하지만 만약 부모 프로세스가 먼저 종료되거나 자식 프로세스가 비정상적으로 종료되는 경우 자원 회수가 안되어 미아 프로세스(좀비 프로세스)가 생성될 수 있다. 이 미아 프로세스가 많이자면 자원이 낭비되기 때문에 효율적인 운영이 방해되고 컴퓨터가 느려진다.

따라서 주기적으로 자원을 회수해야 한다. 위의 exit() 시스템 호출이 하나의 방법이다. 


728x90
반응형

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

CPU 스케줄링  (1) 2019.03.30
스레드  (0) 2019.03.26
프로세스  (0) 2019.03.22
Kernel (커널)  (0) 2019.03.10
운영체제의 정의와 역할  (0) 2019.03.10
댓글