-
<<동시다발적으로 실행되는 프로세스와 스레드는 실행 순서와 자원의 일관성을 보장해야 함>>
운영체제가 제공하는 동기화의 의미
- 실행 순서 제어 : 프로세스를 올바른 순서로 실행
- 상호 배제 : 동시에 접근해서는 안 되는 자원에 하나만 접근
공유 자원 : 공도의 자원 (파일, 전역 변수, 입출력장치 등)
임계 구역 : 동시에 접근하면 문제가 발생할 수 있는 공유 자원에 접근하는 코드블록
레이스 컨디션 (race condition) : 임계 구역을 동시에 실행하여 자원의 일관성이 깨지는 현상
생산자와 소비자 문제 : 동기화가 이루어지지 않았을 때 발생할 수 있는 문제를 보여주는 고전적인 문제
- producer : 생산을 하는 프로세스(스레드)
- consumer : 소비를 하는 프로세스(스레드)
=> 동기화되지 않은 상태에서 실행되기 때문에 똑같은 코드라도 결과 값이 예상했던 것과는 다르게 나오고 그 값이 계속 달라질 수 있음
동기화 해결 세 가지 원칙
- 상호 배제 : 한 프로세스가 임계 구역에 진입했다면 다른 프로세스는 대기해야 함
- 진행 : 어떤 프로세스도 임계 구역에 진입하지 않았다면 진입이 가능해야 함
- 유한 대기 : 한 프로세스가 임계 구역 진입을 위해 대기하고 있다면 언젠간 진입이 가능해야 함
뮤텍스 락(Mutex Lock) : 상호 배제를 위한 동기화 도구. 자물쇠 역할을 하기 때문에 Lock 이라고도 부름
- 자물쇠 역할 : 전역변수 lock
- 자물쇠 잠그기 : acquire 함수 - 임계 구역 진입 전에 호출, 잠겨있는지 지속적으로 확인하고 lock이 풀리는 순간 다시 잠그면서 임계 구역 진입 => 지속적으로 확인하는 것을 바쁜 대기(busy waiting)이라고 함
- 자물쇠 열기 : release 함수 - 작업 종료 후 임계 구역에서 빠져나올 때 호출
세마포어(Semaphore) : 상호 배제, 실행 순서 제어를 위한 동기화 도구. 공유 자원이 하나일 경우에만 사용 가능한 뮤텍스 락과는 다르게 공유 자원이 여러 개 있을 경우에도 사용 가능
- 변수 S : 임계 구역에 진입할 수 있는 프로세스의 개수 = 사용 가능한 공유 자원의 개수
- wait 함수 : 임계 구역 진입 가능 여부 알려주는 함수. S 값이 1 이상이면 임계 구역 진입 후 S 값을 1 감소시키고, S 값이 0이면 큐에 삽입 및 대기 상태 진입
- signal 함수 : 임계 구역 앞에서 기다리는 프로세스에게 진입 신호 주는 함수 = 변수 S 값을 1 증가시키는 함수로 임계 구역 작업이 종료되면 큐에서 대기 중인 프로세스를 준비 큐로 이동
+ 프로세스 상태 전이 활용함 => 먼저 실행할 프로세스 뒤에 signal, 나중에 실행할 프로세스 앞에 wait 넣으면 실행 순서 지정 가능
모니터 : 공유 자원에 접근하기 위한 인터페이스 => 인터페이스를 통해서만 접근 = 상호배제
실행 순서 제어를 위한 동기화를 위해 조건 변수(wait(), signal() 연산이 가능한 특별한 변수) 사용
조건 변수를 활용한 실행 순서 제어
- 아직 실행 조건이 되지 않았을 때 - wait을 통해 실행 중단
- 실행 조건이 충족되었을 때 - signal을 통해 실행 재개
모니터를 활용하는 대표적인 프로그래밍 언어 : Java (synchronized 키워드)
// 뮤텍스 락 (C 언어 기준) pthread_mutex_t [객체이름]; // 뮤텍스 객체 생성 pthread_mutex_init(&mutex, NULL); // 뮤텍스 객체 초기화 pthread_mutex_destroy(&mutex); // 뮤텍스 객체 사용 완료 후 제거 pthread_mutex_lock(&mutex); // 뮤텍스 객체 잠금 pthread_mutex_unlock(&mutex); // 뮤텍스 객체 잠금 해제
// 세마포어(C 언어 기준) // 세마포어 헤더 포함 #include <semaphore.h> sem_t semaphore; // 세마포어 객체 생성 // 세마포어 객체 초기화 if(sem_init(&semaphore, 0, [자원개수]) != 0) { perror("세마포어 초기화 에러"); exit(EXIT_FAILURE); } sem_destroy(&semaphore);// 세마포어 객체 사용 완료 후 제거 sem_wait(&semaphore); // 세마포어 객체 wait sem_post(&semaphore); // 세마포어 객체 종료
교착 상태(Deadlock) : 일어나지 않을 사건(필요한 자원의 할당)을 기다리며 무한히 대기하는 현상
발생 조건 => 단, 4가지를 모두 충족하면 무조건 발생하는 것이 아니라 "발생할 가능성이 있다"
- 상호 배제 : 동시에 자원 사용이 불가능한 경우
- 점유와 대기 : 자원을 할당받은 채 다른 자원의 할당을 기다리는 경우
- 비선점 : 강제로 자원을 빼앗을 수 없는 경우
- 원형 대기 : 자원을 원형으로 대기할 경우
해결 방법
- 교착 상태 예방 : 교착 상태 발생 조건 네 가지 중 하나를 업애서 발생 배경 원천 차단 => 교착 상태가 발생하지 않음을 보장할 수 있지만, 여러 부작용 발생
- 상호 배제 조건 없애기 : 자원을 공유 가능하도록 변경 - 모든 자원에 대해 적용할 수 없음
- 점유와 대기 조건 없애기 : 특정 프로세스에 자원 모두 할당 or 아예 할당 X - 자우너 활용률 저하
- 비선점 조건 없애기 : 전섬하여 사용 가능한 자원(CPU)에 대해서는 효과적 - 모든 자원에 적용 불가능
- 원형 대기 조건 없애기 : 자원에 번호 매기고, 오름차순으로 자원 할당
- 교착 상태 회피 : 교착 상태 발생 이유를 자원의 무분별한 할당으로 간주해서 교착 상태 발생하지 않을 정도로만 조금씩 자원 할당
- 은행원 알고리즘(Banker's algorithm)
- 교착 상태 검출 후 회복 : 교착 상태가 발생하면 그때 회복하는 방식
- 선점을 통한 회복
- 프로세스 강제 종료를 통한 회복
스와핑(Swapping) : 프로세스를 보조기억장치의 일부 영역으로 쫓아내고 당장 필요한 프로세스를 적재하는 기법
- 스왑 아웃(Swap-out) : 프로세스를 보조기억장치의 일부 영역으로 쫓아내는 것
- 스왑 인(Swap-in) : 스왑 아웃된 프로세스를 메모리에 적재하는 것
- 스왑 영역 : 스왑 아웃된 프로세스가 적재되는 보조기억장치 영역
연속 메모리 할당 : 프로세스를 메모리에 연속적으로 배치하는 영역
외부 단편화 : 프로세스들이 실행되고 종료되길 반복하며 빈 공간이 생기는 메모리 낭비 현상
페이징 : 물리 메모리를 프레임(frame)이라는 일정한 크기로 나누고, 프로세스를 페이지(page)라는 일정한 크기로 나눈 뒤 페이지를 프레임에 매핑하는 메모리 관리 방식
가상 메모리(Virtual memory) : 프로세스의 일부만을 적재하여 실제 물리 메모리보다 큰 프로세스를 실행하는 기술
페이지 테이블(Page table) : 프레임과 페이지의 매핑 정보를 담고 있는 표 형태의 데이터
페이지 테이블 베이스 레지스터(PTBR) : 각 프로세스의 페이지 테이블 위치를 가리키는 레지스터
TLB(Transaction Lock-aside Buffer) : 페이지 테이블의 캐시 메모리 - 접근하고자 하는 페이지가 TLB에 있으면 TLB hit, 없으면 TLB miss
유효 비트(Valid bit) : 접근하고자 하는 페이지가 보조기억장치에 있는지 메모리에 있는지 나타냄
페이지 폴트(Page fault) : 접근하려는 페이지가 보조기억장치에 있을 경우
- 작업 내역 백업
- 페이지 폴트 루틴 실행 - 접근하려는 페이지 적재
- 유효 비트 1로 변경
- 접근하려는 페이지 접근
보호 비트(Protection bit) : 접근하려는 페이지의 읽기 쓰기 실행 권한 나타냄
참조 비트(Reference bit) : 접근한 적 있는 페이지인지 나타냄
수정 비트(Modift bit, Dirty bit) : 쓰기 작업을 한 적 있는 페이지인지 나타냄 - 수정사항을 보조기억장치에 반영해야 하는지 판단하는 기준
계층적 페이징 : 페이지 테이블을 페이징 하는 것으로 페이지 테이블 크기를 줄이기 위해서 사용
=> 페이지 테이블 대신 Outer 페이지 테이블만 메모리에 적재되어 있으면 됨
요구 페이징 : 처음부터 모든 페이지를 적재하지 않고 페이지 폴트가 발생하면 그때 페이지 적재
- 순수 요구 페이징 : 아무 페이지도 적재하지 않고 실행 - 첫 명령어 실행부터 페이지 폴트 발생 - 적당한 페이지가 적재된 이후부터 페이지 폴트 감소
페이지 폴트 줄이는 법 => 물리 메모리가 크면 근본적으로 해결 가능
스래싱(Thrashing) : 프로세스 실행 시간보다 페이징에 더 많은 시간이 소요되는 문제
= 지나친 페이지 폴트로 인해 페이지 교체에 너무 많은 시간을 소요하여 성능이 저하되는 문제
=> 동시 실행되는 프로세스 수를 늘린다고 해서 반드시 CPU 이용률이 높아지지 않음
물리 메모리 크기를 키우지 않고 페이지 폴트 줄이는 법
=> 보조기억장치로 내보낼 페이지와 메모리에 적재할 페이지를 잘 선별하면 됨 = 페이지 교체 알고리즘
FIFO 페이지 교체 알고리즘 : 가장 먼저 메모리에 적재된 페이지부터 페이지-아웃
=> 초기에 적재된 페이지 중 프로그램 실행 내내 유지할 데이터가 있을 수 있음
- 2차 기회 FIFO 페이지 교체 알고리즘 : FIFO 페이지 교체 알고리즘 변형. 기본적으로 FIFO와 유사하지만 참조비트가 1일 경우 0으로 변경 후 한번 더 기회 부여 => 참조비트가 0이면 페이지-아웃
최적 페이지 교체 알고리즘 : 앞으로 사용 빈도가 가장 낮은 페이지부터 교체
- 가장 낮은 페이지 폴트 빈도율 보장하는 알고리즘 => 비현실적
- 앞으로 CPU가 어떤 페이지를 얼마나 참조할지 예측하기 매우 어려움
=> "이론적으로" 페이지 교체 알고리즘 성능 평가 시에 주로 사용
LRU 페이지 교체 알고리즘 : 가장 적게 참조한 페이지를 페이지-아웃
- 가장 적게 참조될 페이지 예측은 어려워도 가장 적게 참조된 페이지 확인하는 건 쉬움
쓰기 시 복사(copy-on-write) : 복제 프로세스를 생성할 경우 이를 중복 저장하지 않고 동시에 프로세스 간의 자원을 공유하지 않게 하는 방법 - 부모 프로세스, 자식 프로세스 둘 중 하나라도 쓰기 작업을 한다면 복사하는 것
파일 시스템 : 파일과 디렉터리(폴더)를 관리하는 커널의 한 부분. 여러 파일 시스템 동시 사용 가능
파일(file) : 보조기억장치의 의미 있는 정보의 집합
구성 요소
- 이름
- 실행하기 위한 정보
- 부가 정보 = 메타데이터/속성
- 유형(확장자)
- 크기
- 생성 날짜
- 마지막 접근 날짜
- 마지막 수정 날짜
- 생성자
- 소유자
- 위치
파일 접근 단위 : 블록(block) - 섹터 단위로 접근 X
디렉터리 : 많은 운영체제는 디렉터리를 파일과 동일하게 간주함
- 절대 경로 : 최상위 폴더에서부터 목표 위치까지의 경로
- 상대 경로 : 현재 위치 기준 목표 위치까지의 경로
구성 정보
- 파일 이름
- 위치를 유초할 수 있는 정보
- 파일 정보
파티셔닝(Partitioning) : 보조기억장치의 영역을 구획하는 작업 = 보조기억장치의 저장공간이 크기 때문에 파일 종류에 따라 분류할 수 있도록 나누는 것
포매팅(format + ing) : 파일 시스템을 만드는 작업
마운트(mount) : 파일 시스템에 접근할 경로 설정, 파일 시스템을 다른 파일 시스템에 편입할 수 있음
현재 디스크 상태 확인 $ sudo fdisk -l 파티션 조작 $ sido fdisk [파티션 경로]
FAT 기반 파일 시스템 : FAT(File Allocation Table)를 활용하는 파일 시스템
=> 저용량 보조기억장치용 파일 시스템으로 이용 (ex. USB 메모리, SD 카드)
아이노드(i-node) 기반 파일 시스템 : 아이노드라는 색인 블록을 활용한 파일 시스템
아이노드 : 파일 이름을 제외한 파일의 모든 것을 담고 있음
NTFS : 윈도우 운영체제에서 주로 사용되는 파일 시스템
APFS : macOS, iOS, watchOS, tvOS에서 주로 사용되는 파일 시스템
ext2, ext3, ext4, xfs : 리눅스 운영체제에서 주로 사용되는 파일 시스템
'프로그래밍 > CS' 카테고리의 다른 글
운영체제 (1) (0) 2024.08.06 컴퓨터 구조 (2) (0) 2024.08.05 컴퓨터 구조 (1) (0) 2024.07.25