CS/OS

좀비가 되긴 싫었는데... 부모가 나를 버렸어

햄스타배 2025. 4. 30. 23:54

이번 포스팅의 주제는 프로세스입니다

 

 

목차

1. 프로세스란?

2. 프로세스의 생성과 상태 전이 

3. 프로세스 간 통신

 

1. 프로세스란

프로세스와 프로그램은 같은 것일까?

결론부터 말하자면 아니다!! 프로세스는 실행중인 프로그램의 인스턴스 중 하나로 하나의 프로그램에 여러개의 프로세스를 running 시킬 수 있다. 쉽게 말하면 프로그램을 실행하면 프로세스가 된다 이때 프로세스는 하나일수도 있고 여러개가 될 수도 있다.

또한 운영체제가 자원을 할당하고 관리하는 기본 단위로도 볼 수 있다

프로그램이 실행되면 운영체제는 다음과 같은 자원을 프로세스에게 할당한다. (줄여서 TDBS라 한다)

1. Text : 사용자가 작성한 프로그램 함수, code

2. Data: 전역변수, 정적 변수(불변변수)

3. BSS : 초기화되지 않은 전역/정적 변수

4. Stack: 지역변수, 함수파라미터, 반환 주소 등 임시 data

+)  Heap: 프로그램이 실행되는 동안 malloc과 같은 함수를 통해 동적으로 할당되는 영역

여러개의 프로세스가 실행된다면 Text 부분은 공유 메모리로 read only로 공유/관리되고 나머지는 완전히 분리되어 존재한다 각 프로세스는 PCB(프로세스 상태 표시메타데이터)를 가지는데 PCB에는 PID, 프로세스 상태, PC, CPU register, 스케쥴링 정보(프로세스 우선순위, 스케쥴링 파라미터), 메모리 관리 정보(Base/limit register, page table, segment table..), I/O status 정보(open file list, 할당된 입출력 장치 리스트..), Context save area, Accounting information(CPU 사용, 시작 후 경과한 clock 시간, 시간 제한).....등등 프로세스와 관련된 많은 정보들이 저장되어 커널에서 관리한다

 

2. 프로세스의 상태 전이

한 프로그램에서 여러개의 프로세스를 running할 수 있다고 했는데 CPU는 하나이다. CPU는 한 순간에 오직 하나의 프로세스만 돌릴 수 있다고 했는데 어떻게 여러개의 프로세스를 돌리는 것처럼 보인단 말인가!!

답은 간단한다.  A와 데이트를 하다가 화장실에 가는 척하며 B와 데이트를 하고.. B와 데이트를 하다가 화장실에 가는 척하며 A와 데이트를 이어간다.. 이걸 아주 빠르게 반복하면 A와 B 모두 나랑 시간을 보내고 있다고 착각하게 된다 이러면 나는 한정된 시간 내 두 명과 데이트하는 효율적인 일정을 소화해낼 수 있다

실제로는 이러면 안된다..

이렇게 타이머를 이용하여 일정 시간 동안 A프로세스를 running하고 타임 퀀텀이 끝나면 A프로세스를 not running 상태로 돌리고 ready queue에 있는 B프로세스를 running 시키는 작업을 Context switching이라 한다 

이렇게 process의 상태가 2가지만 있다면 참 좋겠지만... 세상은 그렇게 단순하지 않다

 

 

5가지 상태로 보자면 New, Ready, Running, Blocked, Terminated(Exit)로 나눌 수 있다

New는 프로세스가 생성되어 필요 자원(TDBS)을 할당 받기 위해 대기하는 상태이고

Ready는 필요한 자원을 할당받고 CPU 할당을 기다리는 상태이다 이러한 프로세스들이 대기하는 Ready queue가 존재한다

Running은 CPU에서 실행되는 상태(데이트중인 상태)이며 Blocked는 이벤트를 기다리는 상태로 이벤트가 발생하면 다시 Ready 상태로 돌아가 CPU 할당을 기다린다 이때 이벤트의 예시로는 file open, 입출력 등이 있다

