728x90

5.1 생산자-소비자 문제

5.1.1 생산자-소비자 문제의 정의

  • 생산자-소비자 문제
    • 두 협력 프로세스 사이에 버퍼를 둠
    • 생산자 : 데이터를 넣는 프로세스
    • 소비자 : 데이터를 꺼내는 프로세스
    • 조건 1 : 버퍼에 여러 프로세스가 동시에 접근할 수 없음
      • 상호배제 필요
    • 조건 2 : 버퍼의 크기가 유한함
      • 동기화 필요
  • 생산자-소비자 문제를 유한 버퍼 문제라고도 함
    • 버퍼가 가득 찬 경우 : 생산자가 기다리게 됨
    • 버퍼가 빈 경우 : 소비자가 기다리게 됨

5.1.2 세마포어를 이용한 해결

  • 3개의 세마포어 이용
    • mutex : 상호배제 해결
      • 초깃값 = 1
    • empty : 버퍼가 가득 찬 경우의 동기화
      • 초깃값 = 버퍼의 크기 n
    • full : 버퍼가 빈 경우의 동기화
      • 초깃값 = 0

생산자의 코드

while(true){
데이터를 생산
P(empty);
P(mutex);
버퍼에 데이터를 넣음
V(mutex);
V(full);
}

소비자의 코드

while(true)
{
P(full);
P(mutex);
버퍼에서 데이터를 꺼냄
V(mutex);
V(empty);
데이터를 소비
}

판독기 - 기록기 문제

5.2.1 판독기 - 기록기 문제의 정의

  • 판독기 - 기록기 문제
    • 여러 협력 프로세스가 파일 같은 공유자원을 사이에 둠
    • 판독기 : 데이터를 읽는 프로세스
    • 기록기 : 데이터를 쓰는 프로세스
    • 조건 1 : 기록기가 공유자원에 데이터를 쓰는 중에는 다른 기록기나 판독기는 공유자원에 접근할 수 없음
      • 상호배제 필요
    • 조건 2 : 여러 판독기는 동시에 공유자원에서 데이터를 읽을 수 있음
  • 제 1 판독기 - 기록기 문제
    • 판독기가 공유자원에 접근 중이라면 기록기보다 판독기에 우선순위를 주는 것
    • 기록기가 기아상태에 빠질 수 있음.
  • 제 2 판독기 - 기록기 문제
    • 판독기가 공유자원에 접근 중일 때 대기 중인 기록기가 있다면, 새로운 판독기는 조건2에도 불구하고 대기함
    • 판독기의 병행성이 떨어짐
    • 판독기가 기아상태에 빠질 수 있음

5.2.2 세마포어를 이용한 해결

  • 제1판독기-기록기 문제 : 2개의 세마포어와 하나의 일반 변수 이용
    • wrt : 세마포어. 기록기에 대한 상호배제 해결
      • 초깃값 = 0;
    • mutex : 세마포어. rcount에 대한 상호배제 해결
      • 초깃값 = 1;

기록기의 코드

P(wrt);
공유자원에 쓰기
V(wrt);

판독기의 코드

P(mutex);
rcount = rcount + 1;
if(rcount == 1) then P(wrt);
V(mutex);
공유자원에서 읽기
P(mutex);
rcount = rcount - 1;
if(rcount == 0) then V(wrt);
V(mutex);
}
  • 제2판독기-기록기 문제 : 5개의 세마포어와 2개의 일반 변수 이용
    • wrt : 세마포어. 기록기에 대한 상호배제 해결
      • 초깃값 = 1
    • rcount : 일반 변수. 공유자원의 데이터를 읽는 중인 판독기의 개수
      • 초깃값 = 0
    • mutex1 : 세마포어. rcount에 대한 상호배제 해결
      • 초깃값 = 1
    • rd : 세마포어. 기록기가 대기 중일 때 새로운 판독기에 대한 상호배제 해결
      • 초깃값 = 1
    • wcount : 일반 변수. 공유자원에 데이터를 쓰거나 쓰기 위해 대기 중인 기록기의 개수
      • 초깃값 = 1
    • mutex2 : 세마포어. wcount에 대한 상호배제 해결
      • 초깃값 = 1
    • mutex3 : 세마포어. 기록기에 우선순위를 주기 위함
      • 초깃값 = 1

기록기의 코드

 P(mutex2);
 wcount = wcount + 1;
 if(wcount == 1) then P(rd);
 V(mutex2);
 P(wrt);
 공유자원에 쓰기
 V(wrt);
 P(mutex2);
 wcount = wcount - 1;
 if(wcount == 0) then v(rd);
 V(mutex2);

판독기의 코드

 P(mutex3);
 P(rd);
 P(mutex1);
 rcount = rcount + 1;
 if(rcount == 1) then P(wrt);
 V(mutex1);
 V(rd);
 V(mutex3);
 공유자원에서 읽기
 P(mutex1);
 rcount = rcount - 1;
 if(rcount == 0) then v(wrt);
 V(mutex1);

5.3 프로세스 간 통신

5.3.1 공유 메모리 방법

  • 공유 메모리 방법
    • 협력 프로세스가 공유자원을 이용하는 동일한 변수를 사용함으로써 데이터를 공유하는 방법
      • 고속 통신 가능
      • 통신상 발생할 수 있는 문제는 응용 프로그래머가 책임지고 해결함
        • 통신상 발생할 수 있는 문제 : 상호배제 , 동기화 등
      • 운영체제는 공유 기억장소만 제공

