Jungle

[TIL] pintos 운영체제 환경 세팅 + Synchronization(동기화)

손가든 2023. 11. 23. 22:24

오늘부터는 pintOS라는 교육용 운영체제를 만들고 테스트하며 운영체제에 대해서 배우는 첫 날이다.

 

먼저 작업 환경을 세팅해주고 시작하자.


Kaist pintos 프로그램 master 브랜치

 

일단 카이스트 핀토스 레포지토리의 master가 우리가 구현해야 하는 브랜치인 것으로 확인했다.

 

일단 해당 파일들을 분석하기 전에 개발 환경부터 세팅해주었다.

 

 

 

일단 우분투 18.04 버전의 EC2 환경에 카이스트 pintos 레포지토리를 복제했다.

 

이후 현재 파일에서 운영체제를 테스트하기 위해 가상환경을 세팅해준다.

 

$ source ./activate

 

근데 가상환경의 세팅은 일시적인 것이므로 재부팅 시에 다시 세팅해주어야 하는 번거로움이 있다.

 

따라서 다음과 같이 root에서 가상환경을 자동 세팅해주도록 하는 코드를 추가했다.

 

cd ~ # home 디렉토리로 이동
code .bashrc 

# 아래 내용 추가 

# command for logging in
source ~/pintos-kaist/activate

 

이 내용은 카이스트 pintos 설명서에 들어있는 내용이다.

 

참고 출처 : https://yjohdev.notion.site/Introduction-8f2bad2835c641488a6ab09613911eb1#e1e94fad1d31468bb17fbed5901a0683

 

Introduction (완료)

Introduction 소개

yjohdev.notion.site

 

코드를 추가하라고 해서 이런식으로 추가했다.

 

++

이 환경변수를 통해 자동으로 가상환경을 생성하는 방식은

VSC를 완전히 끔으로써 ssh 연결이 끊겼을 때만 다시 접속하더라도 자동으로 가상환경을 생성해준다.

 

따라서 터미널을 무한 루프나, 의문의 상황에 의해 닫게 되고 다시 켜는 경우는 서버 자체로는 재 접속이 아니므로

 

새 터미널에서는 activate를 통해 가상환경을 재설정 해주어야 한다.

 

 

 

이후 threads 로 들어가서 테스트를 진행했다.

 

테스트는 약 5~10분 정도 걸리는 것 같다.

 

$ cd threads

$ make check

 

 

 

결과를 보고 일단 환경 세팅은 정상적으로 마무리 한 것을 확인할 수 있었다.

 

 


Synchronization (동기화)

 

동기화란 ?

 

동기화란 프로세스 또는 스레드들이 수행되는 시점에 서로가 알고 있는 정보가 모두 동일하게끔 통일 시키는 것을 말한다.

 

예를 들어 process1 과 process2 가 모두 동시에 전역변수 i 를 증감연산자 ++를 통해 i++를 각 100번씩 수행한다고 하자.

 

void process1(int *i){
	for(int j=0;j<100;j++){
    		(*i)++;
    	}
}


void process2(int *i){
	for(int j=0;j<100;j++){
    		(*i)++;
    	}
}

 

이 프로세스는 단순히 프로시저의 개념이 아니고, 하나의 프로세스를 C언어로 추상화했다고 생각해보자.

 

만약 한 운영체제 내부의 두가지 프로세스가 동일한 위치의 메모리에 쓰여있는 i를 동시에 수정한다면, 작업을 동시에 수행함으로써 하나의 프로세스의 역할이 무시될 수 있다.

 

즉 우연히 동시에 버튼을 누름으로써 각각 +1을 하는 동작으로 수행되어 +2가 되어야 했지만, +1만 수행된 것이다.

 

따라서 우리는 동기화를 꼭 지켜줘야만 모든 동시에 발생하는 독립적인 프로세스와 스레드들이 올바른 연산을 수행할 수 있는 것이다.

 

 

Race condition (경쟁상태)

 

