운영체제

운영체제 3. 프로세스, 스레드

MiaCoder 2024. 4. 16. 23:43

프로세스

실행중인 프로그램

 

프로세스 메모리구조 4가지

 

사용자 관점

스택

데이터를 일시적으로 저장하는 공간

지역변수를 사용함

힙과 인접한 방향으로 점점 커짐

후입선출

코드영역과 별도로 유지되는 일시적인 공간

동적메모리할당을 위해 사용하는 공간

위쪽으로 점점 커짐

데이터

프로그램의 가상주소 공간

전역변수 정적변수를 저장하거나 할당

코드

실행 명령을 포함하는 메모리 

컴파일한 프로그램을 저장함

 

시스템 관점의 프로세스

교착상태, 보호, 스케줄러 등을 함

 

프로세스 상태변화 운영체제가 스케줄러를 이용하여 관리함

작업 스케줄러 

디스크 내 작업 중 실행할 작업을 선전, 준비리스트에 삽입

프로세스 스케줄러

선정한 작업의 상태를 변화시킴

프로세스 생성에서 종료까지 수행

 

프로세스이 상태변화 상태 정보

프로세스 생성

작업을 커널에 등록함

프로세스 생성

ready - 메모리를 할당 받음

suspended ready 아직 메모리를 할당받지는 못함

 

준비(ready) 프로세스 이외의 모든 자원을 할당받은 상태 프로세서만 할당받으면 즉시 실행가능

디스패치 ready -> running로 가능 과정

 

실행(running) 모든자원, 프로세서 몯 할당 받은 상태 

일정 시간동안만 점유 가능(선점)

timeout만 발생한 경우 -> ready로 감

새로운 입출력 등이 필요한 경우 스스로 프로세서 양도 -> 대기(asleep)로 이동

 

대기(asleep)

프로세서외 새로운 자원이 필요한 경우

자원 할당은 system call에 의해 결정된다

 

swap-out -> 당분간 사용되지 않아 메모리를 빼앗긴 상태

swap-in    -> 다시 메모리를 할당받은 상태

 

종료(terminated)

프로세스 수행이 끝난 상태

모든 자원 반납

 

프로세스 제어 블록PCB

프로세스가 생성되면 메모리에 PCB형성, 종료되면 삭제

 

프로세스 문맥교환

실행중인 프로세스의 제어를 다른 프로세스에게 넘겨 실행상태가 되도록 하는 것

문백교환이 일어나면 프로세서의 레지스터에 있던 내용을 저장함

 

프로세의 구조

프로세스 실행중 생성시스템을 통해 새로운 프로세스 사용

부모-자식관게를 유지하며 계층적으로 생성

생성하는 프로세스 - 부모 프로세스

생성되는 프로세스 - 자식 프로세스

 

프로세스 생성

일괄처리 - 작업이 도착할 때

대화형 - 새로운 사용자가 로그인할 때

 

부모 프로세스가 자식 프로세스와 동시 실행

부모 프로세스는 자식 프로세스가 모두 종료할 때까지 대기

 

fork()함수

리눅스에서 프로세스를 생성해 프로그램을 실행하는 함수

자식프로세스 fork()가 생성한 부모프로세스와 동일한 프로세스

부모프로세스와 자식프로세스의 시작은 스케줄링에 따라 달라짐

fork()호출 -> 자식프로세스 생성 -> 자식프로세스 메모리 공간을 부모프로세스 메모리공간을 그대로 복제

따라서 부모프로세스, 자식프로세스는 통신 필요 -> 부모는 자식의 PID를 리턴, 자식은PID 0을 리턴

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
    int x = 1;
    pid_t pid = fork(); \\ fork():자식 프로세스 생성 함수
    
    if (pid == 0) {
    
   		//자식이면
    printf("Child has x = %d\n", ++x);
    } else {
    
    	//부모면
    printf("Parent has x = %d\n", --x);
    }
    
    printf("Bye for process %d with x = %d\n", getpid(), x);
}
// 어떤 프로세스가 먼저 실행될지는 알 수 없다
//프로세스가 완벽히 종료 후 자식프로세스가 사용되는 것에 주목
int main(){

	print("L0\n");
    fork();
    // 자식프로세스가 생성됨
    print("L1\n");
    //현재 프로세서가 2개이므로 2번 출력
    fork();
    자식프로세스의 자식프로세스가 생성됨 총 프로세스 4개
    print("L2\n");
    4번 출력
    
}

 