5.3.2 메시지 전달방법

  • 메시지 전달방법
    • 협력 프로세스가 메시지를 주고받으면서 데이터를 공유하는 방법
    • 커널이 제공하는 연산 send와 연산 receive 이용
    • 소량의 데이터를 주고받는 데 적합함
    • 통신상 발생할 수 있는 문제는 운영체제가 책임지고 해결함
  • 통신 링크
    • 메시지를 주고받는 두 프로세스 사이에 존재함
    • 통신 링크의 성질
      • 하나의 링크는 오직 두 프로세스만 연결할 수도 있고 여럿 연결할 수도 있음
      • 두 프로세스 사이에 오직 하나의 링크만 존재할 수도 있고 여럿 존재 할 수도 있음
      • 링크의 방향성을 단방향일 수도 있고 양방향일 수도 있음
      • 링크의 용량은 여러 형태로 설정할 수 있음
  • 직접통신
    • 두 프로세스가 직접 서로를 지정하여 메시지를 주고받는 방법
    • send(B,M) : 프로세스 B로 메시지 M을 보냄
    • receive(A,M) : 프로세스 A로부터 메시지를 M에 받음
      • 대칭형 주소 지정
    • receive(id,M) : 송신자 이름을 id에, 메시지를 M에 받음
      • 비대칭형 주소 지정
    • 두 프로세스 사이에 오직 하나의 통신 링크만 설정됨
    • 하나의 링크는 오직 두 프로세스 사이에만 연관됨
    • 통신 링크는 양방향
  • 간접 통신
    • 통신을 원하는 프로세스들 사이에 우편함을 두고 이를 통해 메시지를 주고받는 방법
    • send(X,m1) : 우편함 X로 메시지 m1을 보냄
    • receive(X,m1) : 우편함 X로부터 메시지를 m1에 받음
    • 두 프로세스 사이에 여러 개의 통신 링크가 존재 가능
    • 하나의 링크는 여러 프로세스와 연관 가능
    • 우편함이 수신 프로세스에 소속된 경우
      • 수신자가 하나
      • 통신 링크는 단방향
    • 우편함이 운영체제에 소속된 경우
      • 수신자가 여럿 가능
      • 한순간에 하나의 수신자만 수신하도록 운영체제가 관리함
      • 송신자와 수신자의 역할이 바뀔 수 있으므로 통신 링크는 양방향

참고 문헌 : 김진욱·이인복. 운영체제 워크북. 한국방송통신대학교출판문화원, 2023.

728x90
728x90

4.1 병행 프로세스의 개요

4.1.1 병행성과 병행 프로세스

동시수행

  • 한 프로세스나 쓰레드가 실행을 시작한 후 종료상태가 되지 않은 상황에서 다른 프로세스나 쓰레드가 실행되는 상황
    병행성(concurrency)
  • 여러 개의 프로세스 또는 쓰레드가 동시 수행되는 시스템의 특성
    병행 프로세스
  • 동시 수행되는 여러 개의 프로세스 또는 쓰레드
    CPU 개수에 따른 병행 프로세스의 실행 형태
  • 하나의 CPU : 인터리빙 형식
  • 여러 개의 CPU(멀티프로세서 시스템) : 메모리 구조에 따른 실행 형태
    • 강결합 시스템 : 하나의 기억장치를 공유하는 여러 CPU를 하나의 운영체제가 제어함
    • 약결합 시스템 : 각 시스템이 개별 운영체제로 독립적으로 운영되고 필요시 네트워크로 통신함

4.1.2 프로세스 간의 관계

독립 프로세스

  • 수행 중인 다른 프로세스의 영향을 주지도 않고 받지도 않는 프로세스
  • 프로세스의 데이터와 상태를 다른 프로세스와 공유하지 않음
  • 프로세스의 실행
    • 결정적 : 실행결과는 입력에 의해서만 결정됨
    • 재생 가능 : 실행결과는 같은 입력에 대해 항상 동일함
  • 타 프로세스와 무관하게 중단되거나 재시작될 수 있음
    협력 프로세스
  • 수행 중인 다른 프로세스와 영향을 주고받으며 동작하는 프로세스
  • 프로세스의 데이터와 상태를 다른 프로세스와 공유함
  • 프로세스의 실행
    • 비결정적 : 실행결과는 실행순서에 좌우됨
    • 재생 불가능 : 실행결과는 같은 입력에 대해 항상 동일함을 보장하지 못함

4.2 병행성 문제

4.2.1 상호배제

상호배제(mutual exclusion)

  • 2개 이상의 프로세스가 동시에 임계영역을 수행하지 못하도록 하는 것
    • 임계영역(critical section) : 2개 이상의 프로세스가 동시에 사용하면 안되는 공유자원을 액세스하는 프로그램 코드 영역

4.2.2 동기화

프로세스 동기화(synchronization)

  • 2개 이상의 프로세스에 대한 처리순서를 결정하는 것
    상호배제 또한 임계영역에 대한 동기화 문제

4.2.3 통신

프로세스 간 통신(InterProcess Communication : IPC)

  • 프로세스들이 데이터를 공유하기 위해 반드시 필요한 것
    프로세스 사이의 통신 방법
  • 하나의 변수를 사용하는 방법
  • 메시지를 서로 주고받는 방법

4.3 세마포어

  • 상호배제와 동기화 문제를 해결하기 위한 도구
  • 데이크스트라(Dijkstra, 다익스트라)가 제안함

4.3.1 세마포어의 정의

세마포어(semaphore)

  • 정수형 공용변수
    • 저장값 : 사용 가능한 자원의 수 또는 잠김이나 풀림의 상태
  • 초기화 : 0 이상인 정수로 상황에 맞게 초기화함
  • 두 기본연산 P와 V에 의해서만 사용됨
    • 기본연산 : 인터럽트되지 않고 하나의 단위로 처리됨
    • 연산 P : 검사 또는 감소시키려는 시도
    • 연산 V : 증가
      세마포어 s에 대한 연산 P(s)의 동작
  • 세마포어 s가 0보다 크면, 세마포어 s를 1만큼 감소시킴
  • 세마포어 s가 0보다 크지 않다면, 현재 프로세스는 연산 P를 완료하지 못한 채 대기상태로 전이
    • 이때 세마포어 s의 대기 큐에 현재 프로세스 추가
      세마포어 s에 대한 연산 V(s)의 동작
  • 세마포어 s의 대기 큐가 비어 있다면, 세마포어 s를 1만큼 증가시킴
  • 세마포어 s의 대기 큐가 비어 있지 않다면, 큐에서 한 프로세스를 빼서 준비상태로 전이
    • 이때 큐는 FIFO(First In First Out)로 동작하는 것으로 가정함

4.3.2 상호배제 해결

세마포어 mutex

  • 초깃값 : 1
    진입영역
  • 임계영역에 대한 수행을 해도 되는지 체크하는 코드를 임계영역의 시작부분에 둠
  • 연산 P(mutex)

해제영역

  • 다른 프로세스가 임계영역 수행을 시작할 수 있도록 하는 코드를 임계영역의 끝 부분에 둠
  • 연산 V(mutex)

4.3.3 동기화 해결

  • 프로세스 A가 특정 코드 S_1을 수행한 후에 프로세스 B가 코드 S_2를 수행 하도록 동기화를 하는 경우
  • 세미포어 sync
    • 초깃값 : 0
  • 코드 S_2 앞에 연산 P(sync)
  • 코드 S_1 뒤에 연산 V(sync)

