2016년 12월 30일 금요일

2016년 10월 30일 일요일

2016년 10월 26일 수요일

2016년 10월 18일 화요일

2016년 7월 17일 일요일

Memory Management

Memory Management
2016 5 26일 목요일
오후 9:07

1.   모든 프로세스는 실행되기 위해 반드시 메모리 위에 있어야 한다.
·       CPU가 알고 있는 주소는 메모리 주소밖에 없기 때문.
·       멀티태스킹을 해야하므로 management 필요.
2.   프로그램은 원래 이진 실행파일 형태로 디스크에 저장되어 있다.
실행되기 위해서는 메모리로 올라와서 프로세스가 되어야 한다. 이를 위해서는 여러 단계를 거쳐야 한다.
·       Source - (Compile) - object module - (linking - 다른 object module ) - load module
- (loader) - 동적 링킹(exe 파일에서 호출이 있을때 linking)
·       Address Binding(주소 할당)  할당이 이루어지는 시점에 따라 3가지로 구분된다.
a.   Compile time binding
·       컴파일 시에 메모리에 올라갈 주소를 미리 알 수 있으면, absolute code 생성 가능.
·       시작주소가 변경된다면 recompile 해야 한다. ( ex. DOS)
·       Logical 주소와 physical 주소가 동일
b.   Load time binding
·       컴파일러는 코드를 relocatable code로 만들고, 이후 프로그램이 메모리로 실제 적재되는 시간에 주소 할당.
(단순히 논리 주소에 실제 시작주소를 더하는 방식)
·       시작주소가 변경된다면 재 적재하면 된다.
·       한번 메모리에 올라오면 주소를 바꿀 수 없다.
·       Logical 주소와 physical 주소가 동일
·       Execution time binding
·    프로세스가 실행하는 중간에도 계속해서 할당이 이루어 지는 방식.
·    프로세스 실행 도중에도 메모리상의 위치를 변화시킬 수 있다.
·    CPU는 오직 상대주소로만 메모리에 접근할 수 있다.
·    CPU가 프로세스에 접근할 때마다 binding이 이루어져야 한다.(별도의 자료구조 - address mapping table 필요)
·    하드웨어 지원 필요(base, limit 레지스터, MMU(memory management unit)- 논리주소를 실제주소로 변환 역할)
·    Logical 주소와 physical 주소가 다르다.
·    유저 프로그램은 physical address를 알 수 없다. 유저 프로그램이 발생시킨 모든 주소는 MMU relocation register(base register)를 더하여 실제 주소로 변환한다.

+) address mapping table : logical address(CPU가 제시한 주소)에 해당하는 physical address(실제 메모리 내
   주소) 값을 유지하는 테이블
+) Base and limit register : logical address space를 정의하는 레지스터 값, base(시작), limit(크기)

Q] 왜 끝번지 말고 길이를 저장?
A] 접근 요청시 address가 합법적인지 검사 후 실제 메모리주소 반환한다. 길이는 최대의 Offset.
CPU가 발생시킨 Offset을 길이와 비교하여 합법적인 접근인지 판단하기 아주 용이하기 때문이다.

Q] 배열은 연속적인 주소공간을 가진다?
A] 이 주소공간은 logical address이다. 실제 메모리 상의 physical address 주소의 연속을 의미하지 않는다.
MMU가 이를 관리하므로 배열은 실제 메모리 상에서는 흩어져서 저장될 수 있다.

·       Dynamic Loading
·       각 루틴은 실제 호출되기 전까지는 디스크에서 대기, 루틴 호출 시 먼저 이미 메모리에 있는지 조사하고, 없다면 적재한다.
·       장점 두 가지 1) 메모리의 효율적 사용(아주 드물게 발생하지만 많은 코드를 갖는 경우, 미리 적재되지 않는다.)
 2) 공유될 수 있다(dll 파일같이 읽기 전용 파일은 공유가 되어도 된다.
                        Address space에 포함시켜 미리 올려주면 중복해서 계속 올라갈 수 있다.)

