1. 프로그램과 프로세스 원리
프로그램은 하드 디스크 등의 저장 매체에 저장된 실행 파일의 형태이다. 우리가 컴퓨터를 사용하는 동안 메모리 안에서는 새로운 프로세스들이 계속하여 생성되고, 사용되지 않은 프로세스는 메모리에서 삭제된다. 프로세스는 프로그램이 메모리에 적재되어 CPU에 의해서 실행 중인 상태로, 메모리에 load 되어 있는 상태이다. 운영체제로부터 필요한 모든 자원(코드, 데이터, 스택, 힙으로 구성된 프로세스 메모리를 갖는다.)을 할당받는다. 프로그램은 실행되기 전까지는 그저 보조기억장치에 있는 데이터 덩어리일 뿐이지만, 보조기억장치에 저장된 실행 파일 형태의 프로그램은 메모리에 적재하고 실행하는 순간 그 프로그램은 하나의 프로세스가 된다.
2. 프로세스의 4 영역 구성과 주소 공간
하나의 프로세스는 크게 4가지 영역으로 나누어 저장된다.
- 코드 영역
텍스트 영역이라고도 부른다. 기계어로 이루어진 명령어가 저장되며 데이터가 아닌 실행할 명령어가 담겨있기 때문에 쓰기가 금지된 읽기 전용 공간이다. 사용자가 작성한 모든 한수의 코드, 사용자가 호출한 라이브러리 함수들의 코드 등 실행될 프로그램 규모가 적재되는 영역이다.
- 데이터 영역
프로그램에서 고정적으로 만든 변수 공간이다.
잠깐 썼다가 없앨 데이터가 아닌 프로그램이 실행되는 동안 유지할 데이터가 저장되는 공간이다. 프로그램 전체에서 접근할 수 있는 전역 변수 공간, 정적 데이터의 공간이며 사용자 프로그램과 라이브러리를 포함한다.
- 힙 영역
프로세스의 실행 도중 동적으로 사용할 수 있도록 할당된 공간이다. malloc() 등으로 할당받는 공간을 힙 영역에서 아래 번지로 내려가며 할당한다. 힙 영역에서 메모리를 할당했다면 언젠가는 해당 공간을 반환해야 한다. 메모리 공간을 반환하지 않는다면 할당된 공간은 메모리 내에 계속 남아 메모리 낭비를 초래한다.
- 스택 영역
함수가 실행될 때 사용할 데이터를 위해 할당된 공간이다. 데이터를 일시적으로 저장하는 공간이며, 일시적으로 저장할 데이터는 스택 영역에 push 되고, 더 이상 필요하지 않은 데이터는 pop이 되어 스택 영역에서 사라진다. 함수의 실행이 끝나면 사라지는 매개변수, 지역변수가 대표적이다. 함수 호출 외에 프로세스에서 필요시 사용 가능하다.
- 프로세스의 주소 공간은 프로세스가 실행 중 cpu가 액세스 할 수 있는 허용된 주소의 최대 크기이며, 프로세스의 현재 크기와는 다르다. 프로세스 주소 공간은 논리(가상) 공간으로 0번지에서 시작하여 연속적인 주소이다.
- 프로세스 주소 공간은 사용자 공간과 커널 공간으로 구성된다. 코드와 데이터 영역의 크기는 프로시스 적재 시 결정되지만 힙은 데이터 영역의 바로 다음, 스택 영역은 사용자 공간의 바닥에서 거꾸로 할당된다.
- 커널 공간은 프로세스가 시스템 호출을 통해 이용하는 커널 공간이다. 커널 코드, 커널 데이터, 커널 스택이 존재한다. 실행 중 크기가 변하지 않는 코드나 데이터 영역은 프로그램을 구성하는 명령어가 바뀔 일이 없기 때문에 크기가 고정, 데이터 영역에 저장될 내용은 프로그램이 실행되는 동안만 유지되기 때문에 ’정적 할당 영역‘이라고 부른다. 반면 힙, 스택 영역은 프로세스 실행 과정에서 크기가 변할 수 있어 ’동적 할당 영역‘이라고 부른다.
3. 프로세스의 생성 관계를 설명하고 리눅스의 #0, #1, #2
프로세스는 일반적으로 부모-자식 관계이며 계층 관계가 아니다. #0 프로세스가 시스템 부팅 시 실행되는 최초의 프로세스로 조상 프로세스가 된다. 부모 프로세스는 fork()를 통해 자신의 복사본을 자식 프로세스로 생성하고 만들어진 복사본(자식 프로세스)은 exec를 통해 자신의 메모리 공간을 다른 프로그램으로 교체한다. 이 과정의 반복으로 여러 프로세스가 계층적으로 실행된다. 따라서 부모 프로세스는 여러 자식 프로세스를 가질 수 있으며 #0 프로세스를 제외한 모든 프로세스는 부모 프로세스를 가진다. 프로세스는 시스템 호출인 fork(), clone()등으로만 생성이 가능하지만 몇몇 조상 프로세스(PID 0, 1, 2)는 시스템 호출이 아닌 수작업으로 생성된다. 부모 프로세스, 자식 프로세스는 엄연히 다른 프로세스이기 때문에 각기 다른 PID를 가진다.
리눅스
#0 프로세스 - swapper/idle 프로세스
#1 프로세스 - init 프로세스: 부팅 후 생성되는 모든 사용자 프로세스의 조상
#2 프로세스 - kthreadd: 커널 모드에서 커널 코드로만 실행되는 모든 커널 프로세스의 조상
4. 좀비 프로세스를 설명하고 제거 방법
좀비 프로세스는 실행이 종료되었지만 부모 프로세스가 자식 프로세스의 종료 상태를 회수하지 않았을 경우 자식 프로세스는 좀비 프로세스가 된다. 프로세스 테이블에는 아직 남아있으므로 프로세스 목록을 출력할 때 ps명령으로 나타난다. 부모 프로세스는 wait() 시스템 호출을 통해 자식 프로세스의 종료 코드를 읽어야 하는 의무가 있다. 자식이 종료되면 부모에게 전송되는 SIGCHLD 신호를 받았을 때 wait() 하도록 작성되어 있지 않다면 자식 프로세스는 계속 좀비 상태로 남아있는다. 좀비 프로세스가 쌓이게 되면 리소스 유출을 야기할 수 있기 때문에 좀비 프로세스 상태가 오래 유지되지 않도록 부모 프로세스는 wait() 시스템 호출을 통해 자식 프로세스 상태를 읽어 들이는 것이 필요하다.
* SIGCHLD 신호: 자식 프로세스가 종료될 때 부모 프로세스에 통보되는 POSIX 신호
좀비 프로세스의 제거 방법은 크게 2가지가 있다.
1. kill 명령어를 날려도 좀비 프로세스는 이미 죽었기 때문에 죽지 않는다. 따라서 쉘에서 부모 프로세스에서 SIGCHLD 신호를 보내 자식 프로세스가 종료되었음을 알리는 방법
$kill-SIGCHLD 부모 프로세스의 PID
부모 프로세스의 SIGCHLD 핸들러가 wait() 호출하여 좀비 자식을 제거한가.
2. 위의 방법으로 좀비 프로세스가 죽지 않는다면 부모 프로세스의 강제 종료
$kill-9 부모 프로세스의 PID
강제 종료하면 좀비는 init 프로세스(PID=1)의 자식이 되고 init은 주기적으로 wait() 시스템 호출하여 실행하기 때문에 이미 좀비가 된 프로세스를 제거한다.
부모 프로세스를 죽인다는 것은 하위의 모든 자식 프로세스를 죽인다는 뜻이 되므로 신중히 고려해야 한다.
5. 고아 프로세스를 설명하고 운명체제의 대응 방법
부모 프로세스가 자식 프로세스보다 멐저 종료되면 자식 프로세스는 고아 프로세스가 된다. wait()을 호출하늨 대신에 그냥 종료를 해버리는 것이다. 이 경우 커널은 종료되는 프로세스가 발생할 때 누구의 부모 프로세스인지 확인한 후 커널이 자식의 부모 프로세스 ID를 1(init 프로세스)로 바꿔준다. 고아 프로세스를 init 프로세스가 입양하여 새로운 부모 프로세스가 된다. 고아 프로세스가 작업을 종료하면 init 프로세스는 주기적으로 wait() 시스템 호출을 통해 고아 프로세스의 종료 상태를 수집하고 프로세스 식별자와 프로세스 테이블 항목을 반환함으로써 좀비 프로세스가 되는 것을 방지한다. 운영체제 혹은 쉘의 경우 모든 자식 프로세스를 강제 종료 시키기도 한다.
6. 교착 상태의 개념 및 Coffman condition 4가지 (코프만 조건)
교착 상태는 자원을 소유한 스레드들 사이에서 각 스레드는 다른 스레드가 소유한 자원을 요청하여 기다리기만 한다면 서로의 작업은 처리되지 못한채 무한정 대기하는 현상
발생 위치
1) 사용자가 작성한 멀티스레드 응용프로그램에서 주로 발생(정교하지 못한 코딩)
2) 커널 내에서도 발생하지만 거의 발생하지 않는다.
코프만 조건은 교착 상태가 발생하는 4가지 필요충분조건이다.
1. 상호 배제: 각 자원을 한 번에 하나의 스레드에게만 할당한다.
2. 소유하면서 대기(점유대기): 스레드가 한 자원을 소유하면서 자원을 추가로 점유하기 위해 다른 자원을 기다리기
3. 강제 자원 반환 불가(비선점): 스레드에게 할당된 자원을 강제로 빼앗지 못함
4. 환형대기(순환대기): 한 그룹의 스레드들에 대해 각 스레드는 다른 스레드가 요청하는 자원을 소유하는 환형 고리 생성
4가지 상황이 허용되는 시스템은 언제든 교착 상태가 발생 가능하다. 4가지 조건 중 하나라도 성립되지 않으면 교착 상태는 발생하지 않는다.
7. 프로세스 생성 과정과 생성되는 경우 5가지
생성 과정
1) 새로운 PID 번호 할당
* PID는 프로세스 ID로, 특정 프로세스를 식별하기 위해 부여하는 고유 번호이다.
2) 커널 영역에 PCB 구조체 생성
* PCB는 프로세스 제어 블록으로 프로세스와 관련 정보를 저장하는 자료구조이다.
3) 프로세스 테이블에서 새 항목 할당
4) 서로 할당된 프로세스 테이블 항목에 PCB 연결
5) 새로운 프로세스를 위한 메모리 공간 할당(프로세스의 코드, 데이터, 힙, 스택 영역 할당 받은 메모리 공간에 프로세스의 코드와 데이터 적재)
6) PCB에 프로세스 정보 기록
7) PCB에 프로세스 상태를 ready로 표시하고 준비 큐에 넣어서 차후 스케줄되게 함
컴퓨터 시스템에서 프로세스가 생성되는 경우 5가지
1. 시스템 부팅 과정에서 필요한 프로세스 생성
2. 사용자의 로그인 후 사용자와 대화를 위한 프로세스 생성
3. 새로운 프로세스를 생성하도록 하는 사용자의 명령
4. 배치 작업 실행 시(at, batch 명령)
5. 사용자 응용 프로그램이 시스템 호출로 새 프로세스 생성
* 프로세스 생성은 시스템 호출로만 가능 리눅스에서는 fork() 함수 사용
'IT' 카테고리의 다른 글
2-1 정보통신개론 (3) | 2024.11.08 |
---|---|
4차 산업혁명과 창의컴퓨팅 (2) | 2024.11.05 |
머신러닝 4th (0) | 2024.10.23 |
머신러닝 3rd (0) | 2024.10.20 |
머신러닝 2nd (0) | 2024.10.20 |