생능출판사 명품 운영체제

 

본 연습문제들은 작성자 본인이 푼것이라 틀릴 수 도 있습니다.

 

[개념체크]

 

1. 물리 메모리의 크기 한계를 극복하기 위한 메모리 관리 기술은?

가상 메모리

 

2. 가상 메모리의 핵심 내용과 관계가 먼 것은?

메모리 사용량이 적은 프로세스의 우선 스케줄링

 

3. 스래싱에 대한 해결책이 아닌 것은?

TLB의 항목수 늘리기

 

4. 스왑 영역으로 적합하지 않는 것은?

 

 

5. 가상 메모리 기법이 도입된 이유는?

물리 메모리보다 큰 프로세스를 실행시키기 위해

 

6. 가상 메모리 기법이 도입된 이유는?

물리 메모리의 크기 한계 극복

 

7. 요구 페이징에 대한 설명으로 틀린 것은?

프로세스의 페이지를 가능한 많이 적재하도록 프레임을 할당하는 기법

 

8. 요구 페이징(demand paging)에서 요구(demand)의 의미는 무엇인가?

페이지가 필요할 때까지 물리 메모리에 적재하지 않고 두었다가, 페이지가 필요할때 물리 메모리를 할당받고 디스크에서 읽어 적재시킨다는 의미

 

9. 요구 페이징에서 요구의 의미에 가장 근접한 것은 무엇인가?

페이지 폴트가발생할 때

 

10. 페이지 테이블 항목에 valid 비트의 역할은 무엇인가?

1이면 페이지가 메모리 프레임에 존재. presence 비트라고도 함, 

 

11. 페이지 테이블의 항목을 구성하는 다음 필드의 용도를 기술하라.

(1) valid bit : 1이면 페이지가 메모리 프레임에 존재. presence 비트 라고도 함

(2) modified bit : 1이면 페이지가 적재된 후 수정되었음. dirty 비트 라고도 함

(3) reference bit : 1이면 페이지가 최근에 참조되었음

(4) protection bit : 'R'이면 읽기 전용 페이지, 'RW'이면 읽기 쓰기 모두 가능한 페이지

 

12. 페이지가 스왑-아웃될 때 페이지 테이블의 필드에서 일어나는 변화는?

valid bit : 1 -> 0, modified bit : 1 -> 0

 

13. 요구 페이징에서 페이지 폴트가 급격히 자주 발생하는 상황을 무엇이라고 부르는가?

스래싱

 

14. 다음은 시간 지역성과 공간 지역성 중 무엇에 대한 설명인가?

(1) 배열은 보통 순차적으로 액세스되므로, 현재 액세스하고 있는 배열의 다음 원소들이 가까운 미래에 액세스될 가능성이 매우 높다. 공간 지역성

(2) 프로그램 코드 역시 위에서 아래로 순차적으로 실행되므로, 현재 100 번지의 명령이 실행되고 있다면 곧 104 번지의 명령을 실행할 가능성이 매우 높다. 공간 지역성

(3) 프로그램 내에 지금 액세스되는 주소 영역(혹은 페이지)이 가까운 미래에 다시 액세스될 가능성이 크다. 시간 지역성

(4) 반복문의 실행 동안 코드나 데이터가 아주 짧은 시간 내에 다시 액세스될 가능성이 매우 높다. 시간 지역성

 

15. 다음 중 공간 지역성을 설명하는 것이 아닌 것은?

반복문의 실행 동안 코드나 데이터가 아주 짧은 시간 내에 다시 액세스될 가능성이 매우 높다

 

16. 다음 중 참조의 지역성을 훼손할 수 있는 것은?

1MB 크기의 큰 배열 사용

 

17. 다음 중 참조의 지역성을 기반으로 하는 컴퓨터 시스템의 정책이 아닌 것은?

페이징 기법

 

18. 시스템을 관찰한 결과, 한 동안 잠잠하다가 일정 시간 페이지 폴트가 연이어 발생한 후 페이지 폴트가 다시 줄어든다. 여기서 페이지 폴트가 연이어 발생하는 상황을 가장 가깝게 설명한 것은?

작업 집합에 포함되는 페이지가 적재되고 있다

 

19. 시스템을 관찰한 결과, 한 동안 잠잠하다가 일정 시간 페이지 폴트가 연이어 발생한 후 페이지 폴트가 다시 줄어든다. 여기서 페이지 폴트가 연이어 발생하는 상황으로 예상할 수 없는 것은?

스래싱이 발생하고 있다

 

20. 시스템 운영자가 스래싱이 발생하고 있음을 탐지하기 위해 필요한 정보는?

CPU 활용률과 입출력 비율의 변화

 

21. DOM이 동시에 실행되는 프로세스의 개수라고 할 때, 스래싱이 발생하는 것이라고 판단할 수 있는 상황은?

DOM 증가에 따른 CPU 활용률의 갑작스런 감소

 

22. 스래싱이 발생하는 원인은 무엇인가?

① 메모리에 적재한 프로세스의 개수가 과다함

 

23. 다음 그래프는 무엇을 보여주고 있는지 간단히 설명하라.

동시에 실행되는 프로세스의 수에 따라 스래싱이 발생하는 상황을 보여준다. 동시에 실행되는 프로세스의 수가 증가할 때 CPU 활용률이 높아지는 것이 컴퓨터 시스템의 정상적인 모습이지만, 프로세스의 수가 더 증가하면 프로세스당 메모리량이 줄어들어 페이지 폴트가 급격히 증가하고 이로 인해 입출력 작업이 증가하며, CPU는 입출력 작업의 완료를 기다리느라 정상적인 프로그램을 실행하지 못하여 오히려 CPU 활용률이 떨어진다. 이러한 현상을 스래싱이라고 한다. M 시점부터 스래싱이 발생하기 시작한다.

 

24. 다음 그림에 대한 설명으로 옳은 것을 모두 골라라?

A 영역은 매우 정상적인 시스템의 모습이다

B 영역에서 스래싱이 발생하고 있다

동시에 실행되는 프로세스의 수가 M보다 커지면 과도한 디스크 입출력이 발생한다

이 그래프에서 B의 현상이 발생하는 원인은 프로세스 당 메모리가 부족하기 때문이다

이 그래프의 B 부분에는 페이지 폴트가 심각하게 발생한다

 

25. 가상 메모리 기법에서는 프로세스의 모든 페이지를 메모리 프레임에 적재해두지 않는다. 그러면 프로세스 당 몇 개의 페이지를 메모리 프레임이 할당하는 것이 적당한가?

작업 집합을 포함할 만큼의 페이지

 

26. 페이지 교체 알고리즘의 목표는 무엇인가?

현재 작업 집합에 포함되지 않거나 가까운 미래에 참조되지 않을 페이지를 희생 페이지로 선택하여 페이지 폴트의 횟수를 줄이는 것이다

 

27. 교체되기로 선택된 페이지를 무엇이라고 부르는가?

희생 페이지

 

28. 다음 중 가장 비현실적인 페이지 교체 알고리즘은?

최적 교체 알고리즘

 

29. 다음 중 참조의 지역성이 전혀 반영되지 않는 페이지 교체 알고리즘은?

FIFO

 

30. 페이지 교체 알고리즘을 평가하는 잣대로 가장 적합한 것은?

페이지 폴트 횟수

 

31. Clock 페이지 교체 알고리즘을 설명한 것 중 틀린 것은?

페이지가 액세스될 때 마다 해당 메모리 프레임에 만들어둔 참조 비트를 0로 만든다

 

32. 희생 페이지를 찾기 위해 현재 적재된 페이지들을 검색하는 시간이 가장 빠른 것은?

최적 교체 알고리즘

 

33. 응용프로그램은 컴파일 과정에서 코드와 데이터로 분리되어 실핼 파일이 구성된다. 아래는 응용프로그램을 구성하는 여러 페이지 중에서 일부이다.

(1) main() 함수의 for문이 실행되는 동안 형성되는 작업 집합을 페이지 순서대로 나열하라.

페이지 0 → 페이지 7(변수 i 액세스) → 페이지 3(함수 f() 코드 실행) → 페이지 9(변수 j 액세스) → 페이지 6(배열 n[] 액세스)

(2) 페이지 0만 적재된 상태에서 응용프로그램이 실행을 시작한다. 다른 페이지들일 적재되지 않았지만 일단 적재되면 실행이 끝날 때 까지 스왑-아웃되지 않는다고 가정하자. 이 프로그램이 실행되는 동안 페이지 폴트가 발생하지 않는 경우는?

함수 f()의 for 문에서 sum += n[j]의 실행 시 sum 변수 액세스

sum 변수는 페이지 7에 존재하는데, 함수 f()가 실행될 때 변수 i를 액세스하기 위해 페이지 7이 적재되어 있으므로 sum 변수를 액세스할 때 페이지 폴트가 발생하지 않는다

생능출판사 명품 운영체제

 

본 연습문제들은 작성자 본인이 푼것이라 틀릴 수 도 있습니다.

 

[개념체크]

 

1. 다음은 페이징 메모리 관리에 대해 기술하는 문장이다. 보기에서 골라 빈칸을 채워라.