·       Dynamic Linking
·       Linking이 실행 때 까지 미루어진다.(주로 시스템 라이브러리에 사용, 라이브러리를 실제로 사용할 때 link 한다.)
·       Swapping
·       프로세스가 실행도중에 일시적으로 디스크로 보내졌다가 나중에 다시 메모리로 돌아오는 것
·       Contiguous Allocation
·       주 메모리 : OS가 상주하는 부분(low memory with interrupt vector), 유저 프로세스가 상주하는 부분(high memory)
o   single-partition allocation(MMU Logical 주소를 base에 더해서 physical 주소로 변환, protection 담당.)
·       Logical address > limit register : trap// else relocation register(base) + logical address -> physical address
o   Multiple -partition allocation
·       Single partition보다 오버헤드 적다. (주소가 아닌 파티션 번호로 관리 가능)
·       Hole 발생(C.A의 특징), 다양한 크기의 Hole들이 메모리 전역에 생긴다. 이 공간들을 어떻게 할당할 것인가
o   Dynamic storage allocation problem
·       First fit    : 첫 번째로 충분히 큰 가용 공간 할당
·       Best fit    : 사용 가능한 공간들 중 가장 작은 것 선택, 전체 리스트를 탐색해야 함. 많은 small hole을 만들어 낸다.
·       Worst fit  : 가장 큰 hole 선택. 전체 리스트를 탐색해야 함.
·       Fragmentation(단편화, 메모리공간을 낭비하게 됨)
o   External fragmentation : 할당되지는 않았지만, 너무 작아서 쓸 수 없는 공간.
(compaction 하면 쓸 수 있지만 오버헤드(메모리 카피)가 너무 커서 구현 힘들다. 또한, 프로세스의 재배치가 실행시간에 동적으로 이루어 지는 경우에만 가능)
o   Internal fragmentation : 할당은 되었지만 실제로 쓰이지 않는 공간. 단위 규격으로 할당 시 발생한다.
·       Partition으로 나누어 관리 시 주소관리 오버헤드 없어지고, 메모리 관리속도 상승. But, internal fragmentation 발생.
Internal 을 줄이려면, partition을 작게 만들면 되고, external을 없애려면 프로세스도 partition화 하면 된다.  
·       Paging
·       Address space page 단위로 쪼개고, physical memory frame 단위로 쪼개서 사용한다.
·       External fragmentation은 발생 x, Internal fragmentation만 존재.
·       Frame size는 반드시 2의 제곱( 4KB = 2^12)
·       Free frame에 관한 정보, page table(logical address -> physical address) 필요.
·       Address transition (1)
o   ┗Logical address/Page size = page number(이를 page table 사용해 frame의 시작주소로 변환)
o   Logical address - ┗Logical address/Page size*Page size = offset(frame 내의 offset과 동일)
·       Address transition (2)
o  
o   Logical address의 하위 n비트는 page offset, 상위 m-n비트는 page number 의미.
o   Logical address p+d일 때, page table에서 p만큼 내려가서 해당 frame의 시작주소 f 얻고, f+d로 변환.
o   Page table 에는 frame 시작주소만 저장하면 된다.(page number 저장 불 필요)
o   메모리(page table)에 한번 접근하는 것이 유일한 오버헤드.

·       Page table은 주 메모리에 위치하며, 위의 방식은 프로세스마다 1개의 page table을 가진다.
·       PTBR(page table을 가리키는 레지스터), PTLR(page table size를 나타내는 레지스터 - protection 위해)
·       위 방식은 데이터에 접근하기 위해 총 두 번의 메모리 접근 필요 -> 속도 향상 위해 TLB 사용.
·       TLB(Transition look-aside buffer)
o   Page table을 위한 캐시, 매우 빠른 associative memory로 구성.
o   Protection 위해 ASIDs 사용 하기도 함.( entry가 어느 프로세스에 속해있는지 저장.)
·       ASIDs가 있으면, 1개의 TLB내에 여러 프로세스들의 정보를 동시에 보관할 수 있다.
·       없으면, context switch가 발생할 때마다 TLB flush 되어야 한다.
o   TLB page table의 일부만 저장, 전부 다 탐색해야 함. Parallel search 지원.(한 번의 search로 탐색 완료.)
·       Address transition with TLB
o   CPU에서 logical address(p+d) 발생. P(m-n 비트) TLB내에 존재하는지 search.
·       존재 시(TLB hit) f+d
·       존재 안하면(TLB miss), page table에서 p만큼 내려가서 frame 시작주소 얻음. F+d
o   Effective access time(실제 기억장치 접근 시간)
·       Associative lookup a, memory access b, hit ratio c.
·       EAT = c*(a+b) + (1-c)*(a+2b) = a + (2-c)b

·       OS는 각 프로세스에게 가능한 최대 크기의 address space를 제공한다. 주어진 공간을 다 사용하지 않을 때 protection 필요.
o   Valid, invalid bit page table의 각 page 항목별로 두어 해당 page가 프로세스의 합법적인 page인지 나타낸다.
o   PTLR 사용하여 검사할 수도 있다.
·       Shared pages
o   여러 프로세스 간에 read only code는 공유되어도 된다.  Code는 공유되어도 그 코드를 위한 데이터는 각자 가짐.
o   , 반드시 프로세스들의 address space에서 공유되는 page들이 같은 위치에 존재해야 한다.