참고 문헌 : 김진욱·이인복. 운영체제 워크북. 한국방송통신대학교출판문화원, 2023.

728x90
728x90

3.1 프로세스 스케줄링

  • 프로세스 스케줄링
    • 주어진 프로세스들이 여러 개인 경우, 어떤 순서대로 프로세스를 처리할지를 운영체제가 결정하는 것

3.1.1 스케줄링 단계

  • 상위단계 스케줄링
    • 장기 스케줄링
    • 시스템에 들어와 작업 큐에 있는 작업을 선택하여 프로세스를 생성한 후 프로세스 준비 큐에 전달하는 역할
    • 작업 선택 기준 : 시스템의 자원을 효율적으로 이용할 수 있도록 하는 것
      • 입출력(I/O) 중심 작업과 연산 중심 작업을 균형 있게 선택함
  • 하위 단계 스케줄링
    • 단기 스케줄링
    • 준비 큐에 있는 프로세를 선택해 사용 가능한 CPU를 할당하는 역할
    • 디스패치된 프로세스는 실행상태가 되어 프로세스가 처리됨
    • 하위단계 스케줄링의 수행 주체 : 디스패처(dispatcher)
  • 중간단계 스케줄링
    • 중기 스케줄링
    • 프로세스를 일시적으로 메모리에서 제거하여 중지시키거나 다시 활성화시켜 시스템에 대한 단기적인 부하를 조절하는 역할

3.1.2 스케줄링의 목표

  • 스케줄링의 기본 목표
    • 공정성 : 모든 프로세스가 적정 수준에서 CPU 작업을 할 수 있게 함
    • 균형성 : 시스템의 자원들이 충분히 활용될 수 있게 함
  • 운영체제 유형에 따른 스케줄링의 목표
    • 일과처리 운영체제 : 처리량의 극대화, 반환시간의 최소화, CPU 활용의 극대화
      • 처리량(throughput) : 주어진 시간에 처리한 프로세스 수
      • 반환시간(turnaround time) : 프로세스 생성 시점부터 종료 시점까지의 소요시간
    • 시분할 운영체제 : 빠른 응답시간, 과다한 대기시간 방지
      • 응답시간(response time) : 요청한 시점부터 반응이 시작되는 시점까지의 소요시간
      • 대기시간(waiting time) : 프로세스가 종료될 때까지 준비 큐에서 기다린 시간의 합
    • 실시간 운영체제 : 처리기한을 맞춤

3.1.3 스케줄링 정책

  • 선점(preemptive) 스케줄링 정책
    • 실행 중인 프로세스에 인터럽트를 걸고 다른 프로세스에 CPU를 할당 할 수 있는 스케줄링 방식
    • 높은 우선순위의 프로세스를 우선 처리해야 하는 경우에 유용함
      • 실시간 시스템, 시분할 시스템
    • 문맥 교환(context switching)에 따른 오버헤드 발생
      • 문맥 : CPU의 모든 레지스터와 기타 운영체제에 따라 요구되는 프로세스의 상태
      • 문맥 교환 : CPU가 현재 실행하고 있는 프로세스의 문맥을 PCB에 저장하고, 다른 프로세스의 PCB로부터 문맥을 복원하는 작업
      • 운영체제는 문맥 교환이 매우 빠르게 실행되도록 만들어져야 함
  • 비선점(nonpreemptive) 스케줄링 정책
    • 실행 중인 프로세를 바로 준비상태로 전이시킬 수 없는 스케줄링 방식
    • CPU를 할당받아 실행이 시작된 프로세스는 대기상태나 종료상태로 전이될 때까지 계속 실행상태에 있게 됨
    • 강제적인 문맥 교환이 없어 오버헤드가 발생하지 않음
    • 긴 프로세스가 실행 중이라면 짧은 프로세스가 오래 기다리게 되는 경우 발생

3.1.4 스케줄링의 평가 기준

  • 평균대기시간
    • 각 프로세스가 수행이 완료될 때까지 준비 큐에서 기다리는 시간의 합의 평균값
  • 평균반환시간
    • 각 프로세스가 생성된 시점부터 수행이 완료된 시점까지의 소요시간의 평균값

3.2 스케줄링 알고리즘

3.2.1 FCFS 스케줄링

  • 특징
    • 비선점 방식
    • 준비 큐에 도착한 순서에 따라 디스패치됨
  • 장점
    • 가장 간단한 스케줄링 기법
  • 단점
    • 짧은 프로세스가 긴 프로세스를 기다리거나, 중요한 프로세스가 나중에 수행될 수 있음
      • 시분할 운영체제나 실시간 운영체제에는 부적합함
    • 프로세스들의 도착순서에 따라 평균반환시간이 크게 변함

3.2.2 SJF 스케줄링

  • 특징
    • 비선점 방식
    • 준비 큐에서 기다리는 프로세스 중 실행시간이 가장 짧다고 예상되는 것을 먼저 디스패치함
  • 장점
    • 일괄처리 환경에서 구현하기 쉬움
  • 단점
    • 실제로는 먼저 처리할 프로세스의 CPU 시간을 예상할 수 없음
    • 짧은 프로세스가 긴 프로세스를 기다리거나, 중요한 프로세스가 나중에 수행될 수 있음
      • 시분할 운영체제나 실시간 운영체제에는 부적합함

3.2.3 SRT 스케줄링

  • 특징
    • SJF 알고리즘의 선점 방식
    • 준비 큐에서 기다리는 프로세스 중 남은 실행시간이 가장 짧다고 예상되는 것을 먼저 디스패치함
  • 장점
    • SJF 스케줄링보다 평균대기시간이나 평균반환시간에서 효율적임
  • 단점
    • 실제로는 프로세스의 CPU 시간을 예상할 수 없음
    • 각 프로세스의 실행시간 추적, 선점을 위한 문맥 교환 등 SJF보다 오버헤드가 큼

3.2.4 RR 스케줄링

  • 특징
    • 선점 방식
    • 준비 큐에 도착한 순서대로 디스패치하지만 정해진 시간 할당량에 의해 실행 제한
    • 시간 할당량 안에 종료하지 못한 프로세스는 준비 큐의 마지막에 배치됨
    • 시간 할당량 크기에 따라 성능 변화
  • 장점
    • CPU를 독점하지 않고 공평하게 이용됨
    • 시분할 운영체제에 적합함
  • 단점
    • 시간 할당량이 너무 크면 FCFS 스케줄링과 동일해짐
    • 시간 할당량이 너무 작으면 너무 많은 문맥 교환 발생으로 오버헤드가 커짐