페이징은 프로세스의 주소 공간을 ( 페이지 )라는 ( 고정 ) 크기로 나누고 ( 물리 메모리 ) 역시 ( 페이지 ) 크기와 동일한 크기로 나누고 이를 ( 프레임 ) 이라고 부르며, 프로세스의 각 ( 페이지 ) 를 임의의 빈 ( 프레임 ) 에 할당하는 메모리 관리 기법이다.

 

2. 프로세스가 실행될 때 변수의 물리주소를 알아내기 위해 사용하는 것은?

페이지 테이블

 

3. 32비트의 주소 체계에서 페이지의 크기가 4KB라면, 한 프로세스 당 페이지 테이블의 크기는 얼마인가?

4MB

 

4. 페이지 테이블에 들어 있는 항목으로 적당한 것은?

④ 페이지의 물리 주소와 페이지 크기, 페이지의 논리 주소, 그리고 프로세스 번호 

---> 1번으로 수정

 

5. 페이지 테이블에 대한 설명으로 틀린 것은?

스레드마다 고유한 페이지 테이블이 사용된다

 

6. 논리 주소를 물리 주소로 바꿀 때 사용되지 않는 것은?

PCB

 

7. 페이지 테이블에 대한 설명 중 틀린 것은?

페이지 테이블은 시스템 전체에 하나 있으며 커널 공간에 저장된다

 

8. 논리 주소를 물리 주소로 바꿀 때 사용되지 않는 것은?

PC 레지스터

 