·       Structure of the page table
·       Hierarchical paging(2 level)
o   32bit , 앞의 20bit(page number), 뒤의 12bit(page offset).
o   앞의 20bit , 앞의 10bit(page number - page 1K개 있으므로), 뒤의 10bit offset(각 페이지에 1K개의 entry)
o   Logical address = p1+p2+d, p1 = outer-page table index, p2 = inner-page table의 페이지 내의 displacement.
o   outer-page table에서 p1만큼 내려와서, inner-page table page에서 p2만큼 내려가서, 해당 frame의 시작주소에서 d만큼 내려가서 physical memory address를 얻는다.
o   메모리 접근 3. 그러나, TLB 사용하면 꽤 효율적.
·       Hashed page tables
o   Page table을 해시로 구현. P+d에서 p를 해시하여 해당 위치에 저장. Collision 발생시 search해야 한다.
o   element page number, frame number, next element pointer 저장.
·       Inverted page tables
o   frame 별로 그 frame에 올라와 있는 page의 주소, 프로세스의 ID 저장.
o   시스템에 단 하나의 페이지 테이블만 존재. 메모리 절약 가능.
o   단점: Page sharing 불가능. 전체 table을 탐색해야 함.(DRAM access 너무 많이 발생. 비효율적)
-> hash, TLB 사용하여 단축 가능.

·       Segmentation
·       사용자의 관점 반영, logical address space segment들의 집합으로 정의.(서브루틴, 전역 변수, 지역변수….)
·       Logical address = segment name + offset
·       Segment table의 각 entry에는 base( segment 들의 시작주소 저장), limit( 해당 segment의 길이) 값 저장.
·       Segment table은 결국 base, limit register 쌍들의 배열.
·       STBR - segment table의 위치 저장, STLR - 해당 프로세스에서 사용하는 Segment의 수 저장.
·       Dynamic allocation problem 발생
o   segment별 로 크기 다양함. First fit, best fit 등 사용, Internal fragmentation x, external fragmentation o
·       Address transition
o   Logical address = s + d, segment table에서 해당 segment limit 값 가져와서 d와 비교.
·       Limit >= d - base + d
·       Limit < d - trap
·       장점
o   protection - limit 레지스터를 활용한 illegal access 판단 이외에도, 추가 비트를 사용해 R,W,X등 권한 설정도 가능.
o   Sharing - 간단히 두 프로세스의 segment table이 같은 주소를 가리키는 것만으로 공유 가능. 의미 단위 공유 가능.
(, 공유하는 프로세스가 모두 이 segment에 대해 같은 번호를 가져야 함. Self reference시 문제 발생 가능.)

·       Segmentation with paging
·       segment paging!
·       기존 segment table segment base를 각 segment page table base로 대체.
·       Logical address = s+ d = s+p+d' (s : segment number, p : page number, d' : frame 내의 displacement, offset)
o   S + STBR을 통해 해당 segment table entry에 접근. D segment length 비교.
·       segment length >= d -  page table base + p를 통해 frame 번호 f 얻고, f + d'
·       Segment length < d - trap.
·       Segment page table 공유가 가능.
·       실제 사용은 TLB와 결합하여 쓴다.
·       Logical address : s + p + d
o   S + p TLB에서 먼저 찾는다.
·       TLB hit -  f + d
·       TLB miss - s + STBR, length >= p+d, page-table base + p, f+d

Deadlock

Deadlock


1.   System model
·       Resource R1,R2,R3.(CPU 주기, 메모리 공간, I/O 장치…)
·       Ri instances Wi를 가진다.( instance들은 서로 동등한 관계, 프로세스는 이를 구분하지 않는다.)
·       프로세스가 자원을 사용하는 순서
o   Request  -> use -> release

2.   Deadlock(교착 상태의 특징)
·       교착상태는 다음 4가지 조건이 모두 만족될 때 발생한다.
o   Mutual exclusion : resource는 한 순간에 한 프로세스만 사용한다.
o   No preemption : 한 프로세스가 자발적으로 방출해야만 다른 프로세스가 사용할 수 있다.
o   Hold and wait : 최소한 하나의 자원을 점유한 채, 다른 프로세스에게 점유된 자원을 위해 대기하는 프로세스가
                      반드시 존재해야 한다.
