프로그램
: 컴퓨터에서 실행할 수 있는 파일
: 아직 파일을 실행하지 않은 상태 -> static program. 코드 덩어리
프로세스
: 프로그램을 실행시켜 동적으로 프로그램이 돌아각 있는 상태. 컴퓨터에서 작업 중인 프로그램. 코드 덩어리를 실행한 것.
: 실행 중인 프로그램
사용자가 작성한 프로그램이 운영체제에 의해 메모리 공간을 할당받아 실행 중인 것
-> 프로세스는 프로그램에 사용되는 데이터와 메모리 등의 자원, 그리고 스레드로 구성됨.
Process = data + memory + thread
프로세스의 메모리
PCB(Process Control Block)
운영체제에서 프로세스를 관리하기 위해 해당 프로세스의 상태 정보를 담고 있는 자료구조.
프로세스가 생성되면 메모리에 해당 프로세스의 PCB가 함께 생성, 종료 시 삭제.
context switching 할 때 PCB를 이용해서 상태를 저장하며 프로세스를 관리함!
Thread?
프로세스 내에서 실제로 작업을 수행하는 주체
=>하나의 프로세스 내에서 동시에 진행되는 작업 갈래, 흐름의 단위
모든 프로세스에는 한 개 이상의 스레드가 존재하여 작업 수행
2개 이상의 스레드를 가지는 프로세스 =>multi-threaded process
Stack
: 함수 호출 시 전달되는 인자, 되돌아갈 주소값, 함수 내에서 선언한 변수 등을 저장하는 메모리 공간TCB(Thread Control Block)
: 각 스레드마다 운영체제에서 유지하는 쓰레드에 대한 정보를 담고 있는 자료구조.
프로세스 내에 쓰레드가 있는 것처럼, PCB안에 TCB가 들어있다.
critical section(임계 영역)
멀티 쓰레드가 동시에 접근해서는 안되는 공유 자원(파일, 입출력, 공유 데이터 등)
: 대표적으로 전역 변수나 heap 메모리 영역
-> 공유 자원이나 변수가 업데이트되는 코드 부분
-> 한 시점에 한 프로세스(또는 쓰레드)만이 이 구역에 진입할 수 있어야 함. 그래야 데이터의 일관성과 안정성 보장됨.
=> 동기화(Synchronization) 기법
필요
: TCB
를 사용하여 관리. -> TCB에서 해당 쓰레드의 mutex/semaphore 정보 관리하고 쓰레드가 해당 자원에 대한 접근 권한을 획득하거나 반납할 때 TCB 정보 업데이트
우리가 Thread를 사용하는 이유
- 메모리 절약
: thread는 1MB 이내의 메모리만 점유 -> 경량 프로세스- 프로세스 context switching에 비해 오버헤드 절감됨
프로세스 Context Switching
: 스위칭할 때마다 CPU 캐시에 있는 내용 모두 초기화하고 새로운 프로세스 정보를 CPU 캐시에 적재해야 함
- 쓰레드 context switching : 하나의 프로세스 내의 쓰레드들을 교환하는 것
multi-thread는 자원을 공유함 -> code, data,files 등
스위칭할 때 쓰레드 간에 공유하는 자원을 제외한 쓰레드 정보(stack, register)만 교체하면 됨!
자식 프로세스는 부모 프로세스의 PID, PPI(Parent Process ID)를 알고 있어서 부모 프로세스와 통신이 가능함. 그러나 부모 프로세스와 자식 프로세스는 엄연히 서로 다른 독립적인 프로세스. 독립적인 메모리 공간을 갖고 있음.
: 하나의 프로세스 안의 여러개의 쓰레드
하나의 프로그램에서 두 가지 이상의 동작을 동시에 처리하게끔! 하나의 스레드는 지연되더라도 다른 스레드는 작업을 지속할 수 있게 된다.
멀티 프로세스 예시: 웹 브라우저의 상단 탭, 여러 창
멀티 스레드 예시: 웹 브라우저 단일 탭 내의 브라우저 이벤트 루프, I/O 작업 등
그러나 쓰레드를 많이 쓰면 쓸수록 항상 성능이 좋아지는가??
- multi-thread: 하나의 쓰레드에서 문제가 발생하면 다른 쓰레드들도 영향을 받아 전체 프로그램이 종료될 수 있다.
- 쓰레드가 데이터 접근하기 전에 Lock 획득, 데이터 접근한 이후에 Lock을 해제 해야 하는데
Lock 획득 및 해제 작업은 추가적인 시간이 소요되며 나머지 쓰레드의 실행을 중지 or 대기하게 만들어야 함- CPU 캐시와 메모리 사이의 캐시 데이터 일관성 문제
: 여러 CPU 코어가 동시에 같은 데이터를 다룰 때 각자의 캐시에 저장된 정보가 서로 달라지지 않게 관리해야 함
-> 멀티 쓰레드가 싱글 쓰레드보다 성능이 뛰어나지만, 멀티 쓰레드의 경우 동기화 처리, 메모리 누수, 데드락 문제가 발생 가능 -> 무조건 멀티 쓰레드가 항상 좋다고 말할 수는 없다.
: 여러 프로세스/스레드가 공유된 자원에, 마치 경쟁하듯, 동시에 접근하고 수정을 시도하는 상황
data race
: 멀티 쓰레드가 거의 동시에 임계 영역을 실행하려고 할 때 발생. 공유 자료 구조를 모두가 갱신하려고 시도할 때
=> Synchronizaiton!
한 번에 하나의 스레드만 공유 자원에 접근할 수 있도록. -> 데이터에 대한 일관성 유지
Lock
- 사용 가능 available (unlocked / free) 상태: 어떤 쓰레드도 락을 소유하고 있지 않음
- 사용 중 (acquired): 임계 영역에서 정확히 하나의 쓰레드가 락을 획득한 상태
Mutex (Mutual Exclusion, 상호 배제)
: critical section에 진입하기 전에 lock 획득하고, critical section 빠져나올 때 lock을 해제하여 다른 쓰레드들이 접근할 수 있도록 한다.
오직 1개의 쓰레드만이 공유 자원에 접근할 수 있도록 제어하는 기법
Semaphore
: 동시에 접근 가능한 쓰레드의 개수를 지정할 수 있다.
값이 1이면(binary semaphore
) Mutex와 동일한 역할,
값이 2 이상이면 동시에 접근 가능한 쓰레드의 수를 제어할 수 있다.
쓰레드가 critical section에 진입하기 전에 세마 포어 값을 확인하고 값이 허용된 범위 내에 있을 때에만 lock을 획득할 수 있다. - 각 사용자는 비어있는 화장실 칸의 개수를 알 수 있음
Mutex
: 한 번에 하나의 쓰레드만 자원 사용 가능하도록Semaphore
: 한 번에 여러 쓰레드가 자원을 사용할 수 있게 하되, 그 수를 제한함Mutex (Mutual Exclusion)
마치 한명만 열쇠를 가진 개인 사물함. 이 사물함을 열 수 있는 열쇠는 오직 1개. 열쇠를 가진 사람만이 그 자원을 사용할 수 있고 자신만이 잠글 수 있음.
Binary Semaphore
화장실의 표지판 - 2가지 상태(0: 사용 가능, 1: 사용중)
화장실이 사용가능한 상태일 때, 누구나 안에서 사용중으로 바꿀 수 있음. 화장실을 사용한 다른 사람이 나와서 사용가능 상태로 바꿀 수 있음.
다수의 프로세스/스레드가 서로 자원을 점유하고 다른 프로세스/스레드가 점유한 자원을 기다리는 상황에서 발생하는 교착 상태.
여러 개의 스레드가 서로 대기하면서 무한정 기다리게 되는 무한 루프와 같은 상황
(예시)
쓰레드 1: 자원 A 점유하지만 자원 B가 필요한 상황, 쓰레드 2: 자원 B를 점유한 상태에서 자원 B가 필요한 상황
상호 배제(Mutual exclusion)
: 쓰레드가 자신이 필요로 하는 자원에 대한 독자적인 제어권을 주장함(예: 쓰레드가 lock을 획득함)점유 및 대기(Hold-and-wait)
: 쓰레드가 자신에게 할당된 자원(예: 이미 획득한 Lock)을 점유한 채로 다른 자원(예: 획득하고자 하는 Lock)을 대기한다.비선점(No preemption)
: 자원(Lock)을 점유하고 있는 쓰레드로부터 자원을 강제적으로 빼앗을 수 없다.환형대기(Circuit wait)
: 각 쓰레드는 다음 쓰레드가 요청한 하나 또는 그 이상의 자원(lock)을 갖고 있는 쓰레드들의 순환 고리가 있다. 데드락은 일단 이정도만 정리하고 넘어가기로.
참고)
https://beststar-1.tistory.com/6
https://inpa.tistory.com/entry/%F0%9F%91%A9%E2%80%8D%F0%9F%92%BB-Is-more-threads-always-better
ㅎ
드디어 핀토스 주간이다
티타임 때 벌써 정글의 40%가 지났다는 소리를 들었을 때 약간 충격 먹었다.
시간 왜이렇게 빨리 가는거지
핀토스 화이팅
운영체제 키워드는 일단 간략하게 보고 바로 코드로 Deep dive해 볼 생각이다.ㅎㅋ
무튼 화이팅