본문 바로가기
공부, 취준/운영체제

[운영체제] pintOS 프로젝트 - Synchronization

by 린레몬 2021. 3. 8.

안녕하세요 레몬입니다.

핀토스 프로젝트 첫 번째 포스팅을 할 때에는 이런저런 배경지식을 설명하느라 글 쓰는게 꽤 오래 걸렸는데, 두 번째 이후로는 구현 관련한 내용만 적다보니 금방 끝나서 오늘 끝까지 써보려 한다!

핀토스 프로젝트 포스팅이 끝나면 요새 Capstone Design 때문에 Google Colab 상에서 이런저런 딥러닝 모델을 돌려보고 있는데, 진~~~~~~~~짜 초보자를 위한 튜토리얼은 그닥 경험하지 못해본 것 같아서 내가 몇가지 실습을 진행하며 얻은 얕은 지식들을 소개하는 글 위주로 작성할 것 같다.


<Synchronization>

1. 과제 개요

한 번에 여러 스레드가 lock, semaphore, condition variable을 얻기 위해 기다리고 있을 경우, 이들 중 가장 높은 우선순위를 가진 thread가 CPU를 점유하도록 한다.

아.. lock과 semaphore 얘기가 나왔다... 진짜진짜 간단히만 훑어보고 시작하자

여러 Thread들이 번갈아가며, 혹은 여러 프로세서에 의해 동시에 수행될 때, 공유되는 자원이 존재할 것이다.

만약 공유자원에 대해 Synchronization이 보장되지 않으면 여러 곤란한 상황이 발생할 것이다.

은행 계좌 거래의 예를 들어보자.

1111 계좌 잔고 = 10,000 원
Thread A : 1111 계좌에서 5,000원 출금!
Thread B : 1111 계좌에 1,000원 입금!

이와 같은 상황에서, 만약 우연히 A와 B의 작업이 동시에 일어나면 어떻게 될까?

A : 현재 잔고 10,000원 - 5,000원 -> 잔고 5,000원 return
B : 현재 잔고 10,000원 + 1,000원 -> 잔고 11,000원 return

만약 A와 B가 동시에 시작되고 B가 조금 늦게 끝났다면, 분명 5,000원을 출금했는데 잔고는 오히려 11,000원으로 늘어있는 상황이 발생할 수 있을 것이다.

이런 상황을 막기 위해, 위의 예시에서 공유되는 자원인 계좌 잔고와 같은 값들을 Synchronization 해야할 필요가 있다.

다시말해, 하나의 Thread가 공유자원(=Lock, Semaphore, condition variable 등등)에 접근하여 연산중이면, 다른 Thread들은 현재 수행중인 Thread가 끝나기 전까지 기다려야 한다!!

이 기능을 구현해주면 되는 실습이다.

(Lock과 Semaphore의 차이와 같은 중요한 내용을 생략하고 대충 설명한 내용이니 확실히 알고있는 정보가 아니면 다른 글이나 수업을 통해 제대로 학습하자!!)

 

2. 아이디어

기존 Pintos는 semaphore를 대기중인 thread들의 리스트 waiters가 FIFO 형식으로 구현되어, 우선순위를 고려하지 않고 waiters에 삽입되는 순서대로 lock을 획득한다. 이를 우선순위 정렬하여 lock을 thread의 우선순위에 따라 얻을 수 있도록 수정한다.

결국 우선순위에 관한 문제이기 때문에, 이전에 구현한 Priority Scheduling과 비슷하게 해결할 수 있다.

 

3. 설계 (코드!)

- pintOS의 Semaphore

기존 Pintos에서 사용되는 Semaphore 구조를 확인했다. 안내자료와 동일하게 코드가 적혀있는 것을 확인하였다. value가 현재 남은 자리를 나타내는 것으로, threadsemaphore를 획득할 때 value1 줄어들고, 반환할 때 value1 늘어난다.

- pintOS의 Lock

Lock의 구조도 확인하였다. threadlock을 요청하거나 반환할 수 있다.

- pintOS의 Condition Variable

Condition Variable의 구조도 확인하였다. condition variable을 통해 thread들을 기다리게 하거나, waiters에서 기다리고 있는 thread들에게 signal을 보낼 수 있다.

- sema_down() 함수 수정

앞서 threadready_list 삽입 방식을 priority 정렬하는 것으로 수정한 것과 동일하게 코드를 수정했다. 기존 단순히 리스트의 맨 뒤에 삽입되도록 하는 코드 대신 list_insert_ordered 코드를 사용했다.

- sema_up() 함수 수정

waiter 리스트를 우선순위 정렬하는 코드를 추가하였다. sema_up (점유하고 있던 semaphore 반환)을 수행한 뒤 value값을 1 증가시킨 이후, 이전에 작성한 test_max_priority 함수를 호출해 현재 CPU 점유중인 threadready_list에 있는 thread의 우선순위를 비교한다.

- 구현할 함수 선언

헤더 파일에 구현할 함수 cmp_sem_priority를 선언하였다.

- cmp_sem_priority() 함수 추가

threadpriority를 비교해 a의 우선순위가 높으면 1, b의 우선순위가 높으면 0을 리턴한다. 여기서 사용한 semaphore_elem 구조체가 cmp_sem_priority보다 뒤에 선언되어 있어 선언 위치를 앞으로 옮겼다.

- cond_wait() 함수 수정

기존 리스트 삽입 방식에서 방금 작성한cmp_sem_priority를 사용해 우선순위에 따라 정렬되어 waiters에 삽입되도록 수정하였다.

- cond_signal() 함수 수정

semaphore를 대기하던 중 각 thread의 우선순위 값이 변경되었을 가능성이 있기 때문에, cond_signal 내에 waiters 리스트를 재정렬하는 코드를 추가하였다.

4. 결과

make check 명령어를 입력해 test를 진행중인 모습이다.

두가지 test에서 pass하는 것을 확인하였다.


오늘 마지막 Priority Inversion Problem까지 싹 끝내고 싶었는데 안될듯..!!

다음에 포스팅할 때 마무리하고, Google Colab쪽 내용들 본격적으로 정리해봐야겠다.

Capstone Design 진행 과정 글도 얼른 써야하는데... 악보 가독성 개선!! 이라고 글 쓰기 시작해놓고 또 결국 주제가 바뀔 위기에 처해서 어떻게 풀어나갈지 모르겠다..ㅠㅠ

댓글