o   Circular wait : 원형 대기.
3.   Resource-allocation graph
·       그래프는 vertex set edge set pair.
o   Vertex set : 각 프로세스들 P1, P2, P3 + Resource type R1, R2, R3
o   Edge set : request edge(Pi -> Ri) + assignment edge(Wi -> Pi)
·       각 프로세스는 원, 자원은 사각형, 인스턴스는 점으로 표시.
·       프로세스가 자원을 요청하면, request edge 추가. 할당 가능하면 즉시 assignment edge 생성.
·       그래프에 cycle이 없다면, deadlock x.
·       그래프에 cycle이 있다면, 각 자원 타입마다 오직 1개의 instance만 있다면, deadlock.
·       각 자원 타입마다 여러 개의 instance가 있다면, deadlock 일수도 아닐 수도.

4.   Deadlock handling 방법에는 3가지가 있다.
a.   Deadlock이 발생하지 않도록 보장.(prevention, avoidance)
b.   Deadlock이 발생하지만, 탐지, 회복할 수 있도록 함.(detection, recover)
c.    Deadlock이 발생하지 않는 것처럼 행동.(대부분의 운영체제가 채택)
                       i.        Deadlock을 예방, 처리 하는 과정이 너무 큰 오버헤드
                      ii.        Deadlock 발생 빈도가 아주 낮다.

5.   Deadlock prevention
·       Deadlock 의 조건 성립을 막아서, deadlock이 발생하지 않도록 보장.
o   Mutual exclusion : 공유가 불가능한 자원들이 존재하므로 방지 불가.
o   Hold and wait : all or nothing
·       1) 각 프로세스가 실행되기 전에 필요한 자원을 모두 요청하고, 모두 할당 받은 후에 실행되게 한다.
·       2) 자원을 전혀 갖고 있지 않을 때만 자원을 요청할 수 있다.
-> 자원 이용도 저하, starvation 가능.
o   No preemption : 만일, 어떤 자원을 점유하고 있는 프로세스가 즉시 할당할 수 없는 자원을 요청하여 대기해야 하면, 그 프로세스가 점유하고 있는 모든 자원이 선점된다. 선점된 자원들은 이 프로세스가 기다리는 자원들의 리스트에 추가되며, 이 자원들을 모두 획득할 수 있을 때에 재 시작 된다.
o   Circular wait : 모든 자원 타입에 순서를 부여하여, 오름차순으로만 요청할 수 있도록 한다.
                   (상위 자원을 점유하고 있으면, 하위 자원 요청 불가.-> 그래프에서 back edge가 만들어지지 않는다.)

6.   Deadlock avoidance
·       Deadlock 발생 가능성이 존재하면, 자원 할당 요청을 받아 들이지 않는다.
·       Unsafe state로는 절대 진입하지 않는다.
·       자원 할당 요청을 들어주었을 때, 발생할 수 있는 worst case를 찾아서 safe한지(circular wait 발생하지 않는지) 검사한다.
 (각 자원 타입 별 최대 자원 요구량 정보 필요)
·       Resource allocation state는 현재 남아있는 자원, 할당된 자원, 최대 자원 요구량에 의해 결정된다.
o   Safe state : 프로세스들이 모두 자원의 최대치를 요구하더라도, deadlock을 야기하지 않고 할당해 줄 수 있는 safe sequence가 존재한다면 safe. 비록 당장 할당이 불가해도, 다른 프로세스의 수행이 끝나고 할당하여 모든 프로세스를 마칠 수 있는 sequence가 존재해야 한다.
o   Unsafe state : deadlock 의 가능성이 존재하는 상태. 반드시 deadlock이 발생하는 것은 아님.
·       Avoidance algorithm
o   Resource allocation graph (각 자원 별 instance 1개씩 있을 때)
·       Claim edge(Pi -> Rj) : Pi가 미래에 Rj를 요청할 가능성이 있음을 의미
·       프로세스가 실행되기 전에 모든 Claim edge들이 추가되어야 한다.
·       판단 방법: 자원 할당을 가정했을 때 , claim edge를 포함하여 cycle이 만들어 진다면 unsafe 하므로 할당 x.
(해당 request edge -> assignment edge cycle을 형성하지 않는다면 할당.)
o   Banker's algorithm(각 자원 별 여러 개의 instance가 있을 때)
·   프로세스 별 필요한 자원의 최대 개수 정보 필요.
·   추가 자료구조 필요.( # of process : n, # of resource : m)
      • Available : m 1차원 배열, 각 종류의 자원이 현재 몇 개가 남아있나. Available[j] = k.
      • Max : n*m 2차원 배열, 각 프로세스가 최대로 필요로 하는 각 자원의 개수. Max[i][j] = k.
      • Allocation : n*m 2차원 배열, 각 프로세스에게 현재 할당된 각 자원의 개수. Allocation[i][j] = k.
      • Need : n*m 2차원 배열, 각 프로세스가 추가적으로 필요한 자원의 수. Need[i][j] = Max[i][j] - allocation[i][j]
·   Safety algorithm.
      • 시스템이 safety 한지 판단하는 방법.
      • work : m 1차원 배열, finish : n 1차원 배열.
·       Work = available, finish[i] = false로 초기화.
·        a) finish[i] == false ,b) need[i] <= work 를 모두 만족하는 i 찾는다.
 (아직 끝나지 않은 프로세스 들 중, 현재 자원을 몰빵하면 끝날 애들을 찾는다. 끝나면 전부 회수.)