3.2.5 HRN 스케줄링

  • 특징
    • 비선점 방식
    • 준비 큐에서 기다리는 프로세스 중 응답비율이 가장 큰 것을 먼저 디스패치함
      • 응답비율 = (대기시간+예상실행시간)/예상실행시간 = 대기시간/예상실행시간+1
    • 예상실행시간이 짧을수록, 그리고 대기시간이 길수록 응답비율이 커짐
  • 장점
    • SJF 스케줄링의 단점(긴 작업과 짧은 작업 사이의 지나친 불평등) 보완
  • 단점
    • 실제로는 프로세스의 CPU 시간을 예상할 수 없음

3.2.6 다단계 피드백 큐 스케줄링

  • 특징
    • 선점 방식
    • 입출력 중심인 프로세스와 연산 중심인 프로세스의 특성에 따라 서로 다른 시간 할당량 부여
    • 단계 1부터 단계 n까지 각 단계마다 하나씩의 준비 큐 존재
    • 단계가 커질수록 시간 할당량도 커짐
  • 스케줄링 방법
    • 신규 프로세스는 단계 1 의 준비 큐에서 FIFO 순서에 따라 디스패치됨
    • 입출력 같은 이벤트가 발생하면 CPU를 양보하고 대기상태로 갔다가 다시 준비상태가 될 때는 현재와 동일한 단계의 준비 큐에 배치됨
    • 시간 할당량을 다 썼지만 프로세스가 종료되지 못했다면 다음 단계의 준비 큐로 이동 배치됨
    • 마지막 단계에서는 RR 스케줄링 방식으로 동작함
    • 단계 k의 준비 큐에 있는 프로세스가 디스패치되려면 단계 1부터 단계 k-1까지 모든 준비 큐가 비어 있어야만 함
  • 장점
    • 입출력 위주의 프로세스는 높은 우선권 유지
    • 연산 위주의 프로세스는 낮은 우선권이지만 긴 시간 할당량을 가짐

참고 문헌 : 김진욱·이인복. 운영체제 워크북. 한국방송통신대학교출판문화원, 2023.

728x90
728x90

2.1 프로세스

2.1.1 프로세스의개요

  • 프로그램과 프로세스 차이
    • 프로그램 : 동작을 하지 않는 정적이며 수동적인 개체
    • 프로세스 : 실행중인 프로그램으로, 동작을 하는 능동적인 개체
  • 프로세스에는 실행을 위해 필요한 자원이 할당됨
    • 자원 : CPU, 메모리, 입출력장치, 파일 등
  • 프로세스의 동작 : CPU가 그 프로세스의 명령들을 실행하는 것
  • 운영체제가 처리하는 작업
    • 프로세스를 생성키기고 종료시키기 위한 다양한 작업
    • 프로세스를 실행시키기 위한 스케줄링 작업

2.1.2 프로세스의 구성

  • 메모리 구조
    • 코드 영역 : 해당 프로세스의 프로그램 자체
    • 데이터 영역 : 상수나 변수의 값, 서브프로그램 호출상태 등
      • 정적 데이터 영역
      • 스택 영역
      • 힙 영역
  • 프로세스 제어 블록(PCB)
    • 프로세스를 관리하기 위해 필요한 정보들로 구성
    • 프로세스 제어 블록에 포함되는 정보
      1. 프로세스 번호(PID) : 프로세스의 구분 기준
      2. 프로세스 상태 : 프로세스의 현재 상태
      3. 프로그램 카운터(PC) : 프로세스 수행을 위해 다음에 실행할 명령의 주소
      4. 레지스터 : CPU의 레지스터 정보
        • 실행상태에서 다른 상태로 전이되는 경우 CPU의 레지스터 정보를 이곳에 저장시킴
      5. 메모리 관리 정보 : 프로세스가 저장된 주소, 가상주소와 실주소의 사상정보, 메모리 경계 정보 등
      6. 프로세스 우선순위 : 스케줄링 시 필요한 프로세스의 우선순위 정보
      7. 회계정보 : CPU 사용시간, 메모리 사용량 등 다양한 정보2.1.3 프로세스 상태 관리
  • 프로세스 상태
    • 생성상태 : 처음 작업이 시스템에 주어진 상태
      • PCB와 메모리 구조가 생성되면 준비상태로 전이
    • 준비상태 : CPU 할당을 기다리는 상태
      • 디스패치 (프로세스에 CPU 할당)되면 실행상태로 전이
    • 실행상태 : CPU가 프로세스의 명령들을 처리하는 상태
      • 스케줄러가 다른 프로세스 선택 : CPU를 회수당하며 준비상태로 전이
      • 입출력 작업, 페이지 교환 요구 등 : CPU를 반납하고 대기상태로 전이
      • 모든 처리 완료 또는 운영체제가 강제 종료 : 종료상태로 전이
    • 대기상태 : 입출력 작업이 끝날 때까지 또는 특정 자원을 할당받을 때 까지 보류되는 상태
      • 재개 조건(입출력 작업 완료, 자원할당 완료 등)이 만족되면 준비상태로 전이
    • 종료상태 : 더이상 실행되지 않도록 끝난 상태
      • 프로세스에 할당되었던 자원 회수2.1.4 부모 프로세스와 자식 프로세스
  • 프로세스 생성 방법
    • 사용자가 프로그램을 직접 실행
    • 한 프로세스가 다른 프로세스 생성
      • 프로세스 생성 시스템 호출 이용
      • 부모 프로세스 : 시스템 호출을 하는 프로세스
      • 자식 프로세스 : 시스템 호출을 통해 새로 생성된 프로세스
  • 프로세스 생성 시스템 호출
    • UNIX, Linux : fork()
      • 자식 프로세스는 부모 프로세스의 복제본(메모리 구조, PCB)
      • PID는 새로 지정
    • Windows: CreateProcess()
      • 자식 프로세스는 새로운 프로그램으로 생성됨
  • 프로세스 종료 방법
    • 프로세스가 모든 처리를 완료하고 정상적으로 종료됨
    • 부모 프로세스에 의해 자식 프로세스가 강제로 종료됨
      • 자식 PID로 프로세스 종료 시스템 호출 이용
      • 부모 프로세스가 종료되는 경우 운영체제가 자식 프로세스 종료