프로세스의 종료

부모 프로세스의 자식 프로세스 종료

부모를 종료하면 자식도 종료

자식이 할당된 자원을 초과해 사용할 때

자식에 할당한 작업이 없을 때

exit() 프로세스 종료

void exit(int status);

프로세스를 종료시키고 부모프로세스에게 전달

atexit()함수로 예약한 함수를 지정된 순서와 역순으로 모두 실행

문제가 생겨 리턴하지 못하면 나머지 과저도 수행 못함

입출력에 남은 데이터를 모두 기록하고 스트림을 모두 닫음

atexit()

종료 시 수행할 작업 function을 예약한다.

int atexit(void *funtcion);
int in_exit(void(* function, void arg))

 

wait() 부모 프로세스가 자식 프로세스 종료를 기다림

pid_wait(int* wstatus);

부모가 자식보다 먼저 종료되면 wait함수가 즉시 리턴함

watatus에 자식 종료상태 저장

리턴 값은 자식의 pid

-1이면 모든 자식이 종료되었다는 뜻

 

좀비프로세스

정상적인 종료과정 - 자식이 종료 상태를 부모에게 전달 -> 부모는 자식 프로세스 삭제

좀비의 발생

부모가 자식의 종료상태를 받지 않거나 자식보다 먼저 종료되는 경우

실제로 일은 못하나 테이블에만 올라와있는 상황

제거방법

부모가 wait()을 해야 사라짐

고아프로세스

자식보다 부모가 먼저 종료된 경우

 

프로세스 제거

사용하던 자원을 시스템에 반납

PCB(프로세스 실행관련 정보 저장테이블)회수

프로그램은 디스크에 저장

 

프로세스 중단

시스템 유휴를 프로세스 중단을 동해 해결

운영체제는 새로운 프로세스를 생성하여 실행중인 프로세스를 중단 후 재실행하여 사용가능

여기서 입력과 같은 이벤트를 기다리면 대기로 전환

단일 시스템 -> 해당 프로세스가 스스로중단

다중 처리 시스템 -> 다른 프로세스가 실행중인 프로세스 중단

다른 프로세서가 재시작하기 전에는 실행 불가

장시간 중단 시 할당 자원 반환결정

메인 메모리 -> 중단 즉시반환

보조 메모리 -> 종료시간이 길 때 반환

 

프로세스 우선순위

PCB의 우선순위를 이용하여 준비리스트 프로세스를 처리

프로세서 중심 프로세스

 

입출력 중심 프로세스

속도가 느리면서 빠른 응답을 요구하는 프로세스에 높은 우선순위 부여

속도가 빠른 디스크 입출력 프로세스에는 낮은 우선순위 부여

우선순위가 낮은 프로세스는 프로세서를 더 많은 시간, 우선순위가 높은 프로세스에는 적은시간 할당

입출력중심의 경우 프로세서를 짧게 여러번, 프로세서 중심의 경우 프로세스를 길게 더 적게 시용함

 

프로세스 문맥교환

실행중인 프로세스에 인터럽트가 발생하면 다른 프로세스를 싱행으로 바꾸고 제어를 넘겨줌

인터럽트의 발생 : 외부의 이벤트 발생 시

입출력 인터럽트

입출력 동작 확인 -> 이벤트를 기다리는 프로세스를 준비로 바꿈  -> 실행할 프로세스 결정

클록 인터럽트

실행중인 프로세스 할당시간 조사 -> 준비로 바꿈 -> 다른 프로세스를 실행으로 바꿈

 

인터럽트가 문맥교환으로 무조건 발전하지는 않음

프로세스가 준비-> 실행,  실행 -> 준비, 실행->대기로 바뀔때 발생

 

문맥교환

이전 프로세스의 레지스터 내용을 보관하고 다른 프로세스의 레지스터를 적재하여 프로세스를 교환하는 과정