이는 서로 다른 프로세스 혹은 스레드가 컴퓨터 메모리의 동일한 자원을 런타임 시간 선상에서 동일하게 접근하려는 현상을 말한다.

 

즉, 이 경쟁상태 때문에 동기화의 오류가 발생한다.

 

 

Critical section (임계영역)

 

이는 공유되는 자원에서 동기화를 보장하기 위해 특정 프로세스나 쓰레드가 독점하는 것을 보장해 주는 곳을 말한다.

 

임계영역이 보장되어야 하는 곳에서 독점이 보장되지 않는다면 경쟁 상태에 의해 동기화에 실패할 수 있다.

 

 

Semaphore (신호등)

 

신호등이라는 뜻의 세마포어는 임계 영역의 사용이 끝났을 경우, 사용을 끝낸 프로세스(혹은 스레드)가 대기중인 프로세스(혹은 스레드)에게 알려주는 방식으로 동기화를 해결한다.

 

세마포어는 해당 방식의 변수를 두어 +와 -하여 진입 가능한 프로세스의 수를 조절하는데

 

sem_wait(sem)으로 -1 하면서 줄이고, sem_post(sem)으로 +1 하며 진입 가능 프로세스 수를 조절한다.

 

 

세마포어는 다른 프로세스를 무한 루프로 기다리게 하는 특정 방식과 다르게 대기하는 프로세스들을 세마포어 내부의 대기 큐에 저장한다.

 

대기 큐는 FIFO(First-In-First-Out) 방식으로 동작하며, 처음 대기하러 온 프로세스가 먼저 허가를 받아 다음으로 임계 영역으로 진입한다.

 

이는 무한 루프를 돌지 않아 CPU 리소스 사용량이 감소하는 장점을 가지지만, 코드가 매우 복잡해지는 단점이 있다.

 

 

Mutex (뮤텍스)

 

뮤텍스는 세마포어가 변수의 크기를 1로 두어(Binary Semaphore) 1개의 프로세스만 진입하게 하는 경우와 같다.

 

이는 단일 스레드 허용이므로 상대적으로 무겁고 오버헤드가 큰 구현일 수 있다.

 

 

CAS (Compare - and - Swap)

 

CAS는 다중 스레드 환경에서의 동기화 기법 중 하나로, 공유 데이터를 안전하게 업데이트하기 위해 사용된다.

 

CAS는 하드웨어 명령어인데, 특정 메모리 위치의 값을 읽어오고

 

만약 기대하는 값(복사된 값)과 현재의 값(포인터 참조 값) 비교하여 동일할 때만 연산을 수행하도록 한다.

 

int global_variable = 10;

bool my_cas(int *ptr, int expected, int new_value) {
    return __sync_bool_compare_and_swap(ptr, expected, new_value);
}

int main() {
    int expected_value = 10;
    int new_value = 20;

    // CAS 연산 수행
    if (my_cas(&global_variable, expected_value, new_value)) {
        printf("CAS successful. Variable value is now %d\n", global_variable);
    } else {
        printf("CAS failed. Variable value is %d, not equal to expected value %d\n", global_variable, expected_value);
    }

    return 0;
}

 

해당 my_cas 함수를 보면 ptr로 포인터 참조를 통해 실시간 값을 비교하고,

 

이 프로세스에 저장되어 있는 데이터와 같은 경우에만 연산을 수행하도록 하는 원자적인 연산이므로

 

다중 스레드 환경에서 공유 변수의 안전한 업데이트를 가능하게 한다.

 

 

'Jungle' 카테고리의 다른 글

[TIL] threads 코드 분석  (0) 2023.11.25
[TIL] 인터럽트 / lock, monitor  (3) 2023.11.24
[TIL] 우분투 포트 kill 하는 법  (0) 2023.11.22
[TIL] 네트워킹 키워드 쪽지 질문 정리  (0) 2023.11.21
[TIL] 파일 디스크립터  (1) 2023.11.21