2.2 쓰레드

  • 전통적인 프로세스
    • 자원 소유의 단위 : 하나의 메모리 구조
    • 디스패칭의 단위 : 하나의 제어 흐름
    • 프로세스 내에서 다중처리 불가
  • 쓰레드(thread)
    • 프로세스 내에서의 다중처리를 위해 제안된 개념
    • 프로세스는 자원 소유의 단위, 쓰레드는 디스패칭의 단위로 구분
    • 하나의 프로세스 내에는 하나 이상의 쓰레드 존재
      • 프로세스의 제어 흐름이 하나 이상 가능
  • 쓰레드와 프로세스
    • 쓰레드는 실행에 필요한 최소한의 정보만 가짐
      • PC를 포함된 레지스터 값
      • 스택 영역
      • 상태정보
    • 나머지 정보는 자신이 속해 있는 프로세스에 두고 다른 쓰레드와 공유
  • 다중 쓰레드로 구성된 프로세스
    • 멀티 CPU 또는 멀티코어인 컴퓨터 시스템
      • 다중 쓰레드를 병렬로 처리

참고 문헌 : 김진욱·이인복. 운영체제 워크북. 한국방송통신대학교출판문화원, 2023.

728x90
728x90

1.1 지옥에서 온 관리자, 깃

2005년, 리눅스 토르발스(Linus Torvalds)는 깃(Git)을 처음 세상에 소개

 

깃으로 무엇을 할 수 있을까?

깃의 제공하는 핵심 기능 3 가지

1. 버전 관리(Version Control)

문서를 수정할 때마다 언제 수정했는지, 어떤 것을 변경했는지 편하고 구체적으로 기록하기 위한 버전 관리 시스템

2. 백업하기(Backup)
백업 : 현재 컴퓨터에 있는 자료를 다른 컴퓨터에 복제하는 것

 

3. 협업하기(Collaboration)
깃을 사용하면 팀원들이 파일을 편하게 주고받으면서 일할 수 있음

또한 누가 어느 부분을 어떻게 수정했는지 기록에 남기 때문에 나중에 오류가 생겼을 때도 파악하기 쉬움

 


깃 프로그램의 종류

1. 깃허브 데스크톱(GitHub Desktop)

- 깃 온라인 저장소 서비스인 깃허브에서 제공하는 프로그램

- 복잡한 깃 사용법을 그래픽 사용자 인터페이스(Graphic User Interface, GUI) 구현

- 사용이 쉬워서 누구나 쉽게 배울 수 있다는 장점이 있음

- 자주 쓰는 기본적인 기능 위주로 되어 있기 때문에 깃 고급 사용자가 되면 아쉬울 수 있음

 

2. 토터스깃

- 토터스깃(TortoiseGit)은 윈도우(Window)전용 프로그램으로 윈도우 탐색기의 빠른 메뉴에 추가되는 프로그램

 

3. 소스트리

- 소스트리(SourceTree)는 깃의 기본 기능부터 고급 기능까지 사용할 수 있는 프로그램

- 기능이 많아 사용법은 복잡하지만 어는 정도 익숙해지면 자유롭게 깃을 활용할 수 있음

 

4. 커맨드 라인 인터페이스

- 커맨드 라인 인터페이스(Command Line Interface, CLI)는 터미널 창에 직접 명령을 입력해서 깃을 사용하는 방식

- 소스트리나 깃허브 데스크톱 등 그래픽 사용자 인터페이스로 만들어진 프로그램으로 깃을 사용하는 것보다 어려움

- 기본적인 리눅스 명령을 알아야 하고, 깃 명령도 외워야 함

- 개발자 대부분은 커맨드 라인 인터페이스로 깃을 사용

 

1.2 깃 설치하기

깃을 사용하기 위해서는 먼저 사용자 컴퓨터에 깃을 설치해야 함

깃은 누구나 무료로 내려받아 설치할 수 있음

 

윈도우에 깃 설치하기

깃에서는 리눅스 명령을 사용하기 때문에 윈도우에 깃을 설치하면 리눅스 명령을 사용할 수 있도록 깃 배시(Git Bash)라는 프로그램이 함께 설치됨

 

맥에 깃 설치하기

맥(Mac) 운영 체제에서는 리눅스 명령을 기본으로 사용하기 때문에 깃을 설치한 후 맥에 있는 터미널 기능을 통해 깃을 사용

터미널 창이 나타나면 'git' 을 입력

$ git

깃이 제대로 설치됐다면 git 명령 다음에 쓸 수 있는 여러 옵션들이 나타남

 

깃 환경 설정

깃을 사용하기 전에 먼저 사용자 정보를 입력해야 함

깃은 버전을 저장할 때 마다 그 버전을 만든 사용자 정보도 함께 저장하기 때문

- 운영체제와 상관없이 리눅스 방식의 명령을 사용

$ git config --global user.name "Woomin"
$ git config --global user.email "changwoomin426@gmail.com"

깃에서 사용자 정보를 설정하려면 git config 명령을 사용

여기에 --global 옵션을 추가하면 현재 컴퓨터에 있는 모든 저장소에서 같은 사용자 정보를 사용하도록 설정

 

1.3 리눅스 명령 연습

현재 디렉터리 살펴보기

~(물결표시) : 현재 홈 디렉터리(home directory) 있다는 뜻
- 윈도우 탐색기의 '폴더(folder)를 리눅스에서는 '디렉터리(directory)'라고 부름 

 

$ pwd

'pwd' 명령을 입력하고 Enter 를 누르면 현재 위치의 경로가 나타남

- pwd는 'print working directory'의 줄임말

 

$ ls

현재 디렉터리에 어떤 파일이나 디렉터리가 있는지 확인할 때는 'ls' 명령을 사용

디렉터리와 파일 이름이 나타남

- ls 명령은 list의 줄임말

 

clear

터미널 창을 사용하다 보면 명령과 결과 화면으로 창이 가득 차게 됨

화면을 깨끗이 정리하려면 'clear' 명령을 입력

 

$ ls -la

리눅스 명령에 옵션(Option)을 추가하려면 붙임표(-)와 원하는 옵션을 나타내는 글자를 함께 입력