오버헤드 발생 - 독립된 메모리 주소를 할당하기 때문

 

다중 프로세스 예시 크롬

브라우저 프로세스, 랜더러 프로세스, 플러그인 프로세스 3가지 실행

 

스레드

프로세스의 특성인 자원과 제어에서 제어만 분리한 실행단위

스레드는 자원은 공유한다

프로세스 하나는 스레드 한개 이상으로 나눌 수 있다

프로세스의 관리정보를 공유한다

메모리를 공유하므로 손상된 데이터는 스레드의 이상 동작을 일으킬 수 있다. 독립자원인 프로세스와 다름

같은 프로세스는 동일한 주소공간을 공유한다

커널은 다중 스레드를 공유한다

스택, 지역데이터는 각 스레드가 가지고 있고, 코드, 전역데이터, 힙은 공유한다

 

스레드는 공동 목적을 위해 병렬수행을 함

프로세스가 하나인 서로다른 프로세서에서 프로그램의 다른 부분을 동시에 실행

응답성증가, 자원 메모리 공유, 경제성, 오버헤드감소, 다중처리효율 향상

 

단일스레드 1프로세스당 1스레드

다중스레드 1프로세스당 n개의 스레드

예를들어 1스레드는 키보드 입력 수행 1스레드는 화면 출력 1스레드는 정보 저장 

 

Pthreads

스레드 생성과 동기화를 위한 표준 API

• int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void
*(*start_routine)(void*), void *arg)
//스레드 생성 함수
//thread 스레드 id저장, attr 특성 nllwlwjd, start_routine 수행할 로직, arg 로직에 전달할 인자

• int pthread_join(pthread_t thread, void **retval)
//스레드가 종료될 때 까지 대기
// retval start_routine가 반환하는 반환값을 저장

스레드는 순차적으로 생성하나 실행순서가 생성 순서와 일치하지 않는다.

 

스레드 상태변환

프로세서오 함께 사용 한상 1개만 실행

한프로세스에 있는 스레드는 순차 실행

프로세스 생성 시 해당 프로세스 스레드도 생성

자원을 부모 프로세스와 공유하므로 초기화 불필요

생성 종료 오버헤드가 훨신 적음

서로 독립적이니 않아 하나의 스레드가 대기상태가 되면 다른 스레드 실행 가능

1개 프로세스에 이쓴ㄴ 모든 스레드는 프로세스 모든 주소에 접근 가능

프로세스는 서로 경쟁적으로 자원을 요구하고 다른 관계를 유지

스레드는 프로세스 하나가 여러스레드를 소유

 

스레드 제어블록 TCB

정보를 저장함

PCB는 TCB리스트를 가리킴

스레드 실행상태, 스케줄링 정보,계정정보, 포틴터 등 포함

 

사용자 수준의 스레드

n:1매핑 thread 라이브러리를 사용해 작동

커널수준 thread 

1:1매핑 운영체제 커널에서 지원

혼합현 thread

n:m 매핑 위 둘을 혼합

 

thread 라이브러리로 스레드의 생성과 종료, 스레드간 메시지 전달, 정보보관, 등을 사용

모든 행위흫 사용자 영역에서 함

커널이 개입하지 않음

사용자 영역으로 전환이 불필요함

 

장점

이식성이 높음, 모든 운영체제 적용가능

오버헤드 감소 스케줄링 동기화등을 위해 커널을 호출하지 않음

응용프로그램에 맞는 유연한 스케줄링 가능

단점

시스템 동시지원을 안함

스레드가 아닌 프로세스 단위로 프로세서를 할당하여 다중처리 환경이어도 스레드단위 다중처리는 불가능

확장제약

프로세스 내 여러 스레드에 프로세서 동시할당이 불가능

스레드간 보호 불가능

커널의 보호방법 사용 불가

 

커널 수준의 스레드

커널이 스레드 관련 모든 작업 관리

스레드 1개가 대기상태가 되면 동일한 프로세스의 다른 스레드로 교환 가능

커널이 직접 스케줄링하고 사용하여 커널 지원부족문제 해결

커널이 전체 프로세스롸 스레드 정보를 유지하여 오버헤드가 커짐