Exit은 이러한 과정을 반복하고 프로세스가 완료되어 종료되는 상태이다

 

여기에서 끝나면 참 좋겠지만 UNIX Process Model로 더 세분화하여 공부해보자 

먼저 프로세스가 생성(8)되고 메모리 공간을 슥 둘러본다

메모리 자리가 없으면 하드디스크에서 Ready상태로 바뀌고(5) 메모리에 자리가 있으면 메모리에 자원을 할당받아 Ready상태(3)로 존재한다 메모리에서 Ready 상태로 있다가 스케쥴러가 타임 퀀텀(CPU 자원)을 할당해주면 커널모드나 유저모드로 running(1 or 2)이 된다 이러다가 이벤트 발생을 대기해야하는 상황이 오면 Asleep(4, Block상태)가 되는데 이때 메모리 관리를 하다가 별로 필요 없어보이면 메인 메모리에서 하드디스크로 쫓겨나기도(6) 한다.. 이렇게 메모리와 하드디스크사이의 이동을 Swap in/out이라 한다

이벤트가 발생되면 힙합정신으로 일어나 하드디스크에서 메모리를 할당받고 CPU를 할당받아 다시 Running 상태로 돌아간다 (메인메모리에서 Ready 상태로 있다가 Running될 수도 있다)

하지만 CPU는 냉정하다 내가 이렇게 바닥부터 올라왔어도 카리나가 CPU 할당을 요청하면 CPU는 나와의 시간이 끝나기도 전에 카리나에게 가버릴 것이다 즉 우선순위가 높은 프로세스가 CPU 할당을 요청하면 이전 실행중인 프로세스는 다시 Ready상태가 되어버린다 이 상태를 Preempted라고 한다

이렇게 각각의 프로세스가 재빠르게 상태전이를 하면서 CPU의 효율을 높여 프로그램을 실행한다

 

사실 이렇게만 말하면 .. 실제로는 어떻게 프로세스를 생성하는지 감이 잘 안잡힌다 아님말고

코드를 보기 전에 2가지만 기억하자

1. 프로세스는 또 다른 프로세스를 생성할 수 있으며 부모, 자식으로 정의한다

2. 부모프로세스는 자식프로세스보다 먼저 끝날 수 없다

 

코드를 보며 더 자세히 공부해보자

 

먼저 프로그램을 돌리면 첫번째 프로세스가 생성이 되고 ready 상태에서 running 상태로 바뀌면서 유저가 짠 코드를 실행하게 된다(전역변수 a는 data영역에, 지역변수 b는 stack에 저장) 그러다 fork() 함수를 만나면 새로운 프로세스를 생성한다

이렇게 프로세스는 또 다른 프로세스를 생성할 수 있는데 fork()함수를 호출한 프로세스를 부모 프로세스, 생성된 프로세스를 자식프로세스라고 한다 부모의 fork() 리턴값은 자식의 pid이고 자식의 fork()의 리턴값은 0(오류나면 음수)이기때문에 저 코드에서는 자식프로세스라면 변수 값들을 하나씩 올려주고 부모프로세스라면 wait 함수를 통해 자식 프로세스가 종료될때까지 기다린다 

만약 wait 함수를 안쓰면 어떤 일이 일어날까?

자식 프로세스가 먼저 종료되어도 할당 받은 메모리를 제대로 반환하지 못한다 이러한 상태를 Zoobie 상태라하고

부모프로세스가 먼저 종료되면 챙겨줄 부모도 없고 메모리도 제대로 반환하지 못하는 Orphan 상태가 되어버린다

 

이외에도 exec()을 이용하여 fork()를 통해 복제 생성된 자식프로세스에게 새로운 역할을 하는 프로세스를 덮어씌워 다른 일을 시킬 수도 있다

 

3. 프로세스 간 통신(IPC)

프로세스는  협력을 통해 특정 태스크를 빨리 실행하기 위해 서브 태스크로 나누어 병렬처리를 할 수 있다 

 