두 옵션을 함께 사용하려면 '-la' 또는 '-al' 처럼 순서에 상관없이 글자를 붙여서 추가 입력

옵션 설명
-a 숨김 파일과 디렉터리도 함께 표시
-l 파일이나 디렉터리의 상세 정보를 함께 표시
-r 파일의 정렬 순서를 거꾸로 표시
-t 파일 작성 시간 순으로 (내림차순) 표시

 

터미널 창에서 디렉터리 이동

터미널 창에서 디렉터리 사이를 이동할 때는 'cd' 명령을 사용 

- cd 명령은 'change directory'의 줄임말

$ cd ..

현재 위치에서 상위 디렉터리로 이동 cd 명령 다음에 한칸 띄고 마침표 2개를 입력

 

cd 명령을 실행한 후 $ 기호 위에 표시된 경로를 확인

$ cd ..
$ ls

한 단계 더 위인 (root) 폴더 까지 이동

ls 명령을 사용하면 파일과 디렉터리를 확인 가능

 

$ cd User

하위 디렉터리로 이동할 때는 cd 명령 다음에 이동할 하위 디렉터리 이름을 입력

 

$ cd ~

처음에 출발했던 디렉터리 , 즉 홈 디렉터리로 돌아가려면 '~'는 홈디렉터리를 나타냄

리눅스에서 디렉터리를 나타내는 기호

기호 설명
~ 현재 접속 중인 사용자의 홈 디렉터리를 가리킴
사용자 디렉터리라고도 부름
사용자 아이디는 5글자까지만 나타냄
./ 현재 사용자가 작업 중인 디렉터리
../ 현재 디렉터리의 상위 디렉터리

 

 

터미널 창에서 디렉터리 만들기 및 삭제하기

- mkdir 명령은 'make directory'의 줄임말

- 현재 홈 디렉터리가 아닌 다른 위치에 있다면 cd ~/Documents를 입력해서 Docu-ments 디렉터리로 이동한 후 mkdir을 사용

$ cd Documents
$ mkdir test

mkdir 명령을 실행하고 하위 디렉터리가 만들어져도 화면에는 아무것도 나타나지 않음

디렉터리가 제대로 만들어졌는지 확인하기 위해 ls 명령을 입력

 

$ rm -r test
$ ls

디렉터리를 삭제할 때는 'rm' 명령을 사용

이때 -r옵션을 붙이면 디렉터리안에 있는 하위 디렉터리와 파일까지 함께 삭제

- rm은 'remove'의 줄임말

여기서 기억해야 할 것은 삭제할 디렉터리의 상위 디렉터리에서 rm 명령을 입력해야 한다는 것

예를 들어 Documents 디렉터리 안에 있는 test 디렉터리를 삭제하려면 먼저 Documents 디렉터리로 이동한 다음

rm 명령을 입력해야함

 

빔에서 텍스트 문서 만들기

리눅스의 기본 편집기인 빔(Vim)은 터미널에서 사용할 수 있는 대표적인 편집기

- 맥에서는 빔 대신 나노(nano)를 사용하기도 함

$ cd Documents
$ mkdir test
$ cd test

기본적으로 홈 디렉터리부터 시작

Documents 디렉터리로 이동해서 test 디렉터리를 만들고 test 디렉터리로 이동

 

$ vim test.txt

현재 디렉터리에 test.txt을 만들기 위해 다음과 같이 'vim' 을 입력

빔에는 문서를 작성하는 '입력 모드''와 문서를 저장하는 'ex 모드' 가 있음

빔은 처음에 'ex 모드'로 열리기 때문에 키를 눌러도 반응이 없는 것

 

빔에서 텍스트를 입력하려면 ex모드에서 i 또는 a 를 눌러 입력 모드로 바꿔야 함

입력 모드가 되면 화면 왼쪽 맨 아래 '끼워넣기' 라는 단어가 뜨는데, 이때부터 텍스트를 입력 가능

- i 는 insert(삽입)를 의미

- a 는 add(추가)를 의미

텍스트 입력이 끝난 후 파일을 저장할 때는 다시 ex 모드로 돌아가야 함

Esc를 누르면 ex모드로 돌아감

그리고 콜론(:)을 입력하면 원래 '끼워넣기'가 있던 자리에 텍스트를 입력할 수 있음

':wq' 명령을 입력 'w' 는 저장 'q' 종료를 실행하는 명령

파일이 저장하면서 편집기가 종료 터미널 창으로 되돌아감

 

빔 ex 모드 명령 모음

명령 설명
:w 또는 :write 편집 중이던 문서를 저장
:q 또는 :quit 편집기를 종료
:wq (파일) 편집 중이던 문서를 저장하고 종료
파일 이름을 함께 입력하면 그 이름으로 저장
:q! 문서를 저장하지 않고 편집기를 종료
확장자가 .swp인 임시 파일이 생김

ex 모드에서 사용하는 명령은 콜론(:)으로 시작

 

 

깃에서 기본 편집기 변경

깃을 설치할 때 기본적으로 빔을 사용하도록 설정했지만, 자신이 익숙하게 사용하는 편집기가 있다면 깃을 설치한 후에도 다른 편집기로 바꿀 수 있음. 예를 들어 깃의 기본 편집기를 'Notepad++'로 바꾸려면 터미널 창에서 아래와 같이 입력

$ git config --global core.editor "notepad++"

 

 

텍스트 문서 내용 확인

터미널 창에서 간단히 텍스트 문서의 내용을 확인할 때는 리눅스의 cat 명령을 사용

- cat 명령은 concatenate(연쇄하다)의 줄임말

$ cat test.txt

cat 명령과 텍스트 파일 이름을 함께 입력

 

명령 설명
$ cat 파일 파일의 내용을 화면에 표시
$ cat 파일1,파일2 파일n > 새파일 파일 n개를 차례로 연결해서 새로운 파일를 만듬
$ cat 파일>>파일2 파일1의 내용을 파일2 끝에 연결

 

 

 

참고 문헌 : 이고잉 고경희. Do it! 지옥에서 온 문서  관리자 깃&깃허브 입문. 이지스퍼블리싱, 2019

728x90

'전산 > Git' 카테고리의 다른 글

GitHub - 터미널로 GitHub 이용하기  (0) 2024.07.03
728x90

1.1 운영체제란 무엇인가?

1.1.1 운영체제의 정의

컴퓨터 시스템의 구성

 

하드웨어 : CPU, 메모리, 저장장치, 입출력장치, 네트워크 장치 등