9. 32비트 주소 체계에서 한 페이지의 크기가 4KB일 때, 논리 주소 0x98761234 번지는 몇 번째 페이지의 몇 번째 바이트에 대한 주소인가(정확한 답 사례 : 0x###페이지의 0x###바이트)

0x98761페이지의 0x234바이트

 

10. 페이징 기법과 세그먼테이션 기법을 비교한 것으로 틀린 것은?

세그먼테이션은 단편화가 적기 때문에 메모리 활용 면에서 페이징보다 우수하다

 

11. 페이지 테이블은 어디에 존재하는가?

메인 메모리

 

12. 페이징에서 프로세스의 논리 주소는?

① [페이지 번호]

---> 2번으로 수정

 

13. 32비트 주소 체계에서 한 페이지가 2KB일 때, 다음 32비트의 논리 주소는 몇 번째 페이지의 볓 번째 바이트에 대한 주소인가?

페이지 3의 15번째 바이트

 

14. 32비트 주소 체계에서 한 페이지의 크기가 4KB일 때, 다음 32비트의 논리 주소에 해당하는 물리 주소는(그림에서의 논리 주소와 프레임 번호는 16진수임)?

0x00022008

 

15. 페이징 메모리 관리 기법은 페이지 테이블로 인해 2가지 성능 이슈가 있다. 이 둘을 골라라?

페이지 테이블의 낭비

CPU의 메모리 액세스 시 2번의 물리 메모리 액세스로 인한 실행 속도 저하

 

16. TLB는 어떤 문제점을 해결하기 위한 것인가?

물리 메모리의 액세스 횟수

 

17. TLB는 일반적으로 어디에 존재하는가?

CPU 패키지의 MMU 장치 내에

 

18. TLB의 역할은 무엇인가?

물리 메모리의 빠른 액세스

 

19. TLB는 고가의 장치이므로 TLB 크기는 페이지 테이블의 약 1/1000 수준이다. 이렇게 적은 크기로 논리 주소를 물리주소로 바꾸는데 효율적인 이유는 무엇인가?

프로그램이 가진 참조의 지역성 때문이다. 참조의 지역성은 지금 참조된 프로그램의 코드나 데이터가 가까운 시간 내에 다시 참조되거나 지금 참조되는 메모리 번지에 가까운 번지가 가까운 시간 내에 다시 참조되는 경향성이다. 그러므로 최근에 참조한 페이지들의 프레임 번호를 TLB에 저장하여 기억하면 동일한 페이지들이 한 동안 계속 참조될 가능성이 높으며, 하나의 TLB 항목이 한 페이지에서의 반복된 참조 시에 활용되므로 많지 않은 개수의 TLB 항목으로도 주소 변환 시 충분한 TLB 히트율을 달성한다.

 

20. 역 페이지 테이블과 멀티레벨 페이지 테이블 기법은 페이지 테이블의 어떤 문제를 개선하기 위한 것인가

페이지 테이블의 낭비 개선

 

21. 역 페이지 테이블을 사용할 때 역 페이지 테이블의 항목은 어떻게 구성되는가?

[프로레스 번호, 페이지 번호]

생능출판사 명품 운영체제

 

본 연습문제들은 작성자 본인이 푼것이라 틀릴 수 도 있습니다.

 

[개념체크]

 

1. 컴퓨터 시스템에서 메모리 계층 구조를 이루는 근본 이유는 무엇인가?

CPU의 메모리 액세스 속도를 높이기 위해

 

2. 메모리 계층화가 성공적인 이유는?

참조의 지역성 때문

 

3. 메모리 계층 구조에서 가장 빠른 메모리는?

CPU 레지스터

 

4. 메모리 계층 구조를 구성하는 기억 장치들의 특징으로 틀린 것은?

용량이 클수록 속도도 빠르다

 

5. 다음 문장의 빈 곳에 보기 중에서 적절한 단어를 삽입하여 문장을 완성하라.

( 논리 주소 )는 개발자나 프로그램에서 사용하는 주소로 0번지부터 시작되고 연속된다. CPU는 ( 논리 주소 )를 ( 물리 주소 )로 변환하는 ( MMU )를 내장하고 있다. CPU의 PC(Program Counter) 레지스터에 들어 있는 주소는 ( 논리 주소 )이다. 시스템 버스를 통해 전달되는 주소는 ( 물리 주소 )이고 그 범위는 CPU ( 주소버스 )의 크기에 달려있다. 개발자나 응용프로그램에서는 작성된 코드의 ( 논리 주소 )는 알 수 있으나 ( 물리 주소 )는 알 수 없다.

 

6. 운영체제의 메모리 관리 목표에 해당하지 않는 것은?

메모리를 연속적으로 할당함으로써 프로세스의 실행 성능 향상

 

7. 논리 주소에 대해 잘못 설명한 것은?

CPU의 PC 레지스터에는 다음에 액세스할 명령의 주소가 들어 있는데 이 주소는 물리 주소이다

 

8. 물리 주소에 대한 설명으로 잘못된 것은?

커널 코드는 물리 주소만 사용한다. 왜냐하면 커널 코드의 빠른 실행을 위해 논리 주소를 물리 주소로 바꾸는 시간을 없애기 위해서 이다

 

9. 다음 프로그램은 C 언어에서 100바이트의 메모리를 동적 할당 받는 코드이다. 포인터 변수 p에는 동적 할당받은 메모리의 주소가 들어 있다. 포인터 변수 p에 들어 있는 주소는 무슨 주소인가?

int *p = (int*)malloc(100);

논리 주소

 

10. 다음 중 절대 주소 300번지는?

②  CPU 패키지를 통해 출력된 주소 300이 주소 버스를 타고 메모리 장치에 도달하였다

 

11. 비주얼 스튜디오를 이용하여 C 응용프로그램을 작성하고 컴파일하였다. 응용프로그램 내에 선언된 변수 n의 절대주소를 알 수 있는 존재는?

위의 어떤 것도 알 수 없다

 

12. 연속 메모리 할당이 분할 메모리 할당보다 나은 면은?

논리 주소와 물리 주소 사이의 매핑 과정이 단순하여 상대적으로 빠른 프로세스의 실행

 

13. 분할 메모리 할당은 연속 메모리 할당의 어떤 면을 개선하기 위한 것인가?

메모리에 빈 영역이 많이 산재되어 있음에도 불구하고 프로세스를 적재할 수 없는 메모리 할당의 경직성을 극복하기 위해

 

14. 다음 중내부 단편화가 발생하는 것을 모두 골라라?

페이징

고정 크기 연속 메모리 할당

 

15. 세그먼테이션과 페이징에 대해 잘못 설명한 것은?

세그먼테이션이나 페이징 모두 세그먼트 테이블과 페이지 테이블이 프로세스마다 1개씩 존재한다

 

16. 홀 선택 알고리즘 중 요청하는 메모리 크기를 수용하는 홀 (비어 있는 메모리 공간) 중 가장 작은 홀을 선택하는 알고리즘은 무엇인가?

best-fit

 

17. 홀 선택 알고리즘은 메모리의 홀(비어 있는 메모리 공간) 중에서 선택하여 요청된 메모리를 할당한다. 요청 크기와 홀의 크기가 같지 않는 경우 할당된 홀에 새로운 홀이 생기게 된다. 이 때 가장 큰 홀을 만들게 되는 알고리즘은 무엇인가?

worst-fit

 

18. 세그먼테이션 메모리 관리 기법에서 세그먼트 테이블의 항목은 어떤 정보로 구성되는가?

세그먼트의 크기와 세그먼트의 물리 주소

 

19. 세그먼테이션 메모리 관리 기법에서 세그먼트 테이블의 항목에는 세그먼트의 크기 정보가 저장된다. 이것은 어떤 목적으로 사용되는가?

CPU에 의해 발생된 논리 주소가 세그먼트가 할당된 무리 메모리의 영역을 넘어섰는지 판단하기 위해

 

20. 현대의 컴퓨터에서 CPU 패키지 안에 들어 있지 않는 것은?

SSD

생능출판사 명품 운영체제

 

본 연습문제들은 작성자 본인이 푼것이라 틀릴 수 도 있습니다.

 

[개념체크]

 

1. 젓가락과 숟가락이 하나씩만 있는 식탁에서 두 사람이 식사를 한다고 하자. 숟가락과 젓가락을 동시에 들어야 한 입 식사가 가능하며, 숟가락이든 젓가락이든 한 번에 하나 씩 들어야 한다. 한 개만 가진 사람은 나머지 한 개가 준비될 때까지 기다려야 한다. 한 입 식사 후 들고 있던 숟가락과 젓가락은 모두 내려놓으며, 둘은 대화할 수 없다고 할 때, 두 사람이 식사하는 동안 교착 상태가 발생하는 상황을 사례를 들어 설명하라. 

정상적으로 식사가 이루어 지려면 한명이 젓가락과 숟가락을 둘다 들고 식사를 마친후 다음 사람이 먹어야 하지만, 한 사람이 젓가락을 드는 동안 다른 사람이 숟가락을 들면 둘다 숟가락과 젓가락을 무한정 기다린다.

 

2. 식사하는 철학자 문제를 잘못 기술한 것은?

식사하는 철학자 문제는 공유 자원에 대한 멀티스레드의 스케줄링 문제이다

 

3. 식사하는 철학자 문제를 해결하는 방법으로 적합한 것을 있는 대로 골라라. 

철학자가하나의 포크를 들고 다른 포크를 1분 이상 기다릴 때, 두 포크를 놓고 잠시 생각한 뒤 다시 식사를 하면 해결된다

식당에 지배인을 두고 지배인이 포크를 대기하고 있는 척학자가 있을 때, 기다리는 포크를 가지고 1분 이상 식사하고 있는 옆 철학자의 포크를 뺏어 주면 된다

③  포크마다 번호를 매기고 포크가 필요할 때 번호 순으로 포크를 들게 하면 해결된다

 

4. 식사하는 철학자 문제가 단일 CPU에서도 발생할 수 있는가, 없는가?

단일 CPU 에서도 발생할 수 있다

 

5. 다음 문장의 빈 곳에 적절한 단어를 선택하여 문장을 완성하라.

컴퓨터 시스템에서 ( 교착상태 )는 deadly embrace라고도 불리는 것으로 ( 교착상태 )가 유발되는 4가지 필요충분조건은 ( 코프만 )에 의해 증명되었다. 그럼에도 불구하고 현재 거의 모든 컴퓨터 시스테멩서는 이를 무시하는 방법을 사용하고 있는데 이것을 ( 타조 ) 알고리즘이라고 부른다.

 

6. 코프만의 4가지 조건에 해당하지 않는 것은?

① 우선순위 역전

 

7. 다음 자원할당 그래프에 대한 설명으로 맞는 것은?

④ 자원할당 그래프는 자원을 할당하는 과정에서 만들어진다

 

8. 다음 자원 할당 그래프에 대한 설명으로 틀린 것은?

③ 현재 이 시스템에서 T4와 T5 사이에 교착상태가 발생하고 있다

 

9. 다음 자원 할당 그래프 중 교착상태를 나타내는 것은 있는 대로 골라라.

 

10. 코프만 조건은 어떤 문제에 관한 것인가?

 

11. 교착상태 무시 전략이 나오게 된 배경이 아닌 것은?

교착상태가 발생한다고 피해가 발생하는 것은 아니다

 

12. 교착상태 예반 전략의 이론적 배경은?

코프만 조건

 

13. 자원할당 그래프를 전혀 사용할 필요가 없는 교착상태 해결 전략은?

④ 교착상태 무시

 

14. 교착상태 관련 알고리즘 중 타조 알고리즘에 대한 설명을 틀린 것은?

교착상태가 의심되면 부팅하거나 의심가능 스레드 중 하나를 종료시키는 단순한 방법이다

 

15. 교착상태 해결 방법중 타조 알고리즘이 적합한 상황은?

개인용 PC

 

16. 교착상태 감지 및 복구와 관련된 방법이 아닌 것은?

② 모든 자원에 번호를 붙이고 각 스레드는 자원을 할당받을 때 작은 번호의 자원부터 할당받도록 함

 

17. 교착상태 감지 및 복구 방법에 대한 설명으로 틀린 것은?

③ 사용자나 시스템 관리자가 교착상태가 발생하였다고 생각되면 시스템을 재시작 시킨다

 

18. 교착상태에 대한 설명으로 옳은 것은?

② 교착상태는 몇 몇 스레드들 사이에서 발생하므로 이들만의 문제이지 시스템 전체의 문제는 아니다

 

19. 교착상태는 주로 어디에서 발생하는가?

① 사용자가 작성한 멀티스레드 응용프로그램의 스레드들 사이에

생능출판사 명품 운영체제

 

본 연습문제들은 작성자 본인이 푼것이라 틀릴 수 도 있습니다.

 

[개념체크]

 

1. 여러 스레드가 공유 변수를 접근하려고 경쟁할 때 공유 변수의 값이 훼손되는 상황이 발생할 수 있다. 공유 변수가 훼손되지 않도록 스레드 사이에 공유 변수에 대한 접근 시간과 방법 등을 조절하는 기법을 무엇이라고 하는가.

① 스레드 동기화

 

2. 멀티스레드가 동시에 공유 데이터를 접근할 때 데이터가 훼손되지 않도록 막는 기법의 핵심 정책은 무엇인가?

상호배제

 

3. 다음은 무엇에 대한 정의인가?

다수의 스레드로부터 공유 데이터의 훼손을 막기 위해 임계구역이 오직 한 스레드만 배타적 독점적으로 사용하도록 관리하는 기술

 상호배제

 

4. 원자명령(atomic instruction)이란?

① CPU 명령

 

5. Test and Set Lock 혹은 TSL 명령에 대한 설명이 틀린 것은?

스핀락

 

6. 다음 원자명령에 대한 설명으로 옳은 것은?

TSL ax, lock

 lock 변수 값을 ax 에 읽어오고 lock 변수에 1을 저장한다.

 

7. 원자명령과 가장 거리가 먼 것은?

④ 원자명령은 거의 모든 CPU에 있으며 CPU를 막론하고 이름이 동일하다

 

8. 임계구역에 대한 설명으로 틀린 것은?

 대부분의 운영체제는 임계구역에 진입할 때 다른 스레드가 진입하지 못하도록 인터럽트를 금지시키고, 나올 때 인터럽트를 허용하는 방법을 사용한다(오늘날에는 원자명령을 활용한다)

 

9. 멀티스레드의 동기화 기법 중 멀티코어 CPU를 가진 현대의 시스템에 적합한 것은?

스핀락

 

10. 멀티스레드의 동기화 기법 중 요청한 자원을 사용할 수 있을 때 까지 대기하는 큐를 사용하지 않는 방법은?

 스핀락

 

11. 임계구역의 실행 시간이 매우 짧을 경우에 적합한 멀티스레드의 동기화 기법은?

 스핀락

 

12. 커널 코드나 인터럽트 서비스 루틴 등에서 임계 구역에 접근할 때 멀티스레드 동기화를 위해 사용되는 기법은?

 스핀락

 

13. 멀티스레드 동기화 기법 중 오랜 시간 동안 공유 자원을 접근하지 못하는 기아가 발생할 수 있는 것은?

 스핀락

 

14. 멀티스레드의 동기화는 왜 필요한가?

② 여러 스레드가 동시에 동일한 변수를 읽고 쓸 때 발생하는 문제를 해결하기 위해

 

15. 다음 중 CPU 사용 시간을 심하게 낭비하는 것이 아닌 것은?

② sleep-waiting

 

16. 다음 중 동기화가 발생하는 공간에 대한 것 중 옳은 것은?

사용자 공간과 커널 공간 모두 동기화 필요

 

17. 우선순위 역전에 대한 설명 중 틀린 것은?

우선순위 역전은 낮은 순위의 스레드가 기아 상태에 빠지는 것을 막기 위한 매우 효율적인 방법이다

 

18. 공유 자원과 가장 거리가 먼 단어는?

N:1 매핑

 

19. 생산자 소비자 문제에 대해 잘 설명한 것은?

공유 버퍼를 사이에 두고 공유 버퍼에 데이터를 저장하는 스레드와 공유 버퍼로부터 데이터를 읽어가는 스레드 사이에 공유 버퍼에 대한 동시 접근 문제이다

 

20. 생산자 소비자 문제인 것은 모두 골라라.

① 마이크로부터 연속하여 들어오는 오디오 샘플을 큐에 넣는 스레드와 큐의 오디오 샘플을 스피커로 출력하는 스레드

③ 프린트할 파일이 생길 때 마다 큐에 넣은 스레드와 큐에 있는 파일을 프린터로 출력하는 스레드

 

21. pthread 라이브러리를 이용하여 작성된 다음 4개의 보기에 대해 물음에 답하라. 보기에서 worker() 함수는 스레드가 실행하는 코드이다.

(1) 보기 (1)에서 임계구역의 코드를 적어라. 

sum = sum + 10;

(2) worker()를 실행하는 10개의 스레드가 동시에 실행될 때 4개의 보기 중 가장 실행 속도가 느린 코드는? 

 

(3) worker()를 실행하는 10개의 스레드가 동시에 실행될 때 4개의 보기 중 가장 실행 속도가 빠른 코드는? 

(4) worker()를 10개의 스레드가 동시에 실행될 때 스레드 동기화가 실패할 가능성이 있는 코드는? 

 

22. 다음은 비디오 플레이어 응용프로그램의 구조를 간략히 묘사한 것이다. 물음에 답하라.

(1) 이 응용프로그램을 개발하기 위해서는 생산자 소비자 문제를 해결해야 한다. 생산자 소비자 문제는 생산자 스레드, 소비자 스레드, 스리고 공유 버퍼로 구성되는데 이들이 각각 그림의 어느 부분에 해당하는지 밝혀라.

생산자 스레드 = 입력스레드

소비자 스레드 = 재생스레드

공유버퍼 = 비디오 버퍼

(2) 이 응용프로그램에서 입력스레드와 재생스레드가 생산자와 소비자로서 비디오를 재생하는 과정을 간단히 설명하라.

입력스레드는 네트워크로 부터 한 프레임씩 읽어 비디오 버퍼에 저장하는 일을 반복하고, 재생스레드는 비디오 버퍼에 도착하는 프레임을 읽고 디코딩하여 디스플레이에 출력하는 작업을 반복한다.

 

[복합 문제]

 

1. 응용프로그램 개발자는 어떤 코드를 임계구역으로 설정해야 하는가?

공유 데이터를 액세스하는 코드 블록을 임계구역으로 묶고, 임계구역에 대한 상호배제가 이루어지도록 작성해야 한다.

 

2. 다음 코드는 lock 변수를 이용하여 임계구역에 멀티스레드의 상호배제를 이루려고 한다. lock은 0이나 1 값을 가지는 변수이다. 질문에 답하라.

1       loop:
2                mov ax, lock
3                mov lock, 1
4                cmp ax, 0
5                jne loop
6                --------------
---             임계구역
100            --------------
101            mov lock, 0

(1) lock 변수의 역할은 무엇인가? 임계구역에 들어갈때 변수에 1을 쓰고 나올때 0을 쓴다. 1일때는 임계구역에 들어갈수 없다.

(2) 스레드 A가 임계구역의 코드를 실행하다 중단된 경우, 스레드 B가 1번 라인부터 실행하게 되면 스레드 B는 어떤 코드를 실행하게 되는가? lock 변수가 1이라 임계구역으로 들어가지 못하고 loop으로 돌아가 lock 이 0이 될 때까지 lock 변수를 읽고 0과 비교하는 코드를 반복 실행한다. 

(3) 이 코드는 임계구역에 대한 상호배제를 이룰 수 있는 코드인가? 상호배제에 실패하는 코드인가? 실패하는 코드이다.

(4) 질문 (3)의 이유를 설명하라. 만약 스레드 A 가 먼저 lock 변수 값 0을 ax로 읽은 후 스레드 B 로 컨텍스트 스위칭이 되고, 스레드 B 가 lock 변수를 읽고 lock변수를 1로 변경하고 임계구역에 진입후 임계구역 내에서 스레드 A 로 컨텍스트 스위칭이 일어난다면 스레드 A 와 B 둘다 임계구역에 있는 충돌 상황이 발생한다.

(5) 만일 질문 (3) 에서 상호배제가 실패하는 코드라면, 상호배제가 성공하도록 해결 방법을 제시하라. 상호배제가 실패하게 만드는 원인인 mov ax, lock 와 mov lock, 1 을 두개로 합치면 된다.

 

 

 

생능출판사 명품 운영체제

 

본 연습문제들은 작성자 본인이 푼것이라 틀릴 수 도 있습니다.

 

[개념체크]

 

1. 다음 빈 칸에 적절한 단어를 삽입하라.

프로그램의 실행 과정은 두 가지 상황이 번갈아 진행되는데, 그것은 한동안 CPU 연산이 계속되는 ( CPU burst ) 상황과, I/O 작업이 이루어지는 ( I/O burst ) 상황이다. CPU 연산이 주를 이룰 때 ( CPU 집중 ) 프로세스라고 부르고 I/O 작업이 주를 이룰 때 ( I/O 집중 ) 프로세스라고 한다. CPU 스케줄링은 CPU의 ( idle ) 시간을 줄이기 위해 도입되었다.

 

2. CPU 스케줄링 알고리즘을 평가하는 기준과 거리가 먼 것은?

동시성(cocurrency)

 

3. CPU 스케줄링의 평가 기준 사이의 관계를 잘못 설명한 것은?

시스템 정책 우선으로 스케줄링하면 CPU 활용률은 높아진다

 

4. CPU 스케줄링이 행해지는 상황들을 나열하였다. 비어 있는 상황을 적어라.

첫째, 스레드에게 할당된 CPU 타임 슬라이스가 소진되었을 때

둘째, 스레드가 자발적으로 CPU를 반환하는 경우

셋째, 현재 실행중인 스레드보다 더 높은 순위의 스레드로부터 내려진 입출력이 완료되어 I/O 인터럽트가 발생한 경우

넷째, 스레드가 I/O를 요청하는 시스템호출을 실행하여 블록 상태가 되거나, 자원을 기다리는 상태가 될때, 다른 스레드에게 CPU를 할당하는 경우

 

5. 타임 슬라이스에 대한 설명으로 틀린 것은?

④ 타임 슬라이스가 클수록 컨텍스트 스위칭의 횟수가 증가한다

 

6. 선점과 비선점 중 선택하여 빈 칸을 채워라

스레드가 CPU를 할당받아 일단 실행을 시작하면 완료되거나 CPU를 더 이상 사용할 수 없는 상황이 될 때까지 스레드를 강제로 중단시키지 않는 방식을 ( 비선점 ) 스케줄링이라고 하며, 커널이 현재 실행 중인 스레드를 강제로 중단시켜 준비 리스트로 이동시키고, 스케줄링을 통해 다른 스레드에게 CPU를 넘겨주는 방식을 ( 선점 ) 스케줄링 이라고 한다. ( 비선점 ) 스케줄링의 경우, 스레드가 더 이상 CPU를 사용할 수 없는 상황에야 비로소 스케줄링이 이루어 진다. PC와 같은 범용 시스템에서 ( 비선점 ) 스케줄링은 현재는 거의 사용되고 있지 않다.

 

7. 다음 스케줄링이 선점 스케줄링인지 비선점 스케줄링인지 표기하라.

(1) 선입 선처리 (FCFS) - 비선점

(2) 최단 작업 우선 스케줄링 (SJF) - 비선점

(3) 최소 잔여 시간 우선 스케줄링 (SRTF) - 선점

(4) 라운드 로빈 스케줄링 (RR) - 선점

 

8. 다음 그림은 3개의 프로세스 p1, p2, p3이 실행되는 과정을 보여준다. 선점 스케줄링과 비선점 스케줄링 중 어떤 것이 사용되었는지 판단하고 그 이유를 설명하라.

비선점 스케줄링이다. T1이 시작하면 종료하기 전 까지 스케줄링이 이루어지지 않으며, T1이 종료될때 스케줄링이 이루어져 T2가 실행된다. T2의 실행 중 I/O가 발생하면 T2를 중단시키고 스케줄링을 실행하여 T3를 선택한다. T3이 실행 중 yield()를 호출하면 준비상태인 T2를 스케줄링하고 실행시킨다. T2가 끝날때 다시 스케줄링이 이루어져 T3이 실행된다

 

9. 다음은 무엇에 대한 설명인가?

스케줄링 과정에서 선택되지 못한 채 오랫동안 준비 리스트에 있는 상황

기아

 

10. 다음은 무엇에 대한 설명인가?

스레드가 준비 리스트에 머무르는 시간에 비례하여 우선수위를 높여주는 기법

에이징(aging)

 

11. 다음은 무엇에 대한 설명인가?

프로세스나 스레드가 특정 CPU에서 실행되도록 제한하는스케줄러의 특징

CPU 친화성 ( CPU affinity )

 

12. 에이징(aging) 기법은 CPU 스케줄링의 어떤 단점을 극복하기 위한 정책인가?

기아발생

 

13. RR(Round Robin) 스케줄링을 사용할 때 오늘날 합리적인 타임 슬라이스로 적합한 것은?

50 밀리초(20~120밀리초가 적당)

 

14. 스레드가 종료할 때 비로소 새 스레드를 스케줄한다면 이 운영체제는 선점 스케줄링을 하는가 아니면 비선점 스케줄링을 하는가?

비선점 스케줄링

 

15. 다음은 에이징을 설명하는 문장이다. 빈 칸에 적절한 단어는 무엇인가?

스레드가 준비 리스트에 머무르는 시간에 비례하여 스레드의 (           )을/를 높이는 기법이다.

우선순위

 

16. 다음 CPU 스케줄링 알고리즘 중에서 실현성이 없는 것은?

SJF (실행시간 예측 불가능)

 

17. 다음 중 모든 스레드에게 CPU를 가장 공평하게 나누어 주는 스케줄링 기법은?

① RR

 

18. 다음 중 기아 발생 가능성이 가장 큰 CPU 스케줄링은?

SJF

 

19. 다음 중 기아가 전혀 발생하지 않는 CPU 스케줄링은?

RR

 

20. 어떤 연구소에서 컴퓨터 시스템 사용자들을 책임연구원, 연구원, 연구 보조원의 3 그룹으로 나누어 놓고 각 사용자들이 생성된 프로세스나 스레드의 우선순위를 다르게 매기려고 한다. 가장 적절한 CPU 스케줄링은 무엇인가?

MLQ

 

21. RR(Round Robin) 스케줄링에서 스레드에게 할당하는 타임 슬라이스의 크기에 관한 설명 중 틀린 것은?

타임 슬레이스가 클수록 더 균등한 알고리즘이 된다

 

22. MLFQ(Multi-Level Feedback Queue) 스케줄링에 대한 설명으로 옳은 것은?

스레드의 기아를 막기 위해 큐에 대기하는 시간이 오래되면 위 레벨의 큐로 이동시킨다

 

23. 단일 코어 CPU와 달리 멀티 코어 CPU에서 스케줄링할 때 특별히 고려할 사항과 거리가 가장 먼 것은?

타임 슬라이스

 

24. 코어 친화성 혹은 CPU 친화성과 관계가 깊은 것은?

캐시

 

25. 멀티 코어 CPU를 가진 시스템에서 CPU 스케줄링 알고리즘은 스레드를 어떤 코어에서 실행시킬 것인지에 따라 컨텍스트 스위칭 후 오버헤드가 달라진다고 한자.

(1) 구체적으로 어떤 오버헤드가 문제인가? 일반적으로 코어는 내부의 CPU 캐시를 가지고 있다. 캐시에는 현재 실행중이거나 이전에 실행되었던 스레드 코드와 데이터가 적재되어 있다. 만일 스레드가 한 코어에서 실행되다가 중단된 후 동일한 코어에서 다시 실행된다면 코어 내부의 캐시에 스레드 코드와 데이터가 그대로 남아있을 가능성이 높기 때문에 메모리로부터 스레드 코드와 데이터를 적재할 가능성이 상대적으로 낮다. 하지만, 만일 스케줄된 스레드가 다른 코어에서 실행되도록 스케줄 되었다면 메모리로부터 스레드 코드와 데이터가 스케줄된 코어 내부의 캐시로 적재되어야 한다. 스레드를 어떤 코어에 할당하느냐에 따라 컨텍스트 스위칭의 오버헤드가 달라진다.

(2) 이 오버헤드를 줄일 수 있는 해결책은 무엇인가? 스레드가 특정 코어에서만 실행되도록 스케줄링을 제한하도록 하면 된다. 이것은 CPU 친화성 혹은 코어 친화성이라고 한다.

 

26. 멀티 코어 CPU를 가진 시스템에서 스케줄링이 잘못되면 한 코어에만 스레드가 몰리고 다른 코어는 놀게 되는 현상이 나타난다. 이러한 현상을 무엇이라고 부르고 그 해결책은 무엇인가?

코어 부하 불균형 현상. 해결책 : 푸시 마이그레이션 기법, 폴 마이그레이션 기법

생능출판사 명품 운영체제

 

본 연습문제들은 작성자 본인이 푼것이라 틀릴 수 도 있습니다.

 

[개념체크]

 

1. 스레드가 도입된 배경으로 프로세스의 문제점을 잘못 설명한 것은?

④ 프로세스 스케줄링의 복잡성을 줄이려 했다

 

2. 프로세스와 스레드의 관계에 대한 설명으로 틀린 것은?

③ 프로세스는 자신에게 속한 모든 스레드의 부모이다

 

3. 멀티태스킹 프로그램을 작성하는데 있어서 각 태스크를 프로세스로 만드는 것과 스레드로 만드는 방법 중 스레드로 만드는 방법이 유리한 이유로 맞는 것은?

② 프로세스들은 주소 공간이 완전히 분리되어 있어 공유 공간을 만들기 위해 운영체제의 도움을 받아야 하지만, 멀티스레드를 이용하는 경우 프로세스 내에 공유 변수 등을 통해 쉽게 통신할 수 있기 때문이다

 

4. 스레드에 관한 정보를 저장하는 구조체를 무성이라고 부르는가?

TCB

 

5. 다음 중 다른 한가지는?

TLS(Thread Local Storage)

 

6. 다음 중 프로세스와 스레드 중 선택하여 문장을 완성하라.

운영체제의 실행 단위는 ( 스레드 ) 이며, ( 프로세스 ) 는 ( 스레드 ) 들이 공유하는 환경을 제공한다. ( 프로세스 ) 들은 각각 독립적인 메모리  공간에서 실행되므로 ( 프로세스 ) 사이에 데이터를 주고받는데 심각한 어려움이 있다. 응용프로그램을 실행시키기 위해 운영체제는 ( 프로세스 ) 를 만든다. 하나의 ( 프로세스 ) 가 실행되면 반드시 한 개의 ( 스레드 ) 가 자동으로 만들어지고 이것은 ( 스레드 ) 라고 부른다. 하나의 ( 프로세스 ) 는 여러 개의 ( 스레드 ) 를 가질 수 있다. ( 프로세스 ) 가 실행중이라는 뜻은 ( 프로세스 ) 속한 ( 스레드 ) 중 한 개의 ( 스레드 ) 가 현재 CPU에 의해 실행되고 있음을 뜻한다. 그러므로 운영체제 스케줄러에 의해 스케줄되는 단위는 ( 스레드 ) 이며, ( 프로세스 ) 에 속한 모든 ( 스레드 ) 가 종료할 때 ( 프로세스 ) 도 종료된다.

 

7.  다음 설명은 concurrency와 paralleism 중 어떤 것인지 선택하라.

(1) 1개의 CPU가 여러 스레드를 번갈아 실행할 때 cocurrency

(2) 2개의 CPU에서 2개의 스레드가 각각 동시에 실행될 때 paralleism

(3) CPU가 스레드의 입출력으로 인해 유휴(idle) 상태에 있지 않고 다른 스레드를 실행할 때 cocurrency

(4) 멀티 코어 CPU가 여러 스레드를 같은 시간에 동시에 실행할 때 paralleism

 

8. 다음 그림은 스레드 T1, T2, T3 가 실행되는 과정을 보여준다. cocurrency인가, parallelism인가?

cocurrency 이다

 

9. 스레드가 활동하는 코드, 데이터, 힙, 스택은 어떤 메모리 공간에 형성되는가?

스레드가 속한 프로세스 주소 공간 내에

 

10. 스레드의 주소 공간에 대한 설명으로 틀린 것은?

스레드 코드는 프로세스의 공간 밖에 별도의 공간에 적재된다

 

11. 스레드 로컬 스토리지(TLS)란 어떤 메모리 공간인가?

① 다른 스레드가 접근할 수 없는 스레드만의 사적인 공간이다

 

12. 스레드 A가 malloc(100)을 이용하여 동적 할당받은 100바이트 공간에 대해 틀리게 설명한 것은?

스레드 A가 종료할 때 할당받은 100바이트 공간은 자동 반환되지 않는다

 

13. TCB에 저장되는 내용이 아닌 것은?

스레드 크기

 

14. TCB에 저장되는 내용이 아닌 것은?

스레드 시작 시간

 

15. 다음 중 스레드 스케줄링이 일어나는 시점이 아닌 것은?

스레드가 시스템 호출을 하여 커널로 진입한 직후

 

16. 프로세스 컨텍스트 스위칭과 스레드 컨텍스트 스위칭을 비교하여 잘 설명하지 못한 것은?

프로세스 컨텍스트 스위칭이 개념적으로 스레드 컨텍스트 스위칭보다 단순하다

 

17. 스레드 운용에 관한 설명 중 틀린 것은?

스레드가 종료되면 스레드가 속한 프로세스도 종료된다

 

18. 스레드 라이브러리에 포함된 것이 아닌 것은?

스레드에서 파일을 여는 함수

 

19. 커널 레벨 스레드의 정의는 무엇인가?

커널에 의해 스케줄되는 스레드

 

20. 사용자 레벨 스레드의 정의는 무엇인가?

스레드 라이브러리에 의해 스케줄되는 스레드

 

21. 사용자 레벨 스레드의 장점이 아닌 것은?

여러 스레드가 각 코어에서 동시에 실행될 수 있기 때문에 멀티 코어 CPU를 가진 시스템에 적합하다

 

22. 커널 레벨 스레드의 장점은?

여러 스레드가 각 코어에서 동시에 실행될 수 있기 때문에 멀티 코어 CPU를 가진 시스템에 적합하다

 

23. 최근 들어 운영체제는 사용자가 만든 스레드를 커널 레벨 스레드로 구현하는 추세이다. 그 이유는 무엇인가?

① 응용프로그램에서 생성한 각 스레드를 멀티 코어 CPU에 할당하여 응용프로그램 실행에 높은 병렬성을 얻을 수 있기 때문

 

24. N개의 사용자 레벨 스레드를 1개의 커널 레벨 스레드로 매핑하는 N:1 매핑의 최대 단점은 응용프로그램에 속한 한개의 사용자 레벨 스레드가 입출력을 수행하여 볼륵 상태가 되면 응용프로그램 내의 다른 모든 사용자 레벨 스레드가 스케줄(실행)될 수 없다는 점이다. 이 과정을 자세히 설명하라.

사용자 레벨 스레드가 입출력을 수행하여 커널 레벨 스레드가 Blocked 상태가 되면 N:1 매핑이기 때문에 다른 사용자 레벨 스레드가 있음에도 불구하고 응용프로그램 전체가 중단된다. Blocked 상태가 되면 CPU 코어가 다른 커널 레벨 스레드를 할당해 다른 작업을하다 Blocked 상태가 Ready 상태로 바뀌어 커널 스케줄러에 의해 스케줄될 때 까지 기다려야한다.

 

25. 사용자 레벨 스레드와 커널 레벨 스레드의 매핑 기법으로 최근에 가장 많이 사용하는 것은?

② 1:1

 

26. 사용자 레벨 스레드와 커널 레벨 스레드의 매핑 기법으로 1:1 기법을 현재 가장 많이 사용하는 이유는?

매핑 개념이 단순하여 구현하기쉽다. 높은 병렬성을 제공하기 때문에 멀티프로세서를 가진 현대의 컴퓨터 시스템에 매우 적합하다. N:1 모델과 달리, 사용자 레벨 스레드 중 하나가 시스템 호출 중 블록 상태가 되어도, 응용프로그램 내 다른사용자 레벨 스레드는 여전히 스케줄링 가능하므로 응용프로그램 전체가 중단되는 일은없다. N:M 모델은 매핑과 스케줄링 과정이 복잡하여 현대의 운영체제에서는 거의 사용하지 않는다.

 

 

[복합 문제]

 

1. 그림 4-5의 맛보기 프로그램을 참고하여, 리눅스에서 다음 5가지 조건에 부합하느 멀티스레드 C 응용프로그램을 작성하라. 4개의 스레드를 활용하여 1에서 40000까지의 합을 구하여 출력한다.

(1) pthread 라이브러리를 이용하여 작성하라.

(2) 응용프로그램에 0으로 초기화된 전역 변수 int sum[4]를 선언하라.

(3) 스레드로 실행할 함수의 이름을 runner로 하라.

(4) main()에서 pthread_create() 함수를 활용하여 4개의 스레드를 연속적으로 생성하여 4개의 스레드를 동시에 실행시켜라.

- 스레드 1 : 1~10000 까지의 합을 구하고 sum[0]에 저장
pthread_create(... ... runner,"1"); //1에서 10000까지 합 구하기
- 스레드 2 : 10001~20000 까지의 합을 구하고 sum[1]에 저장
pthread_create(... ... runner,"10001"); //10001에서 20000까지 합 구하기
- 스레드 3 : 20001~30000 까지의 합을 구하고 sum[2]에 저장
pthread_create(... ... runner,"20001"); //20001에서 30000까지 합 구하기
- 스레드 4 : 30001~40000 까지의 합을 구하고 sum[3]에 저장
pthread_create(... ... runner,"30001"); //30001에서 40000까지 합 구하기

(5) main()은 4개의 스레드가 모두 종료하기를 기다린 후 sum[] 배열의 값을 모두 합쳐 그 결과를 화면에 출력하라. 다음은 이 프로그램의 이름이 prac4_1.c라고 할 때 컴파일 과정과 실행 결과를 보여준다.

$ gcc -o prac4_1 prac4_1.c -lpthread
$ ./prac4_1
1에서 40000까지 4개의 스레드가 계산한 총 합은 800020000
$

 

 

#include <pthread.h> // pthread 라이브러리를 사용하기 위해 필요한 헤더 파일 
#include <stdio.h>
#include <stdlib.h>

void* runner(void *param); // 스레드로 작동할 코드(함수) 
int total = 0; // main 스레드와 runner가 공유하는 전역 변수  
int sum[4] = { 0 };
int j = 0;
int main() {
        pthread_t tid1; //  스레드의 id를 저장할 정수형 변수 
        pthread_t tid2; //  스레드의 id를 저장할 정수형 변수 
        pthread_t tid3; //  스레드의 id를 저장할 정수형 변수 
        pthread_t tid4; //  스레드의 id를 저장할 정수형 변수 
        pthread_attr_t attr; // 스레드 정보를 담을 구조체 

        pthread_attr_init(&attr); // 디폴트 값으로 attr 초기화 
        pthread_create(&tid1, &attr, runner, "1"); // runner 스레드 생성
        pthread_create(&tid2, &attr, runner, "10001"); // runner 스레드 생성 
        pthread_create(&tid3, &attr, runner, "20001"); // runner 스레드 생성 
        pthread_create(&tid4, &attr, runner, "30001"); // runner 스레드 생성 
	// 스레드가 생성된 수 커널에 의해 언젠가 스케줄되어 실행 
        pthread_join(tid1, NULL); // tid 번호의 스레드 종료를 기다림
        pthread_join(tid2, NULL); // tid 번호의 스레드 종료를 기다림 
        pthread_join(tid3, NULL); // tid 번호의 스레드 종료를 기다림 
        pthread_join(tid4, NULL); // tid 번호의 스레드 종료를 기다림 
        for (int i = 0; i < 4; i++) {
            total += sum[i];
        }
	printf("1에서 40000까지 4개의 스레드가 계산한 총 합은 %d\n", total);
}

void* runner(void *param) { // param에 "값" 전달 
        int to =  atoi(param); // to = "값"
        int tmp = 0;
        total = 0;
        for (int i = to; i <= to + 9999; i++) { // to에서 to+9999까지 합계산 
            tmp += i;
        }
        sum[j] += tmp;
        j++;
}

 

2. 앞의 문제 1을 수정하여 리눅스에서 5가지 조건에 부합하는 멀티스레드 C 응용프로그램을 작성하라. 4개의 스레드를 활용하여 1에서 40000까지의 합을 구하여 출력한다.

(1) pthread 라이브러리를 이용하여 작성하라

(2) 응용프로그램에 전역 변수 int sum을 선언하고 0을 초기화하라.

(3) 스레드로 실행할 함수의 이름은 runner로 하라

(4) main에서 pthread_create() 함수를 활용하여 4개의 스레드를 연속적으로 생성하여 4개의 스레드를 동시에 실행시켜라.

- 스레드 1 : 1~10000 까지의 합을 구하고 sum에 합산
pthread_create(... ... runner,"1"); //1에서 10000까지 합을 sum에 합산
- 스레드 2 : 10001~20000 까지의 합을 구하고 sum에 합산
pthread_create(... ... runner,"10001"); //10001에서 20000까지 합을 sum에 합산
- 스레드 3 : 20001~30000 까지의 합을 구하고 sum에 합산
pthread_create(... ... runner,"20001"); //20001에서 30000까지 합을 sum에 합산
- 스레드 4 : 30001~40000 까지의 합을 구하고 sum에 합산
pthread_create(... ... runner,"30001"); //30001에서 40000까지 합을 sum에 합산

(5) main은 4개의 스레드가 모두 종료하기를 기다린 후 sum 값을 화면에 출력하라. 다음은 이 프로그램의 이름이 prac4_2.c라고 할 때 컴파일 과정과 여러 번의 실행결과를 보여준다. ( 실행결과가 실행할 때 마다 달라진다. )

$ gcc -o prac4_2 prac4_2.c -lpthread
$ ./prac4_2
1에서 40000까지의 스레드가 합친 sum 변수의 값은 583862451
$ ./prac4_2
1에서 40000까지의 스레드가 합친 sum 변수의 값은 640209990
$ ./prac4_2
1에서 40000까지의 스레드가 합친 sum 변수의 값은 500849160
$

1에서 40000까지의 합은 문제 1의 결과에 따라 800020000인데, 앞의 결과 화면에는 80020000가 출력되지 않는다. 여러 번 실행해도 계속 다른 값이 출력된다. 그 이유는 무엇인지 나름대로 설명해보라.

#include <pthread.h> // pthread 라이브러리를 사용하기 위해 필요한 헤더 파일 
#include <stdio.h>
#include <stdlib.h>

void* runner(void *param); // 스레드로 작동할 코드(함수) 
int total = 0; // main 스레드와 runner가 공유하는 전역 변수  
int sum = 0;
int main() {
        pthread_t tid1; //  스레드의 id를 저장할 정수형 변수 
        pthread_t tid2; //  스레드의 id를 저장할 정수형 변수 
        pthread_t tid3; //  스레드의 id를 저장할 정수형 변수 
        pthread_t tid4; //  스레드의 id를 저장할 정수형 변수 
        pthread_attr_t attr; // 스레드 정보를 담을 구조체 

        pthread_attr_init(&attr); // 디폴트 값으로 attr 초기화 
        pthread_create(&tid1, &attr, runner, "1"); // runner 스레드 생성
        pthread_create(&tid2, &attr, runner, "10001"); // runner 스레드 생성 
        pthread_create(&tid3, &attr, runner, "20001"); // runner 스레드 생성 
        pthread_create(&tid4, &attr, runner, "30001"); // runner 스레드 생성 
	// 스레드가 생성된 수 커널에 의해 언젠가 스케줄되어 실행 
        pthread_join(tid1, NULL); // tid 번호의 스레드 종료를 기다림
        pthread_join(tid2, NULL); // tid 번호의 스레드 종료를 기다림 
        pthread_join(tid3, NULL); // tid 번호의 스레드 종료를 기다림 
        pthread_join(tid4, NULL); // tid 번호의 스레드 종료를 기다림 
	printf("1에서 40000까지 4개의 스레드가 계산한 총 합은 %d\n", sum);
}

void* runner(void *param) { // param에 "값" 전달 
        int to =  atoi(param); // to = "값"
        total = 0;
        for (int i = to; i <= to + 9999; i++) { // to에서 to+9999까지 합계산 
            sum += i;
        }
}

스케줄링에 의해 4개의 스레드가 실행되는 순서가 계속 달라지기 때문에 매번 값이 달라진다.

생능출판사 명품 운영체제

 

본 연습문제들은 작성자 본인이 푼것이라 틀릴 수 도 있습니다.

 

[개념체크]

 

1. 다음글에서 프로세스와 프로그램 중에서 선택하라.

( 프로그램 ) 은 컴파일되어 실행 가능한 형태로 저장 장치에 저당된 상태일 때 부르는 용어이며, ( 프로세스 ) 는 메모리에 적재되어 실행 중인 상태일 때 부르는 용어이다

 

2. 프로세스의 특징을 설명한 것 중 맞는것은?

프로세스를 스케줄링 하는 것은 커널 기능이다

 

3. 프로세스에 대한 설명으로 틀린 것은?

동일한 프로그램이 실행되어 생성된 프로세서는 항상 동일한 프로세스 번호를 할당받는다.

 

4. PCB에 들어 있는 정보가 아닌 것은?

④ 프로세스 이름

 

5. 프로세스의 종료코드는 어디에 저장되는가?

프로세스의 PCB

 

6. 프로세스가 종료될 때, 커널이 프로세스 테이블 항복이나 PCB를 즉각 삭제하지 않는 이유는 무엇인가?

프로세스 종료코드를 부모 프로세스가 읽어갈 때까지 기다리기 위해

 

7. 32비트 CPU에 대해 다음에 답하여라.

(1) CPU의 주소선 개수는? 32개

(2) CPU가 액세스 가능한 메모리의 최대량은? 4GB

(3) 이 CPU를 사용할 때 프로세스의 주소 공간 크기는? 4GB

 

8. 프로세스의 주소 공간에 대한 설명으로 맞는 것은?

프로세스가 실행되는 동안 접근할 수 있는 메모리의 최대 범위이다.

 

9. 프로세스가 메모리에 적재될 때 프로세스를 구성하는 4개의 영역은 무엇인가?

코드 영역, 데이터 영역, 힙 영역, 스택 영역

 

10. 운영체제는 프로세스를 코드, 데이터, 힙, 스택의  4 영역으로 구성한다. 다음은 어느 영역에 형성되는가?

(1) 전역 변수 : 데이터 영역

(2) 지역 변수 : 스택 영역

(3) C++에서 new 연산자나 C 프로그램에서 malloc() 함수를 호출하여 할당받은 메모리 : 힙 영역

(4) 사용자가 작성한 함수 코드 : 코드 영역

(5) 라이브러리에 작성된 함수 코드 : 코드 영역

(6) 라이브러리 함수에 선언된 지역 변수들 : 스택 영역

 

11. 프로세스가 적재된 이후 실행 과정 동안 크기가 변하지 않는 영역을 있는 대로 골라라.

코드 영역,데이터 영역

 

12. printf()는 C 프로그램에서 화면 출력을 위해 사용되는 C 표준 라이브러리 함수이다. 다음 질문에 답하라.

(1) printf() 함수의 코드는 프로세스의 코드 영역에 포함되는가? 포함된다

(2) printf() 함수 내에 선언된 지역 변수들은 프로세스의 어느 영역에 포함되는가? 스택 영역

(3) printf() 함수의 코드와 지역 변수들은 사용자 공간에 적재되는가, 커널 공간에 적재되는가? 사용자 공간에 적재된다.

 

13. 프로세스의 주소 공간은 0번지부터 시작되어 연속적인 번지로 이루어진다. 만일 3개의 프로세스가 메모리에 적재된채 동시에 실행된다고 하면, 모든 프로세스가 0번지에서 시작하므로, 프로세스들 사이에 번지 충돌이 발생하고 메모리 충돌이 발생할 것 같다. 운영체제는 어떻게 이 문제를 해결하는가?

매핑테이블을 이용해 가상 메모리와 물리 메모리를 연결해 관리한다

 

14. 프로세스 스케줄링에는 어떤 상태의 프로세스들이 대상이 되는가?

Ready 상태

 

15. 커널은 현재 실행 중인 프로세스가 입출력을 요청하면 어떤 상태로 전이시키는가?

Blocked 상태

 

16. 프로세스는 실행 중 다음 각 경우에 어떤 상태로 바뀌는가?

(1) yield() 시스템 호출을 불러 스스로 실행을 중단하고 다른 프로세스에게 양보할 때 : Ready 상태

(2) sleep(1) 시스템 호출을 불러 1초 동안 잠을 잘 때 : Blocked 상태

(3) exit(-1) 시스템 호출을 불러 종료할 때 : Terminated/out 상태

(4) 프로세스에게 할당된 타임 슬라이스가 다 되었을때 : Ready 상태

 

17. PCB 내에 프로레스가 열어 놓은 파일에 관한 정보가 저장되는 것으로 미루어 다음 중 틀리게 설명한 것은?

한 프로세스가 열어 놓은 파일을 다른 프로세스가 입출력할 수 있다

 

18. 다음 중 자식 프로세스를 생성하는데 사용되는 시스템 호출은?

fork()

 

19. wait() 시스템 호출에 대해 잘 설명한 것은?

자식 프로세스가 종료할 때까지 대기한다

 

20. 부모 프로세스가 wait() 시스템 호출을 부르기 전, 자식 프로세스가 먼저 종료할 때 상황에 맞게 설명된 것은?

커널은 자식 프로세스를 좀비 프로세스로 만든다

 

21. 좀비 상태의 프로세스에 대한 설명 중 틀린 것은?

좀비 프로세스는 시스템의 성능을 심각하게 떨어뜨린다

 

22. 유닉스 계열의 운영체제에서 #1 프로세스를 무엇이라고 부르는가?

swapper

 

23. 유닉스 계열의 운영체제에서 모든 사용자 프로세스의 조상은 누구인가?

#1 init 프로세스

 

24. Windows에서 #0 프로세스인 시스템 유휴 프로세스(system idle process)나 리눅스의 #0 idle 프로세스의 역할은 무엇인가?

모든 프로세스가 블록 상태여서 시스템에 실행시킬 Ready 상태의 프로세스가 1개도 없는 상황에 빠지지 않도록 하기 위해서이다

 

25. 다음은 어떤 프로세스를 설명하는지 적어라.

(1) 부모 프로세스가 먼저 종료한 자식 프로세스 : 고아 프로세스

(2) 종료할 때 종료코드를 남겨 놓았지만 부모 프로세스가 읽어가지 않고 있을 때, 종료한 자식 프로세스 : 좀비 프로세스

(3) 입출력 작업이 계산 작업보다 월등히 많은 프로세스 : I/O 집중 프로세스

(4) 계산 작업이 입출력 작업보다 월등히 많은 프로세스 : CPU 집중 프로세스

(5) 사용자와 대화가 필요하지 않고 낮는 우선순위로 실행되는 프로세스 : 백그라운드 프로세스

 

26. 시스템에 무한히 많은 프로세스가 생성되지 못하는 이유가 구체적으로 무엇일까?

시스템에 과부하가 올 수도 있고 최악의 경우 너무 많은 프로세스가 존재하면 새로운 프로세스를 생성할 수 없는경우도 발생할 수 있기 때문이다

 

27. main()에서3을 리턴하는 three라는 C 프로그램을 작성하였다. 쉘에서 다음과 같이 실행시키면, main()에서 리턴한 값 3은 누구에게 전달되는가?

$ ./three
$

 

28. 종료코드의 목적은 무엇인가?

프로세스가 어떤 상태로 종료함을 부모 프로세스에게 전달하기 위해

 

[복합문제]

 

1. 다음 C 프로그램을 실행하면 오류가 발생하지는 않는다. 하지만 잘못 작성되었다고 의심되는 부분이 있다. 이를 지적하고 이유를 설명하라.

#include <stdio.h>

int main(){
   printf("I am a child\n");
   return 300;
}

return 0 을 해야 올바르게 종료를 한다. 종료코드는 0이기 때문이다.

 

※[2~3] 다음 C 프로그램에 대해 물음에 답하라. 헤더 파일은 생략하였다.

int a=10;
int main(){
	int b=20;
    int* p = (int*)malloc(100);
    f();
    printf("%d",b)
    return -1;
}
void f(){
	int c=30;
    printf("%d",c);
}

2. main() 함수의 return -1; 에서 -1을 무엇이라고 부르는가? exit(-1)로 해도 같은 의미인가? 누구에게 전달하려고 리턴하나? 이 값을 받은 프로그램이 받은 값을 양수로 출력하면 얼마가 출력될 것인가?

main() 함수의 return -1; 에서 -1은 종료코드이다.

exit(-1)해도 같은 의미이다.

부모 프로세스에게 전달하기위해 리턴한다.

양수로 출력하려면 255이다.

종료코드는 0~255(1바이트)의 값만 가능하다. 그러므로 -1은 0xff이므로 이것은 곧 양의 정수로 255이다. 결과적으로 255가 전달된다.

 

3. main() 함수가 실행되어 f() 함수 내 printf()가 실행되기 직전과 f()에서 리턴한 직후의 사용자 주소 공간을 각각 그리되, 주소 공간이 형성되는 과정과 주소 공간의 각 영역에 어떤 것들이 존재하는지 자세히 그려라. 현재 소스코드에 보이는 것들만 고려하라.

 

f() 함수 내 printf()가 실행되기 직전의 사용자 주소 공간

[코드영역]
main() 함수코드
f() 함수 코드
print()함수코드
malloc() 함수코드
[데이터 영역]
a = 10
[힙 영역]
100바이트
[미 할당 영역]
[스택 영역]
b = 20
c = 30
p = 힙 영역의 가상 주소

f()에서 리턴한 직후의 사용자 주소 공간

[코드영역]
main() 함수코드
f() 함수 코드
print()함수코드
malloc() 함수코드
[데이터 영역]
a = 10
[힙 영역]
100바이트
[미 할당 영역]
[스택 영역]
b = 20
p = 힙 영역의 가상 주소

4. 다음 C 프로그램에서 main()이 실행되면 f(2)를 호출하고, f()는 다시 g()를 호출한다. f()가 g()를 호출하기 직전과 g()에서 리턴한 직후의 사용자 주소 공간을 각각 그리되, 주소 공간이 형성되는 과정과 주소 공간의 각 영역에 어떤 것들이 존재하는지 자세히 그려라. 현재 소스 코드에 보이는 것들만 고려하라.

int a[100];
int main(){
	int b=1;
    f(2);
    return 0;
    }
void f(int c){
	int d=3;
    g();
    printf("%d",c);
}
void g(){
	int* p = (int*)malloc(100);
}

f()가 g()를 호출하기 직전의 사용자 주소 공간

[코드영역]
main() 함수코드
f() 함수 코드
print()함수코드
malloc() 함수코드
[데이터 영역]
a [100]
[힙 영역]
[미 할당 영역]
[스택 영역]
b = 1
c = 2
d = 3

g()에서 리턴한 직후의 사용자 주소 공간

[코드영역]
main() 함수코드
f() 함수 코드
print()함수코드
malloc() 함수코드
[데이터 영역]
a[100]
[힙 영역]
100바이트
[미 할당 영역]
[스택 영역]
b = 1
c = 2
d = 3

p = 힙 영역의 가상 주소

 

5. 다음 코드에 답하라.

/*************************
소스 프로그램 prac3_5.c
컴파일 및 실행 방법
$ gcc -o prac3_5 prac3_5.c
$ ./prac3_5
*************************/
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <wait.h>

int main(void){
    pid_t pid;
    int status;
    
    pid = fork();
    if(pid>0){ // (a) 1.부모 2.자식 3.오류처리
        sleep(2);
        wait(&status);
        printf("%d\n",WEXITSTATUS(status));
        return 0;
        }
        else if(pid==0){ // (b) 1.부모 2.자식 3.오류처리
        	sleep(1);
            return -1;
        }
        else{ // (c) 1.부모 2.자식 3.오류처리
          sleep(3);
          return 1;
       }
}

(1) 위 코드의 3개의 주석문 (a), (b), (c)에서 1.부모 2.자식 3.오류처리 중 적합한 것 하나를 선택하라

(a) 부모 (b) 자식 (c) 오류처리

(2) 실행 결과 출력되는 내용은 무엇인가? 프로그램을 실행시켜 결과를 확인하라.

(3) 자식 프로세스는 종료 후 얼마의 시간 동안 좀비 프로세스로 있게 되는가? 1초

 

6. 다음 C 프로그램에 대해 답하라.

 

/*******************************
소스 프로그램 prac3_6.c
컴파일 및 실행 방법
$ gcc -o prac3_6 prac3_6.c
$ ./prac3_6
*******************************/
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <wait.h>

int main(void){
	pid_t pid;
	int status;
    
    pid = fork();
    if(pid>0){
    sleep(1);
    return 0;
    }
    else if(pid == 0){
    	sleep(2);
        printf("부모프로세스의 pid = %d", getpid());
        return -1;
    }
}

(1) fork() 후 어느 부분이 부모 프로세스의 코드와 자식 프로세스의 코드인가?

if(pid>0) 부분이 부모 프로세스의 코드이고

else if(pid==0) 부분이 자식 프로세스의 코드이다

(2) 고아 프로세스가 발생하는가? 발생한다

(3) 이 프로그램의 실형 결과는 무엇이라고 예측되는가? 프로그램을 실행시켜 결과를 확인하고 실행 결과에 대한 이유를 설명하라.

고아 프로세스가 되어도 종료 되지 않고 #1 init 프로세스에 입양된다. 그래도 여전히 고아 프로세스 라고 부른다

 

7. 1에서 10까지 더한 합을 종료코드로 리턴하는 sum.c 프로그램을 작성하라. 그리고 execlp("./sum", "./sum", NULL); 을 이용하여 sum 프로그램을 자식 프로세스로 실행시키고 종료코드를 받아 합을 출력하는 프로그램 prac3_7.c를 작성하라. 컴파일 및 실행 사례는 다음과 같다.

$ gcc -o sum sum.c
$ gcc -o prac3_7 prac3_7.c
$ ./prac3_7
1에서 10까지 합한 결과는 55
$
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main() {
	int sum = 0;
	for (int i = 1; i <= 10; i++) {
		sum += i;
	}
	printf("1에서10까지 합한 결과는 %d",sum);
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main() {
	pid_t pid;
	pid = fork(); // 자식 프로세스 생성
	if (pid > 0) { // 부모 프로세스 코드
		wait(NULL); // 자식프로세스가 종료할 때까지 대기 
		return 0;
	}
	else if (pid == 0) { // 자식 프로세스 코드
		execlp("./sum", "./sum", NULL); 
	}
	else { // fork() 오류
		printf("fork 오류");
		return 0;
	}
}

8. 다음과 같이 주어진 응용프로그램을 작성하라.

부모 프로세스는 두 변수 n과 m을 통해 자식 프로세스가 더할 범위를 지정한다. n에는 1, m에는 100을 저장한다. 이들을 전역 변수로 선언하든 지역 변수로 선언하든 상관없다. 그리고 fork()를 이용하여 자식 프로세스를 생성한다.

자식 프로세스는 부모 프로세스를 그대로 복사하므로 부모에 선언된 변수 n과 m을 그대로 물려받는다. 자식 프로세스는 변수 n에서 변수 m까지 합을 구하고 합이 1000보다 작으면 0을, 1000이면 1을, 1000보다 크면 2를 종료코드로 리턴한다.

부모 프로세스는 wait() 함수를 호출하여 자식 프로세스가 종료하기를 기다린 후, 자식 프로세스의 종료코드를 읽어 n에서 m까지의 합이 1000보다 큰 것이었는지를 판별한다.

이 프로그램이 prac3_8.c 라고할 때, 컴파일 및 실행 사례는 다음과 같다.

$ gcc -o prac3_8 prac3_8.c
$ ./prac3_8
자식 프로세스 : 10에서 100까지의 합은 5050
부모 프로세스 : 1000보다 크다.

참고로, 실행 결과에서 "자식 프로세스 : 10에서 100까지의 합은 5050"은 자식 프로세스가 출력한 것이고, "부모 프로세스 : 1000보다 크다." 는 부모 프로세스가 자식의 종료코드를 분석하여 출력한 결과이다.

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main() {
	pid_t pid;
	int child_pid;
	int n=1,m=10,sum=0;
	int status;
	

	pid = fork(); // 자식프로세스 생성 
	child_pid = wait(&status);
	if (pid > 0) { // 부모 프로세스에 의해 실행되는 코드  
		wait(NULL); // 자식프로세스가 종료할 때까지 대기
		if (WEXITSTATUS(status) == 2) {
			printf("부모 프로세스 : 1000보다 크다.\n");
		}
		else if (WEXITSTATUS(status) ==0) {
			printf("부모 프로세스 : 1000보다 작다.\n");
		}
		else if (WEXITSTATUS(status) == 1) {
			printf("부모 프로세스 : 1000이다.\n");
		}
		return 0;
	}
	else if (pid == 0) { // 자식 프로세스에 의해 실행되는 코드  
		sum = 0;
		for (n; n<=m; n++)
			sum += n;
		printf("자식프로세스: 1에서 100까지의 합은 %d\n",sum);
		if (sum < 1000) {
			return 0;
		}
		else if (sum == 1000) {
			return 1;
		}
		else if (sum > 1000) {
			return 2;
		}
	}
	else { // fork() 오류 
		printf("fork 오류");
		return 0;
	}
}

+ Recent posts