1. 공유 메모리 시스템

일반적으로 OS는 한 프로세스가 다른 프로세스의 메모리에 접근하는 것을 금지하지만 프로세스간 데이터를 공유하기 위해 boutntls bznded 원형 버퍼를 공유한다. 

이때 버퍼는 무한버퍼 (unbounded buffer)와 유한버퍼 (bounded buffer)를 사용할 수 있다

 

2. message Passing

위 공유 메모리 방식은 동일한 주소 공간을 공유하여 데이터를 공유하는 반면 message Passing은 동일한 주소 공간을 공유하지 않고도 프로세스간 통신이 가능하다 

  • Blocking send : 다른 프로세스에게 메시지 보내고 메시지를 받을때까지 block(sleep)상태로
  • Blocking receive: 메시지가 올때까지 sleep(block)상태
  • buffering : link는 임시저장할 공간을 가짐

이러한 통신은 직접적 or 간접적으로 이루어질 수 있다

  • Direct : 소통중인 플세스 이름 명시적
    • send (dest프로세스, 메시지), receive (src프로세스, 메시지)
    • 두 프로세스는 하나의 link로 연결되어있음 (양방향)
  • Indirect : mailbox를 사용
    • send(mailbox, message), receive(mailbox, message)
    • 많은 프로세스들이 mail box 공유, 두 프로세스 사이 다수의 link 존재

이때 사용하는 버퍼의 유형은 다음과 같다

  • zero capacity : 메시지 저장 불가능
    • 큐의 최대 길이 0, 링크 안에 대기하는 메시지 가질 수 없음
    • 송신자는 수신자가 메시지를 수신할 때까지 기다려야 함
    • 랑데뷰 = 데이터를 교환하기 위한 동기화
  • Bounded capacity: 제한적인 용량
    • 수신 queue가 차지 않았으면 메시지가 큐로 감
    • 수신 큐가 다 차있다면 송신자가 그만 보내!!
  • Unbounded capacity : 무한정
    • 송신자가 항상 송신해

3. RCP(Remote Procedure Call)

function call 을 할 때 같은 프로세스면 인자를 stack을 통해 공유할 수 있지만 다른 프로세스라면 remote procedure call이 이루어진다 호출하는 client는 서버에 있는 함수를 호출하지만 stub을 통해 호출하기 때문에 서버까지 가는지 모른다(프로시저 호출 추상화) 

어떤 프로세스에서 foo(1,2,3) 호출

→ 클라이언트 stub 호출

→ 클라이언트 stub 메시지 작성 & RPC에 보냄

→ 미리 RPC에 저장되어있던 foo를 RPC가 matching

→ 메시지 서버stub으로 전송 (pack param, 마샬링)

→ 서버 stub 메시지 unpack, 언마샬링 ,서버 로컬 프로시저 호출

→ 서버 서버 로컬 프로시저 반환값 포함 메시지 작성 (pack result) & 클라이언트 stub 전송

→ 클라이언트 stub 결과 unpack, 클라이언트에게 반환

  1. Client procedure이 클라이언트 stub 호출
  2. 클라이언트 stub이 param을 메시지에 패키징 & 커널에 trap
  3. 커널이 remote kernel에 메시지 전송
  4. remote kernel이 서버 stub에 전달
  5. 서버 stub이 param unpack & 서버 call
  6. 서버가 프로시저 실행하고 서버stub에 결과 반환
  7. 서버 stub이 결과를 메시지에 pack & 커널로 trap
  8. remote kernel이 local kernel에게 전송
  9. local kernel이 클라이언트 stub에게 메시지 전송
  10. client stub이 결과 unpack, 클라이언트에게 결과 반환

 

 

 

 

 

'CS > OS' 카테고리의 다른 글

[OS] Semaphore(쎄마포어)  (4) 2025.08.02
[OS] Critical Section Problem, 쓰레드간 협력  (0) 2025.07.05
[OS] NachOS 환경 설정  (3) 2025.05.21
운영체제란 무엇인가  (0) 2025.04.30