- 저장장치 : 하드 디스크, SSD 등

- 입출력장치 : 키보드, 마우스,프린터 등

 

소프트웨어 : 응용 소프트웨어, 시스템 소프트웨어

- 응용 소프트웨어 : 웹 브라우저, 워드프로세서, 게임, 그래픽 소프트웨어 등

- 시스템 소프트웨어 : 운영체제, 컴파일러 등

 

운영체제

대표적인 시스템 소프트웨어

다음을 제공하는 프로그램들의 모음

- 컴퓨터 시스템의 자원 관리

- 컴퓨터 프로그램이 동작하기 위한 서비스 제공

 

1.1.2 운영체제의 역할

컴퓨터 시스템의 자원을 제어 및 관리

자원 : 하드웨어 자원, 소프트웨어 자원, 데이터

- 하드웨어 자원 : CPU, 메모리, 키보드, 마우스, 네트워크 카드 등

- 소프트웨어 자원 : 웹 브라우저, 워드프로세서, 게임 등

컴퓨터 시스템을 효율적으로 운영하는 목적

 

사용자지원

- 사용자가 내린 명령을 해석하여 실행함

- 사용자와 하드웨어 사이의 매개체 역할

- 사용자에게 편의성을 제공하는 목적

 

1.1.3 컴퓨터 시스템과 운영체제

운영체제가 없던 초기의 컴퓨터 시스템

- 응용 프로그램이 직접 컴퓨터 시스템의 자원 제어

- 하나의 하드웨어를 여러 사용자가 공유해서 사용하는 경우 자원을 나눠 쓰기 어려움

 

운영체제가 있는 컴퓨터 시스템

- 하드웨어와 응용 프로그램 사이에 운영체제 위치

- 운영체제가 컴퓨터 시스템의 자원 제어

- 여러 응용 프로그램이 동시에 수행되더라도 운영체제가 자원을 효율적으로 나눔

- 컴퓨터 시스템이 안정적이고 효율적으로 동작하도록 함

 

1.1.4 커널 모드와 사용자 모드

커널 모드(슈퍼바이저 모드)

- 하드웨어를 직접 제어할 수 있는 CPU의 명령어를 사용할 수 있는 모드

- 운영체제의 커널이 동작함

 

사용자 모드(보호 모드)

- 하드웨어를 직접 제어할 수 있는 CPU의 명령어를 사용할 수 없는 모드

- 응용 프로그램이 동작함

 

커널

커널 모드에서 동작하는 운영체제의 핵심 요소

응용 프로그램과 하드웨어 수준의 처리 사이의 가교 역할

 

일체형 커널(monolithic kernel)

- 운영체제의 모든 서비스가 커널 내에 포함됨

- 장점 : 커널 내부 요소들이 서로 효율적으로 상호작용을 함

- 단점 : 한 요소라도 오류가 발생하면 시스템 전체에 장애 발생 가능

- UNIX와 Linux 운영체제

 

마이크로커널(microkernel)

- 운영체제 요소의 대부분을 커널 외부로 분리함

- 커널 내부에는 메모르 관리, 멀티태스킹, 프로세스 간 통신(IPC) 등 최소한의 요소만 남김

- 장점 : 새로운 서비스를 추가하여 운영체제를 확장하기 쉬우며, 유지보수가 용이하여 안정성이 우수함

- 단점 : 커널 외부의 운영체제 요소들 사이는 프로세스 간 통신이 필요하여 성능저하 발생

 

시스템 호출

응용 프로그램이 하드웨어에 대한 제어가 필요한 경우에 필요함

운영체제에 서브스를 요청하는 메커니즘

1. 사용자 모드 : 응용 프로그램이 시스템 호출

2. 모드 변경 : 사용자 모드 -> 커널 모드

3. 커널 모드 : 커널이 동작하며 하드웨어 제어

 

1.2 운영체제의 구성

자원의 성격에 따라 구분

- 프로세스 관리자, 메모리 관리자, 장치 관리자, 파일 관리자

 

각 서브시스템

- 자신의 자원을 모니터링

- 정해 둔 기준에 따라 자원의 배분 및 회수

 

1.2.1 프로세스 관리자

프로세스의 생성 및 삭제

CPU 할당을 위한 스케줄 결정

프로세스의 상태를 관리하며 상태 전이 처리

 

1.2.2 메모리 관리자

메모리(주기억장치) 공간에 대한 요구의 유효성 체크

메모리 할당 및 회수

메모리 공간 보호

 

1.2.3 장치 관리자

컴퓨터 시스템의 모든 장치 관리

시스템 장치의 할당, 작동, 반환

 

1.2.4 파일 관리자

컴퓨터 시스템의 모든 파일 관리

파일의 생성, 열기, 수정, 닫기, 삭제

파일 관리를 위한 저장장치의 공간 관리

파일의 접근 제한 관리

 

1.3 운영체제의 유형

1.3.1 일괄처리(batch processing) 운영체제

작업을 모아서 순서대로 처리하는 방식

사용자와 상호작용 없이 순차적으로 실행

나중에 들어온 작업은 앞선 작업들이 모두 끝날 때까지 아무런 상호작용 없이 기다려야만 함

 

1.3.2 시분할(time-sharing) 운영체제

대화형(interactive) 운영체제라고도 함

여러 프로그램에 대해 각 프로그램을 한 번에 조금씩 수행하는 방식

사용자들은 마치 혼자 컴퓨터를 사용하는 듯한 느낌을 받음

응답시간이 일괄처리 운영체제보다 크게 단축됨

- 응답시간 : 요청한 시점부터 반응 시작되는 시점까지의 소요시간

 

1.3.3 실시간(real-time) 운영체제

원하는 시간 내에 프로그램의 결과를 얻을 수 있는 방식

처리결과가 현재의 결정에 영향을 주는 환경에서 사용됨

- 미사일 제어 시스템, 증권거래 관리 시스템 등

 

1.3.4 분산 운영체제

분산 시스템을 관리하기 위한 운영체제

- 분산 시스템 : 2개 이상의 컴퓨터 시스템이 네트워크로 서로 연결되어 서로의 자원을 이용하는 시스템

다른 컴퓨터 시스템은 자원을 이용하는 것이 마치 자신의 컴퓨터 시스템에 있는 자원을 이용하는 것처럼 가능해야 함

 

 