·        i를 찾았다면, work = work + allocation[i], finish[i] = true 후 다시 위 조건을 만족하는 i를 찾는다.
·        i가 없다면, 모든 i값에 대해 finish[i] == true 라면 safe. 단 하나라도 false라면 unsafe 이다.
·       Resource-request algorithm.
§  Pi가 자원을 요청했을 때, 줄지 말지 결정하는 방법.
§  Request-i : n 1차원 배열, Pi의 자원 요구량 의미.
·       Request-i <= need-i 이 아니라면 error
·       Request-i <=  available-I 이 아니라면 Pi wait.
·       제대로 요청했고, 할당해줄 수 있는 자원이 있다면, 자원을 할당해 준 것처럼 자료구조만 변경해본다.
·       Available = available - request-I, allocation-I = allocation + request-I, need-I = need-I - request-I
·       이 상태에서 safety 알고리즘을 적용하여, safe하다면 자원을 실제로 할당한다. Unsafe하다면 자료구조를 복구 후 Pi wait한다.

6.   Deadlock detection
·       Deadlock에 들어갔을 때, 탐지 및 회복하기 위한 방법 필요.
·       Detection algorithm.
o   Wait-for graph(각 자원 별 1개의 instance 존재 시)
·       노드는 process Pi만 존재, Pi -> Pj (Pi Pj가 현재 점유중인 자원을 기다리는 상태.)
(노드의 개수를 줄여 complexity 줄이기 위함.)
·       Cycle의 존재 여부를 검사, 존재한다면 deadlock.
§  Reduction of resource graph(cycle 탐지에 사용)
·       각 프로세스가 dormant state에 있다고 가정.(추가적인 자원 요청을 하지 않는다.)
·       각 프로세스는 자원을 얻고, 작업 완료 후, 전부 반납한다고 가정.
·       자원을 요청하지 않는 프로세스와 edge를 같이 지우고, 연쇄적으로 reduce한다. Irreducible == deadlock!
·       Reduction order는 무관하다.

o   Deadlock detection algorithm.

·       Work = available // allocation[i] = 0 이면 finish[i] = true, 아니면 false.
·       a)  finish[i] == false && b) request[i] <= work (안 끝난 애들 중, 요청 량이 현재 남은 것으로 해결 가능하다면)
·       Work = work + allocation, finish[i] = true 후 위 조건 만족하는 프로세스 계속 탐색.
·       만족하는 프로세스가 없다면, finish[i] 가 모두 true라면 deadlock x, 하나라도 false라면 deadlock o.
-> banker's algorithm과 다르게 프로세스들이 dormant state라고 가정 + 현재 상태만 고려.

8.   Recovery from deadlock.
·       Process termination(둘 중 하나)
o   Deadlock에 빠진 프로세스를 모두 중지. -> 모든 프로세스의 연산 결과들이 모두 소실되므로 비용이 크다.
o   Deadlock이 제거될 때까지 하나씩 중지. -> 계속해서 detection 수행해야 하므로 오버헤드가 크다.
·       Resource preemption(세가지를 모두 고려)
o   Selecting of a victim - victim process를 선정해서, 자원을 선점하는 방식.
o   Rollback - process safe state로 후퇴시키고, 그 상태부터 재 시작. -> 이전 정보를 갖고 있어야 함.
o   Starvation - 같은 process가 반복적으로 victim이 되지 않도록 보장해야 함.(# of rollback을 카운트)

9.   Avoidance : worst case( 모든 프로세스가 동시에 maximum 자원 요구) 시에도 safe sequence가 존재할 때만 할당.
Detection : best case(모든 프로세스가 추가 자원 요구 x), 현재 자원 요구량 만 고려.