참고 문헌 : 김진욱·이인복. 운영체제 워크북. 한국방송통신대학교출판문화원, 2023. 5-9

728x90
728x90

1.1 자료구조와 알고리즘

자료구조란?

 

자료구조(data structure)

자료들을 정리하여 보관하는 여러 가지 구조

 

알고리즘(algorithm)

주어진 문제를 처리하는 절차

또는

문제를 풀기 위한 단계적인 절차

 

특정한 일을 수행하는 명령어의 집합

 

프로그램 = 자료구조 + 알고리즘

 

정의 1.1 알고리즘

입 력 : 0개 이상의 입력이 존재하여야 한다.

출 력 : 1개 이상의 출력이 존재하여야 한다.

명백성 : 각 명령어의 의미는 모호하지 않고 명확해야 한다.

유한성 : 한정된 수의 단계 후에는 반드시 종료되어야 한다.

유효성 : 각 명령어들은 종이와 연필 , 또는 컴퓨터로 실행 가능한 연산이어야 한다.

 

 

 

// 프로그램 1.1 cal_scores.c

#defube MAX_ELEMENTS 100
int scores[MAX_ELEMENTS]; // 자료구조

int get_max_score(int n) // 학생의 숫자는 n
{
	int i, largest;
    largest = scores[0]	// 알고리즘
    for(i = 1; i < n ; i++)
    {
    	if(scores[i] > scores[i];
        {
        	largest = scores[i];
        }
    }
    return largest;
}

 

알고리즘을 기술하는 4가지 방법

1. 한글이나 영어 같은 자연어

2. 흐름도(flowchart)

3. 의사 코드(pseudo-code)

4. 프로그래밍 언어

 

가장 많이 쓰이는 방법은 

3. 의사코드

4. 프로그래밍 언어

 

 



1.2 추상자료형

자료형(data type)

데이터의 종류

 

(정수, 실수, 문자열 등 기초적인 자료형의 예)

(스택, 큐, 리스트, 트리 등 새로운 자료형)

 

- 배열

동일한 자료형아 여러 개 모인 것

 

- 구조체

다른 자료형이 여러 개 모인 것

 

연산(operation)

정수 간의 덧셈, 뺄샘, 곱셈, 나눗셈, 나머지 연산 ,==,> , <

 

추상 자료형(ADT : abstract data type)

추상적, 수학적으로 자료형을 정의

실제적인 구현으로부터 분리되어 정의된 자료형

 

ADT 안에는 객체(objects) 와 함수(functions) 들이 정의

 

추상화

어떤 시스템의 간략화된 기술

또는

명세로서 시스템의 정말 핵심적인 구조나 동작에만 집중하는 것

 

객체지향언어에는 "클래스"개념을 사용하여 ADT가 구현

private나 protected 키워드를 이용하여 내부 자료의 접근을 제한

클래스는 계층구조(상속 개념 사용)로 구성 될수 있음

1.3 알고리즘의 성능 분석

수행시간 측정방법

// 방법 #1
#include <time.h>

start = clock();

...

stop = clock();
double duration = (double)(stop - start) / CLOCKS_PER_SEC;
// 방법 #2
#include <time.h>

start = time(NULL);

...

stop = time(NULL);
double duration = (double) difftime(stop,start);

 

clock() 함수

호출 프로세스에 의하여 사용된 CPU 시간을 계산

 

time() 함수

초 단위로 측정된 시간을 반환

 

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
	clock_t start, stop;
    double duration;
    start = clock();	// 측정 시작
    
    for(int i = 0; i < 1000000; i++)	// 의미 없는 반복 루프
    ;
    stop = clock();	// 측정 종료
    duration = (double)(stop - start) / CLOCKS_PER_SEC;
    printf("수행시간은 %f초입니다.\n",duration);
    return 0;
 }
 
 // 실행 결과
 // 수행 시간은 0.002000초 입니다.

 

알고리즘의 복잡도 분석방법

알고리즘 복잡도 분석(complexity)

구현하지 않고도 모든 입력을 고려하는 방법

실행 하드웨어나 소프트웨어 환경과는 관계없이 알고리즘의 효율성을 평가할 수 있다.

 

시간 복잡도 함수

시간 복잡도(time complexity)
알고리즘의 수행시간 분석

 

공간 복잡도(space complexity)

알고리즘이 사용하는 기억공간 분석

 

알고리즘의 비교

  알고리즘 A 알고리즘 B 알고리즘 C
대입연산 1 n n * n
덧셈연산   n n * n
곱셈연산 1    
나눗셈연산      
전체연산수 2 2n 2n^2

 

빅오 표기법

빅오 표기법을 사용하면 시간 복잡도 함수의 증가에 별로 기여하지 못하는 항을 생략함으로써 시간복잡도를 간단하게 표시할 수 있다.

 

O(1) 상수형
O(logn) 로그형
O(n) 선형
O(nlogn) 선형로그형
O(n^2) 2차형
O(n^3) 3차형
O(2^n) 지수형
O(n!) 팩토리얼형

 

알고리즘이 지수형이나 팩토리얼형의 시간복잡도를 가지면 사실상 사용할 수 없다.

입력의 개수가 30을 넘으면 현재의 가장 강력한 수퍼 컴퓨터를 동작시켜도 우주가 탄생되어 지금까지 흘러온 시간보다 더 많은 수행 시간을 요구할 수도 있다.

 

빅오표기법 이외의 표기법

빅오메가(big omega) Ω

어떤 함수의 하한을 표시하는 방법

 

빅세타(big theta) Θ

 

3개의 표기법 중에서 가장 정밀한 것은 

빅세타

 

통상적으로 빅오 표기법을 많이 사용

 

최선, 평균, 최악의 경우

최악의 경우(worst case)

자료집합 중에서 알고리즘의 수행시간이 가장 오래 걸리는 경우

 

최선의 경우(best case)

수행시간이 가장 적은 경우

 

평균적인 경우(average case)

알고리즘의 모든 입력을 고려하고 각 입력이 발생하는 확률을 고려하여 평균적인 수행시간을 의미

 

 

참고문헌 : 천인국 · 공용해 · 하상호. C언어로 쉽게 풀어쓴 자료구조. 생능출판사, 2005

728x90

'전산 > 자료구조' 카테고리의 다른 글

자료구조 - 자료구조, 데이터 구조  (1) 2024.07.05
자료구조 - 스택(Stack)  (0) 2024.07.01

+ Recent posts