[인프런 워밍업클럽 CS 2기] 3주차 발자국

[인프런 워밍업클럽 CS 2기] 3주차 발자국

3주차 학습 내용

 

  • '그림으로 쉽게 배우는 자료구조와 알고리즘 (기본편)' Section 3(Unit 6~10)

  • '그림으로 쉽게 배우는 운영체제' Section 8, 9, 10


 

'그림으로 쉽게 배우는 자료구조와 알고리즘 (기본편)' Section 3(Unit 6~10)

 

Section 3. 알고리즘

  • 정렬 - 병합정렬(Merge Sort)

    • divide and conquer - 분할 정복

      • 해결하기 힘든 문제가 발생한다면 이걸 한 번에 해결하려고 하지 말고,
        해결하기 쉬울 정도로 문제를 쪼갠 다음 하나씩 해결하라

      • 원소를 하나일 때까지 쪼개고, 역순으로 순서에 맞게 하나의 배열로 병합해줌
        (재귀함수를 호출한 모양과 비슷함)

        image

    • 코드 구현

      function MergeSort(arr, leftIndex, rightIndex) {
      	if(leftIndex < rightIndex) {
      		let midIndex = parseInt((leftIndex + rightIndex) / 2);
      		MergeSort(arr, leftIndex, midIndex);
      		MergeSort(arr, midIndex + 1, rightIndex);
      		Merge(arr, leftIndex, midIndex, rightIndex);
      	}
      }
      
      function Merge(arr, leftIndex, midIndex, rightIndex) {
      	let leftAreaIndex = leftIndex;
      	let rightAreaIndex = midIndex + 1;
      	
      	let tempArr = [];
      	tempArr.length = rightIndex + 1;
      	tempArr.fill(0, 0, rightIndex + 1);
      	
      	let tempArrIndex = leftIndex;
      	while(leftAreaIndex <= midIndex && rightAreaIndex <= rightIndex) {
      		if(arr[leftAreaIndex] <= arr[rightAreaIndex]) {
      			tempArr[tempArrIndex] = arr[leftAreaIndex++];
      		} else {
      			tempArr[tempArrIndex] = arr[rightAreaIndex++];
      		}
      		tempArrIndex++;
      	}
      	
      	if(leftAreaIndex > idIndex) {
      		for(let i = rightAreaIndex; i <= rightIndex; i++) {
      			tempArr[tempArrIndex++] = arr[i];
      		}
      	} else {
      		for(let i = leftAreaIndex; i <= midIndex; i++) {
      			tempArr[tempArrIndex++] = arr[i];
      		}
      	}
      }
      
    • 병합정렬 성능

      • 성능측정 부분은 Merge() 함수 내 흩어진 배열을 합치는 부분

        • 하나의 데이터와 하나의 데이터가 두 개로 합쳐질 때 비교 연산을 두 번 함

        • 두 개의 데이터와 두 개의 데이터가 네개로 합쳐질 때 비교가 네 번 이뤄짐

      • 각 단계를 거칠 때마다 영역의 수가 반으로 줄어 logn이 됨

      • 분할된 배열을 병합할 때는 n개의 데이터를 n번 비교하므로 O(nlogn) 성능이 나옴

        image

    • 병합정렬 장단점

      • 장점 - 성능이 좋음(O(nlogn))

      • 단점 - 이해와 구현이 어려움

  • 정렬 - 퀵정렬(Quick Sort)

    • 분할 정복 알고리즘으로 재귀를 사용함

    • 퀵정렬 설명

      • 정렬하기 전에 배열에 있는 숫자 중 하나를 피벗으로 설정해줌


        image

      • leftStartIndex는 피벗보다 큰 값을 만나면 멈춤

      • rightStartIndex는 피벗보다 작은 값을 만나면 멈춤

      • leftStartIndex, rightStartIndex의 값을 스왑해줌

      • 서로 지나쳤다면 더이상 진행하지 않음

      • 이상태에서 피벗과 rightStartIndex 값 스왑해줌

      • 피벗값을 기준으로 오른쪽, 왼쪽을 정렬해줌

    • 코드 구현

      function quickSort(arr, left, right) {
      	if(left <= right) {
      		let pivot = divide(arr, left, right);
      		quickSort(arr, left, pivot - 1);
      		quickSort(arr, pivot + 1, right);
      	}
      }
      
      function divide(arr, left, right) {
      	let pivot = arr[left];
      	let leftStartIndex = left + 1;
      	let rightStartIndex = right;
      	
      	while(leftStartIndex <= rightStartIndex) {
      		while(leftStartIndex <= right && pivot >= arr[leftStartIndex]) {
      			leftStartIndex++;
      		}
      		
      		while(rightStartIndex <= (left + 1) && pivot >= arr[rightStartIndex]) {
      			rightStartIndex++;
      		}
      		
      		if(leftStartIndex <= rightStartIndex) {
      			swap(arr, leftStartIndex, rightStartIndex);
      		}
      	}
      	
      	swap(arr, left, rightStartIndex);
      	return rightStartIndex;
      }
      
      function swap(arr, index1, index2) {
      	let temp = arr[index];
      	arr[index1] = arr[index2];
      	arr[index2] = temp;
      }
      
      let arr = [5, 3, 7, 2, 6, 4, 9, 1, 8];
      
      console.log("==== 정렬 전 ====");
      console.log(arr);
      
      quickSort(arr, 0, arr.length - 1);
      
      console.log("==== 정렬 후 ====");
      console.log(arr);
      
    • 퀵 정렬의 성능

      • 피벗이 매번 배열의 반을 가르는 경우

        • O(nlogn)

      • 피벗이 배열을 반으로 가르지 않고 한쪽에 쏠리는 경우 - 최악의 경우

        • O(n^2)

      • 성능만 보면 병합 정렬이 더 좋다고 볼 수 있는데, 실제로 비교하면 퀵정렬이 더 적은 비교와 더 적은 메모리 공간을 차지하기 때문에 더 좋은 알고리즘으로 평가됨

      • 퀵정렬의 장단점 - 병합정렬과 동일

  • 동적 프로그래밍 - 메모이제이션

    • 재귀의 단점

      • 피보나치 수열


        image

      • 피보나치 수열 코드

        function fibonacci(n) {
        	if(n == 0 || n == 1) return n;
        	return fibonacci(n - 2) + fibonacci(n - 1);
        }
        
        console.log(fibonacci(5));
        
      • 성능이 좋지 못함 - 반복 계산


        imageimage

        • 단점 - 이미 계산했던 것을 다시 또 계산하게 됨

      • 메모이제이션

        • 재귀의 문제점 해결방법

        • 계산 결과를 저장해두고 사용

        • 해시테이블 사용

        • 피보나치 수열 코드를 메모이제이션을 사용해 수정

          function fibonacci1(n) {
          	if(n == 0 || n == 1) return n;
          	return fibonacci(n - 2) + fibonacci(n - 1);
          }
          
          function fibonacci2(n) {
          	if(n == 0 || n == 1) return n;
          	
          	if(memo[n] == null) {
          		memo[n] = fibonacci2(n - 2, memo) + fibonacci2(n - 1, memo);
          	}
          	return memo[n];
          }
          
          let start = new Date();
          console.log(fibonacci1(40));
          let end = new Date();
          console.log("fibonacci1 함수 실행시간 : ${end - start}ms");
          
          let start = new Date();
          console.log(fibonacci2(40, {}));
          let end = new Date();
          console.log("fibonacci2 함수 실행시간 : ${end - start}ms");
          
        • 메모이제이션 장단점

          • 장점

            • 성능 O(n)을 보임

            • 재귀덕분에 하향식 계산 방식으로 어려운 문제를 간단하게 해결할 수 있음

            • 중복 계산을 하지 않아서 속도가 빠름

          • 단점

            • 메모리 영역을 사용함(ex, 캐시)

  • 동적 프로그래밍 - 타뷸레이션

    • 상향식 계산 방식으로, 계산에 필요하지 않을 수 있는 값도 미리 계산해 테이블에 저장해둠


      image

    • 코드 구현

      function fibonacci1(n) {
      	if(n == 0 || n == 1) return n;
      	return fibonacci(n - 2) + fibonacci(n - 1);
      }
      
      function fibonacci2(n) {
      	if(n == 0 || n == 1) return n;
      	
      	if(memo[n] == null) {
      		memo[n] = fibonacci2(n - 2, memo) + fibonacci2(n - 1, memo);
      	}
      	return memo[n];
      }
      
      function fibonacci3(n) {
      	if(n <= 1) return n;
      	
      	let table = [0, 1];
      	
      	for(let i = 2; i <= n; i++) {
      		table[i] = table[i - 2] + table[i - 1];
      	}
      	return table[n];
      }
      
      let start = new Date();
      console.log(fibonacci1(40));
      let end = new Date();
      console.log("fibonacci1 함수 실행시간 : ${end - start}ms");
      
      let start = new Date();
      console.log(fibonacci2(40, {}));
      let end = new Date();
      console.log("fibonacci2 함수 실행시간 : ${end - start}ms");
      
      let start = new Date();
      console.log(fibonacci3(40));
      let end = new Date();
      console.log("fibonacci3 함수 실행시간 : ${end - start}ms");
      
    • 성능

      • 메모이제이션은 여러번의 함수 호출로 메모리 공간에 스택을 차지하고, 메모이제이션을 위한 해시 테이블 공간까지 차지하기 때문에 메모리를 더 많이 사용함

      • 타뷸레이션은 적은 메모리 사용임에도 불구하고 빠른 시간을 보임

    • 메모이제이션 vs 타뷸레이션

      • 메모이제이션

        • 재귀를 이용해 문제를 하향식으로 해결함

        • 재귀만 이용한다면 중복 계산을 하기 때문에 성능의 문제가 발생했는데 계산 결과를 저장하는 방식으로 단점을 해결함

        • 해결하기 힘든 문제를 하향식으로 접근하고, 더 많은 메모리를 이용해 성능을 향상시킴

        • 이러한 이유로 분할 정복을 해결할 때 재귀가 더 직관적이라면 메모이제이션을 이용하는 것이 유리함

      • 타뷸레이션

        • 재귀가 직관적이지 않을 때는 상향식 접근인 타뷸레이션을 이용해 메모리도 절약하고 속도도 빠르게 할 수 있음


 

'그림으로 쉽게 배우는 운영체제' Section 8, 9, 10

Section 8. 가상메모리

  • 가상메모리 개요

    • 컴퓨터마다 실제 메모리 크기가 다른데, 만약 운영체제나 프로세스가 특정 크기에서 동작하도록 만들어졌다면 그 크기보다 작은 메모리를 가진 컴퓨터에서는 실행되지 않음 → 가상 메모리는 이 문제를 해결함

    • 가상 메모리

      • 프로세스는 운영체제의 영역이 어디있는지, 물리 메모리의 크기가 얼마나 큰지 몰라도 됨

      • 프로세스는 메모리 관리자에게 요청만 하면됨

      • 메모리 관리자는 프로세스의 요청이 있으면 그에 맞는 물리 메모리로 연결시켜줌

      • 가상메모리의 크기는 이론적으로는 무한대이지만 실제로는 물리 메모리 크기와 CPU의 비트 수로 결정됨 (ex, 32bit CPU(대략 4GB) → 가상 메모리 크기도 4GB가 됨)

    • 가상메모리로 프로세스들 실행시키는 방법

      • 물리메모리 내용의 일부를 하드 디스크에 있는 스왑영역으로 옮기고, 처리가 필요할 때 물리 메모리로 가져와 실행시키기 때문에 운영체제와 프로세스 5개를 전부 실행시킬 수 있음

         

    • 동적주소변환(Dynamic Address Translation)

      • 메모리 관리자는 물리메모리와 스왑영역을 합쳐서 프로세스가 사용하는 가상주소를 물리주소로 변환함

         

      • 동적 주소 변환을 거치면 프로세스는 마음대로 사용자 데이터를 물리 메모리에 배치할 수 있음

      • 메모리 관리자의 역할

        • 물리 메모리를 어떻게 나눌지

        • 프로세스를 어디다 배치할지

        • 부족한 물리 메모리는 어떻게 처리할지 등등을 위해 복잡한 과정을 거침

    • 가상 메모리 시스템의 메모리 할당 방법

      • 가상 메모리 시스템에서는 운영체제 영역을 제외한 나머지 영역을 일정한 크기로 나누어서 프로세스에게 할당함

      • 할당하는 방식은 메모리 분할방식과 마찬가지로 ‘가변 분할 방식’, ‘고정 분할 방식’으로 나뉨

         

        • 가변 분할 방식(세그멘테이션)

          • 단점 - 외부 단편화

        • 고정 분할 방식(페이징)

          • 단점 - 내부 단편화

        • 각각의 단점을 보완한 ‘세그멘테이션-페이징 혼용기법 ’ 사용

      • 세그멘테이션-페이징 혼용기법

        • 가상메모리 시스템에서 가상주소는 메모리나 스왑영역 한 곳 중에 위치

        • 메모리 관리자는 가상주소와 물리주소를 일대일 매핑 테이블로 관리함

           

  • 세그멘테이션(배치정책)

    • 가변 분할 방식을 이용하는 세그멘테이션 기법

      • 프로그램은 함수나 모듈등으로 세그먼트 구성

        • 프로그램(사용자) 관점 메모리 - 코드, 데이터, 힙, 라이브러리, 스택 각각 구성(인접할 필요 없음)

        • 프로세스 관점 메모리 - 코드, 데이터, 힙, 스택 영역을 서로 인접한 것처럼 바라봄

      • 논리주소

        • 사용자, 프로세스, CPU가 바라보는 주소

        • 실제 물리주소로 변환은 중간에서 메모리 관리자(MMU)가 해줌

      • 메모리 관리자가 논리주소 → 물리주소 변환 방법

        • 메모리 관리자가 가지고 있는 세그멘테이션 테이블에 Base Address, Bound Address(Segment 크기) 정보가 저장되고 이걸 이용해 물리 메모리 주소를 계산함

        • 운영체제는 컨텍스트 스위칭을 할 떄마다 메모리 관리자 내에 Segment Table Base Register를 해당 프로세스의 것으로 값을 바꿔줘야함 → 굉장히 무거운 동작

        • 논리주소가 Bound Address보다 작다면, 논리주소 + Base Address 로 물리주소를 구함

        • 논리주소가 Bound Address보다 크다면, 메모리를 침범했다고 생각하고 에러를 발생

      • 세그멘테이션 장점

        • 메모리를 가변적으로 분할할 수 있고, 코드 영역, 데이터 영역, 스택 영역, 힙 영역을 모듈로 처리할 수 있음 → 공유와 각 영역에 대한 메모리 접근보호가 편리함

      • 세그멘테이션 단점

        • 가변 분할 방식의 단점인 “외부 단편화”가 발생함

  • 페이징(배치정책)

    • 고정분할방식을 이용한 페이징

    • 세그멘테이션 기법은 외부 단편화 문제가 있기 때문에 이를 해결하기 위해 고안됨

    • 페이징

      • 메모리를 할당할 때 정해진 크기의 페이지로 나눔

      • 모든 페이지는 크기가 같기때문에 관리가 편하고, 일정한 크기로 나눴기 때문에 외부 단편화 현상이 일어나지 않음

      • 논리주소공간에서의 페이징 → 페이지

      • 물리주소공간에서의 페이징 → 프레임

         

    • 페이징의 주소변환 방법

      • 메모리 관리자가 “페이지 테이블”을 통해 CPU에서 전달받은 논리주소가 몇번 페이지, 오프셋은 얼마인지 알아냄

      • 메모리 관리자 내에 Page Table Base Register(PTBR)를 이용해서 물리 메모리에 있는 페이지 테이블을 찾고, 페이지 번호를 인덱스로 프레임 번호를 알아내고, 오프셋을 이용해 물리주소로 변환을 함

      • 페이지 테이블에 Invalid로 표시되어 있으면 스왑영역, 즉 하드디스크레 저장되어 있다는 의미임

      • PTBR은 운영체제가 컨텍스트 스위칭을 할 때마다 해당 프로세스의 것으로 업데이트 해줌

         

    • 세그멘테이션 vs 페이징 차이점

      • 페이지의 크기가 다름

      • 세그멘테이션은 프로세스마다 크기가 달라 Bound Address를 가지고 있지만, 페이징은 모든 페이지의 크기가 동일해서 크기를 표현하는 Bound Addresss는 필요하지 않음

        • 페이징은 이런 특성때문에 외부단편화는 발생하지 않지만 내부단편화가 발생함 (정해진 크기의 페이징보다 프로세스의 정보가 작으면 그만큼 공간이 낭비됨)

        • 세그멘테이션의 단점과 비교하면 많은 고간이 낭비되는게 아니라서 심각하게 생각하지 않음

      • 세그멘테이션은 논리적인 영역별로 세그먼트를 나눔(코드, 데이터, 스택, 힙 영역), 그러나 페이징은 페이지의 크기가 고정되어 있어 논리적인 영역별로 나누는 것이 아니라 페이지로 나누기 때문에 논리적인 영역을 나눌 수 없음 그래서 특정 영역만 공유하거나 권한을 부여하는게 더 어려움

        • 페이징에서 가장 신경써야하는 것은 페이지 테이블 크기임

        • 각 프로세스마다 페이지 테이블을 가지고 있는데 프로세스가 많아질수록 페이지 테이블도 많아지기 때문에 프로세스가 실제로 사용할 수 있는 메모리 영역이 줄어듦

        • 실제로 메모리 관리자가 참조하는 페이지 테이블도 물리 메모리의 운영체제 영역에 저장되어 있기 때문에 페이지 테이블 크기가 너무 크면 사용자 영역이 부족하게 됨 → 페이지 테이블의 크기를 적절하게 유지하는 것이 굉장히 중요함

  • 페이지드 세그멘테이션(배치정책)

    • 페이징과 세그멘테이션의 각각의 장점을 취한 방식 → 새로운 단점이 생기기도 함

      • 세그멘테이션 장점

        • 가변 분할 방식이라서 코드 영역, 데이터 영역, 스택 영역, 힙 영역을 세그먼트로 나눠서 관리할 수 있음

        • 그에 따라 다른 프로세스와 공유하기도 편하고, 각 영역에 대한 메모리 접근보호를 하기가 쉬움

      • 페이징 장점

        • 고정분할 방식으로 메모리를 효율적으로 관리할 수 있음

    • 메모리 접근 권한

      • 메모리의 특정 번지에 부여된 권한으로 읽기(Read), 쓰기(Write), 실행(Execute) 세 가지가 있음

         

      • 프로세스는 코드 여역, 데이터 여역, 스택 영역, 힙 영역이 있는데 각 영역마다 접근 권한이 있음

         

      • 코드 영역

        • 프로그램 그 자체이기 때문에 수정되면 안되므로, 읽기와 실행 권한만 있음

      • 데이터 영역

        • 일반변수, 전역변수, 상수로 선언한 변수가 저장되기 때문에 읽기 권한이 있고, 쓰기 권한은 있거나 없거나 함 실행권한은 없음

      • 스택, 힙 영역

        • 읽기, 쓰기 권한이 있고, 실행권한은 없음

      • 메모리 접근권한에 대한 검사는 가상주소에서 물리주소로 변환될 때마다 일어나는데, 만약 권한을 위반하면 에러를 발생시킴

         

    • 페이지드 세그멘테이션

      • 세그멘테이션 기법 - 세그멘테이션 테이블은 Base Address와 Bound Address로 구성됨

      • 페이징 기법 - 페이지 테이블은 프레임 번호로 구성됨

         

      • 위의 둘을 혼합해 페이지드 세그멘테이션으로 만듦 (각각의 역할은 이름만 바꼈을 뿐 달라진 것은 없음)

        • 세그멘테이션 테이블에 권한 비트를 추가함

        • Base Address는 페이지 넘버로 바뀜

        • Bound Address는 이 세그먼트 페이지 개수로 바뀜

           

      • 페이지드 세그멘테이션의 단점은 물리메모리에 접근하기 위해서 메모리에 접근을 두 번해야 된다는 것

        • 첫번째, 세그멘테이션 테이블을 참조할 때

        • 두번째, 페이지 테이블을 참조할 때 일어남

      • 위의 단점 때문에 운영체제는 페이징과 페이지드 세그멘테이션 기법을 적절히 섞어서 사용함

  • 디맨드 페이징(가져오기 정책)

    • 프로세스가 실행될 때, 프로세스를 이루고 있는 코드영역, 데이터영역, 힙영역, 스택영역과 같은 모듈이 모두 메모리에 올라와 실행된다고 알고 있음

    • 하지만 실제로는 모든 모듈이 메모리에 올라오는 것이 아니라 필요한 모듈만 올라와서 실행됨

    • 도널드 커누스의 발견 - 90:10 법칙

      • 90%의 시간이 10% 코드에서 보내는 것 → 지역성 이론이라고 함

      • 지역성(두가지)

        • 공간의 지역성

          • 현재 위치에서 가까운 데이터에 접근할 확률이 높다는 것

        • 시간의 지역성

          • 최근 접근했던 데이터가 오래전에 접근했던 데이터보다 접근할 확률이 높음

        • goto문 - 지역성 이론에 따라 성능이 좋지 않기 때문에 쓰지 않는 것을 추천

        • 지역성 이론은 조만간 쓰일 데이터만 메모리에 올리고 당분간 필요하지 않을 것 같은 데이터는 스왑영역으로 보내 성능을 향상시킴

           

        • 디맨드 페이징은 조만간 필요할 것 같은 데이터를 메모리로 가져오고 쓰이지 않을 것 같은 데이터는 스왑영역으로 이동시키는 정책

        • ex, 포토샵

          • 포토샵은 본 프로그램 외에도 이미지에 효과를 주는 외부 필터들이 있는데, 이 필터들을 포토샵과 같이 메모리에 모두 올리면 메모리를 많이 차지해서 프로그램이 더 무거워짐

          • 그래서 본 프로그램만 메모리에 올리고 외부 필터들은 사용자의 요청이 있을 때만 메모리로 가져오는 것이 메모리도 절약되고, 메모리를 효율적으로 관리할 수 있고, 프로세스의 응답속도도 빨라짐

             

    • 메모리 계층구조

      • 메모리는 레지스터, 캐시, 메인 메모리, 보조저장장치로 나눌 수 있음

      • 메인 메모리에 접근하는 시간

         

        • 레지스터

          • CPU 내에 존재하고, CPU의 한사이클에 접근할 수 있어서 굉장히 빠름

        • 캐시

          • CPU의 수 사이클에서 수십 사이클에 접근 가능

        • 메인 메모리

          • CPU의 수백 사이클에 접근 가능

        • 보조저장장치(HDD, SSD)

          • CPU의 수백만 사이클에 접근 가능

    • 디맨드 페이징은 스왑영역을 보조저장장치에 저장하는데, 성능향상을 위해서는 스왑영역으로 데이터를 이동시키는 것을 최소화 시켜야 함

    • 가상 메모리의 크기 = 물리 메모리 크기 + 스왑영역임

    • 스왑인, 스왑아웃

       

      • 스왑인 - 스왑영역에서 물리메모리로 데이터를 가져오는 것

      • 스왑아웃 - 물리메모리에서 스왑영역으로 데이터를 내보내는 것

    • 메모리 관리자는 페이지 테이블을 참조해서 물리 메모리가 있는 프레임을 알아내거나 스왑영역의 위치를 알아내야 하는데, 이를 위해 페이지 테이블에는 여러가지 비트가 있음

      • 페이지 테이블을 이루고 있는 한 행을 페이지 테이블 엔트리(PTE)라고 부름

         

      • 페이지 테이블 엔트리(PTE)

         

        • 접근 비트

          • 페이지가 메모리에 올라온 후 데이터에 접근이 있었는지 알려주는 비트

          • 메모리에 읽거나 실행 작업을 했다면 1로 바뀌게 됨

        • 변경비트

          • 페이지가 메모리에 올라온 후 데이터의 변경이 있었는지 알려주는 비트

          • 메모리에 쓰기 작업을 했으면 1로 바뀌게 됨

        • 유효비트

          • 페이지가 물리 메모리에 있는지 알려주는 비트

          • 만약 유효비트가 1이라면 페이지가 스왑영역에 있고, 0이라면 물리 메모리에 있다는 의미임

        • 읽기, 쓰기, 실행 비트

          • 권한 비트로 해당 메모리에 접근권한이 있는지 검사하는 비트

      • 프로세스가 가상 메모리에 접근요청을 했을 때

         

        • 메모리 관리자는 페이지 테이블을 보고 물리 메모리의 프레임을 찾아냄

        • 만약 물리 메모리에 없다면 Page Fault라는 인터럽트를 발생시킴

        • Page Fault가 발생하면 보조저장장치의 스왑영역에 접근하게 되고 해당 프로세스는 대기상태가 됨

        • 스왑영역에 있는 데이터가 메모리에 올라가는 작업을 시작하고, 메모리에 올라갔다면 대기상태에 있던 프로세스는 다시 실행하게 됨

      • 물리 메모리와 스왑영역에서 어떻게 참조되는가(세가지)

        • 스왑이 필요없는 경우

           

          • ex, 프로세스가 페이지 0을 요청

            • 페이지 테이블의 0번 인덱스를 살펴보면 유효비트 0, 프레임 넘버 1 → 해당 주소가 물리메모리의 1번 프레임

            • 물리 메모리에 있는 1번 프레임에 접근해 데이터를 참조함

        • 스왑영역에 있는 데이터를 참조하는 경우

          • ex, 프로세스가 페이지 2번을 요청

             

            • 페이지 테이블의 2번 인덱스를 살펴보면, 유효비트가 1이고 프레임 넘버가 2임 → 페이지가 스왑영역 2번에 있다는 뜻

            • 물리메모리에 적절히 빈 공간을 찾음

            • 스왑영역 2번에 저장된 C를 물리메모리 3번 프레임으로 가져오고

            • 페이지 테이블에서 해당 엔트리의 유효비트를 0으로, 프레임 넘버를 3으로 수정함

            • 프로세스에게 데이터를 참조하게 해줌

        • 물리메모리가 꽉찼을 때 스왑영역에 있는 데이터를 참조하는 경우

          • ex, 프로세스가 페이지 1번을 요청했다고 가정

             

            • 페이지 테이블 1번 인덱스를 살펴보면, 유효비트 1, 프레임 넘버 0 → 페이지가 스왑영역 0번에 있음

            • 물리메모리로 가져오기 위해 적절한 빈공간을 찾지만 꽉 차서 여유가 없음

            • 현재 물리 메모리에서 필요하지 않다고 판단하는 영역을 스왑영역으로 옮김

            • A가 필요하지 않다고 가정하고 스왑영역 3번으로 옮김

            • 페이지 테이블에서 0번 인덱스의 유효비트를 1, 프레임 넘버를 3으로 변경

            • 물리메모리 빈공간이 된 1번으로 B를 가져옴

            • 페이지 테이블에서 1번 인덱스의 유효비트를 0으로, 프레임 넘버를 1로 수정함

            • 프로세스에게 데이터를 참조하게 해줌

          • 스왑인(스왑영역 → 물리메모리), 스왑아웃(물리메모리 → 스왑영역) 시, 어떤게 적절한지는 운영체제가 판단함 → 페이지 교체 알고리즘

  • 페이지 교체정책

    • 메모리가 꽉찼을 때, 어떤 페이지를 스왑영역으로 보낼지 결정하는 정책임

      • 프로세스는 데이터 접근을 위해 메모리를 참조하는데, 해당 데이터가 메모리에 없으면 Page Fault가 발생함

      • Page Fault가 발생하면, 해당 페이지를 스왑영역에서 메모리로 불러들여야하는데 메모리가 꽉차서 공간이 없다면 메모리에 있는 페이지 중 하나를 선택해서 스왑영역으로 옮겨야함

      • 메모리에 있는 페이지를 스왑영역으로 옮길 때 어떤 페이지를 선택할지 결정하는 정책을 페이지 교체 정책이라고 부르고, 페이지 교체 정책에는 여러가지가 있음

    • 페이지 교체 정책의 방법들

      • 무작위로 선택하는 방법(Random)

        • 지역성을 고려하지 않기 때문에 자주 사용되는 페이지가 선택될 때도 있어 성능이 별로 좋지 않음

        • 그래서 거의 사용되지 않음

      • 메모리에 들어온지 가장 오래된 페이지를 선택하는 방법(FIFO)

        • 자주 쓰이는 페이지가 먼저 들어왔다는 이유로 해당 페이지가 교체되면 공평하지 않음

        • 위의 단점이 있지만 구현이 간단하고 성능도 꽤 괜찮아서 조금 변형해서 많이 쓰임

      • 앞으로 가장 오랫동안 쓰이지 않을 페이지를 선택하는 방법(Optimum)

        • 사실상 구현이 불가능한 이론적인 선택방법

        • 구현이 불가능해서 필요가 없을 것 같지만, 다른 알고리즘과 성능 비교를 할 때 참조용으로 쓰임

      • 최근에 가장 사용이 적은 페이지를 선택하는 방법(LRU - Least Recently Used)

        • 지역성 이론의 시간의 지역성에 따르면 최근 사용한 데이터가 앞으로도 사용될 확률이 높기 때문에 최근에 가장 사용을 적게한 페이지가 앞으로도 사용될 확률이 적다는 결론이 나옴

        • 실제로도 Optimum 알고리즘에 근접한 성능을 보임

        • 그러나 프로그램이 지역성을 띄지 않을땐 성능이 떨어지게됨

        • 페이지 테이블 엔트리는 여러개의 비트와 페이지 넘버가 저장되는데, 이곳에 시간을 기록하려면 비트가 많이 필요하게됨

        • 많은 비트를 준비하기 어려우므로 실제 LRU를 구현할 때는 접근비트를 이용해서 LRU에 근접하게 구현함

    • Optimum vs FIFO vs LRU 비교

       

      • ex, 페이지가 A B C A C D A D C A B 순서대로 요청되는 상황

         

        • 세 방법 모두 메모리가 비어있기 때문에 처음 요청에서는 전부 Page Fault가 발생함

        • A 요청 들어옴

          • 세 알고리즘 모두 Page Fault가 일어나지 않음

        • C 요청 들어옴

          • 세 알고리즘 모두 Page Fault가 일어나지 않음

        • D 요청 들어옴

          • Page Fault 발생

            • Optimum

              • 뒤에 들어오는 요청을 훑어봄

              • 페이지 B가 가장 사용되지 않을 것을 알기 때문에 페이지 B를 스왑영역으로 옮기고, B가 있던 자리에 D를 가져옴

            • FIFO

              • 먼저 들어온 페이지가 먼저 나가기 때문에 가장 먼저 들어온 페이지 A를 스왑영역으로 보내고, A가 있던 자리에 D를 가져옴

            • LRU

              • 최근에 가장 사용이 적은 페이지가 나가기 때문에 최근에 들어온 페이지의 참조 수를 계산함

              • A 2번, B 1번, C 2번으로 B가 가장 덜 사용됐으니 B를 스왑영역으로 옮기고 B가 있던 자리에 D가 들어옴

    • 빌레이디의 역설(Belady’s Anomaly)

      • Page Fault를 줄이려고 메모리를 더 늘려서 프레임 수를 늘렸는데, 오히려 Page Fault가 더 많이 발생하는 현상

        → FIFO의 가장 큰 문제임

      • FIFO에서만 발생하며 LRU에서는 발생하지 않음

    • LRU 문제점

      • 시간을 기록해야하는 LRU는 구현이 힘듦

      • 시간을 기록할 bit가 많이 필요

      • 많은 bit가 있어도 시간이 아주 오래 지난다고 가정하면 어쩔수없이 오버플로우가 발생 → 오버플로우로 값이 초기화되면서 시간을 올바르게 표현할 수 없게됨

    • 클락 알고리즘

       

      • LRU 알고리즘과 유사하게 구현하는 방법

      • 접근비트 하나만 이용

        • 일정 시간 간격마다 모든 페이지의 접근 비트를 0으로 초기화함

        • 접근비트의 초기값은 0으로 설정되어 있고, 만약 페이지가 참조되었다면 1로 설정됨

      • 페이지를 원형으로 연결함

        • 스왑영역으로 옮길 페이지를 포인터로 가르키는데, 이 포인터를 클락 핸드라고 부름

        • 클락 핸드는 시계방향으로 돌게됨

        • 만약 Page Fault가 발생해서 스왑영역으로 보내야하는 상황이 나오면, 클락 핸드는 현재 참조하고 있는 페이지의 접근비트를 봄

        • 만약 접근비트가 1이라면 해당 접근비트를 0으로 바꾸고, 클락핸드가 다음 페이지를 가르킴

        • 이렇게 반복하다가 접근비트가 0인 페이지를 발견하면, 해당 페이지를 스왑영역으로 보냄

      • 향상된 클락 알고리즘(Enhanced Clock Algorithm)

        • 이 알고리즘은 접근비트만 이용하는 것이 아니라 변경비트까지 봄

        • 스왑 영역으로 보내지는 순위가 가장 높은 것은 접근비트가 0이고, 변경비트도 0인 페이지임

        • 그 다음으로 접근비트가 0, 변경비트가 1인 페이지임

        • 그 다음으로 접근비트가 1, 변경비트가 0인 페이지임

        • 마지막으로 접근비트가 1, 변경비트가 1인 페이지가 교체됨

    • FIFO를 사용하는 경우

      • LRU에서는 접근비트를 이용하는데, 하드웨어적으로 접근비트를 지원하지 않는 시스템에서는 FIFO를 이용할 수 밖에 없음

      • 어쩔 수 없이 FIFO를 이용하기 위해 성능을 높이는 방법을 고안함

      • 2차 기회 페이지 교체 알고리즘

        • FIFO방식에서 자주 사용하는 페이지에게는 또 한번의 기회를 줌

        • FIFO방식과 동일하게 동작하지만, 만약 Page Fault없이 페이지 접근에 성공했다면 해당 페이지를 큐의 맨 뒤로 이동시켜 수명을 연장시켜주는 방식

        • 이 알고리즘은 LRU보다는 안좋고, FIFO보다는 좋음

  • 스레싱과 워킹셋

    • CPU 스케줄링

      • CPU 사용률을 높이는 것이 목표

        • CPU 사용률을 높이기 위해서는 동시에 실행하는 프로세스의 수, 멀티프로그래밍의 정도를 올리는 것

        • 동시에 실행하는 프로세스의 수가 늘어나면, 어떤 프로세스가 I/O작업으로 CPU를 사용할 수 없을 때 다른 프로세스로 컨텍스트 스위칭을 해서 CPU 사용률을 높일 수 있음

        • CPU 사용률을 위해 멀티프로그래밍의 정도를 높였으면, 프로세스들이 필요로하는 공간이 있기때문에 물리메모리에 프레임을 할당해야함

        • 물리메모리의 크기는 한계가 있기 때문에 모든 프로세스의 모든 프레임을 물리메모리에 올릴 수 없고, 일부는 스왑영역에 저장됨

      • 멀티프로그래밍 정도가 늘어나는 경우에 문제가 나타남

        • 멀티프로그래밍 정도가 늘어나면 제한된 물리메모리에 모든 프로세스를 올려야하고, 당장 실행되는 프레임을 제외한 나머지 프레임들은 스왑영역에 저장되고 Page Fault가 많이 발생하게 됨

        • CPU가 작업하는 시간보다 스왑작업의 시간이 더 길어지고, CPU 사용률은 떨어지게됨

        • CPU 스케줄러는 CPU 사용률이 낮아지면, 더 많은 프로세스를 메모리에 올리게되고, 이렇게 반복하다보면 어느새 CPU 사용률이 0에 가깝게 떨어지게됨

        • 스레싱

          • CPU 사용률을 높이려했지만 오히려 더 떨어지는 상황

          • 근본적인 원인은 물리메모리의 크기가 부족한 것

          • 하드웨어적으로 해결하려면 메모리 크기를 늘리면 됨

            • 그러나 4GB 램에서 16GB 램으로 올려도 성능향상을 느끼기 힘듦

            • 현재 메모리가 프로세스들이 작업을 하는데 충분한 크기라서 스레싱이 발생하지 않는다면 크기를 늘려도 별 다른점이 없기 때문임

          • 운영체제가 스레싱을 소프트웨어적으로 해결하기 위한 방법

            • 한 프로세스가 실행될 때 너무 많은 페이지를 할당하면 다른 프로세스가 사용할 페이지가 줄어들기 때문에 효율이 떨어지게됨

            • 반대로 너무 적은 페이지를 할당하면 빈번한 Page Fault가 발생하고, 스왑요청이 많아 스레싱이 발생하게됨

            • 이를 해결하기 위한, 프로세스가 실행되는 동안 해당 프로세스에게 맞는 적절한 페이지 수 결정 방법

              • 프로세스가 실행되면 일정량의 페이지를 할당 후, 만약 Page Fault가 발생하면 더 많은 페이지를 할당하고, 반대로 Page Fault가 너무 적게 발생하면 페이지를 과하게 할당해 메모리가 낭비되는 것이라고 판단하고 페이지를 회수함

            • 어떤 페이지를 유지할 것인지 결정 방법

              • 지역성 이론을 따름

              • 현재 메모리에 올라온 페이지는 다시 사용할 확률이 높기 때문에 하나의 세트로 묶어서 메모리에 올림 → 워킹셋

              • 워킹셋은 프로세스가 준비상태에서 실행상태가 되는 컨텍스트 스위칭을 할 때 사용됨

Section 9. 입출력

  • 주변장치(I/O 디바이스, 저장장치)

    • 주변장치 종류

      • 그래픽카드, 하드디스크, SSD, 키보드, 마우스 등이 있음

         

        • 주변장치들은 메인보드에 있는 버스로 연결됨

      • 버스

         

        • Address 버스, Data 버스, Control 버스로 이루어져 있음

        • I/O 디바이스는 이 세가지 버스를 따로 받을 수 있음

      • 외부 인터페이스

        • 각 하드웨어에 맞게 존재함

      • 각종 레지스터

        • 장치의 상태와 데이터를 보관할 수 있음

        • 입출력 작업을 할 때 데이터를 저장하는 역할을 함

        • 값들은 CPU가 사용하기위해 메모리로 이동되기도 함

    • 데이터의 전송단위에 따른 주변장치 분류

      • 데이터의 전송단위가 캐릭터(글자)인지, 블록인지에 따라 나뉨

        • 캐릭터 디바이스

          • 마우스, 키보드, 사운드카드, 직별렬포트 등

          • 데이터 전송 단위가 캐릭터(글자)로 상대적으로 크기가 작음

        • 블록 디바이스

          • 하드디스크, SSD, 그래픽카드 등

          • 데이터 전송 단위가 블록(범위)로 상대적으로 크기가 큼

    • 각 장치 세부 설명

      • 버스

         

        • 예전에는 주변장치들을 하나의 버스로 연결해서 사용함

        • CPU가 작업을 하다가 I/O 명령을 만나면 직접 입출력장치에서 데이터를 가져왔는데 입출력중에는 다른 작업을 하지 못했기 때문에 CPU사용률이 떨어짐

        • 이를 해결하기 위해 입출력 제어기(I/O Controller)와 여러개의 버스가 추가됨

           

        • CPU는 I/O 명령을 만나면 입출력 제어기에게 입출력작업을 맡기고 다른 작업을 실행함

        • 입출력 제어기

          • 시스템 버스, 입출력 버스로 구분하여 두 개의 채널을 가지고 있음

          • 시스템 버스

            • 고속으로 작동하는 CPU와 메모리가 사용

          • 입출력 버스

            • 주변장치가 사용

          • 입출력 버스는 세부적으로 느린장치와 빠른장치를 구분하기 위해 다시 고속 입출력 버스, 저속 입출력 버스 두 개의 채널로 나뉨 → 느린장치와 빠른장치로 구분 해 속도차이로 인한 병목현상을 해결함

      • 그래픽 카드

        • 그래픽 카드가 다루는 데이터는 매우 대용량이라 고속 입출력 버스로도 감당이 안됨

        • 그에 따라 그래픽 카드는 입출력 버스에 있지 않고, 시스템 버스에 바로 연결해 사용함

      • 입출력 제어기

        • 입출력 제어기는 여러 주변장치를 처리하는데 입출력 버스에서 온 데이터를 메모리로 옮김

        • 메모리는 CPU의 명령으로 움직이기 때문에 입출력 제어기가 메모리에 접근하기 위해서는 CPU가 필요함

           

        • 입출력 제어기가 CPU의 도움이 필요없도록 DMA(Direct Memory Access - 직접 메모리 접근) 제어기가 추가됨

        • 입출력 제어기는 DMA로 데이터를 직접 메모리에 저장하거나 가져올 수 있음

        • Memory Mapped I/O

          • CPU와 DMA가 사용하는 메모리가 겹치지 않도록 CPU가 사용하는 메모리 영역과 DMA가 사용하는 메모리 영역을 나눔

  • 마우스/키보드

    • 마우스

      • 볼 마우스

        • 회전을 감지해서 움직임을 처리하는 방식

      • 광학 마우스

        • 아래쪽에 작은 카메라가 표면으로 초당 1500회가 넘는 사진을 찍어 마우스의 디바이스 컨트롤러 내 DSP(Digital Signal Processor)로 보냄

        • DSP는 이 사진을 분석해 마우스의 X축 좌표와 Y축 좌표 움직임을 캐치함

        • DSP가 마우스의 움직임과 클릭같은 데이터를 감지하면, 디바이스 컨트롤러는 CPU에게 인터럽트를 보내고, 마우스 드라이버가 동작해서 데이터를 읽어감

        • 마우스 드라이버는 운영체제에게 이벤트 신호를 주는데, 운영체제는 이 이벤트 Foreground 애플리케이션으로 전달해주고 해당 애플리케이션은 받은 마우스 이벤트 처리를 함

    • 키보드

      • 사용자가 키보드 버튼을 누르면 키보드의 디바이스 컨트롤러가 어떤 키를 입력 받았는지 알아냄

      • CPU에게 인터럽트를 보내고 키보드 드라이버는 운영체제에게 이벤트를 보냄

      • 운영체제는 Foreground 애플리케이션으로 이 이벤트를 전달해주고, 애플리케이션에서 해당 키에 맞는 동작을 수행함

  • 하드디스크/Flash Memory(SSD)

    • 하드디스크 구조

       

      • spindle

      • platter

        • 여러개의 트랙으로 구성됨

        • 표면에 자성이 있어 N극을 띄면 0, S극을 띄면 1로 인식함

        • 보통 하드디스크의 플래터 수는 2개 이상임

        • 실린더(cylinder)

          image

          • 트랙은 다시 여러개의 섹터로 나뉘는데, 섹터가 하드디스크의 가장 작은 단위임

             

      • disk Arm

        • 읽기/쓰기 헤드로 플래터의 표면을 읽음

      • read/write head

        • 헤드는 disk Arm에 고정되어 있기 때문에 모든 헤드는 항상 같이 움직임

        • 헤드가 움직이면 이 헤드들은 여러 개의 플래터를 가리키게 되는데, 이때 여러개의 플래터에 있는 같은 트랙의 집합을 실린더(cylinder)라고 부름

    • 하드디스크에서 데이터 읽어오는 예시

      • 유저프로세스가 하드디스크의 특정 섹터에 접근을 위해 요청을 보냄 (ex, 실린더 C로 가서 트랙 B에 있는 섹터 D를 읽어라)

      • 디스크암은 헤드를 실린더 C로 이동시키는데, 이를 Seek라고 부름

      • 헤드를 실린더로 이동시키는데 걸리는 시간을 Seek Time이라고 부름 → 이것때문에 하드디스크가 굉장히 느림

      • 트랙 B의 섹터 D가 헤드에 닿을 때까지 스핀들을 회전시키고, 헤드에 섹터 D가 읽히면 작업이 끝남

    • Flash Memory

      • 요즘은 하드디스크보다 Flash Memory를 더 많이 사용함

      • 데스크탑에는 Flash Memory 이점으로 많은 사람이 SSD를 사용함

      • 핸드폰, 테블릿은 하드디스크를 넣을 큰 공간이 없어서 Flash Memory를 사용함

      • 하드디스크 vs Flash Memory

        • 하드디스크

          • 기계적으로 헤드를 움직여 속도가 많이 느리고 소음도 남

          • 자기적으로 처리하는 하드디스크는 자석을 갖다대면 데이터가 손상됨

          • 스핀들처럼 회전축같은 것들이 있어서 충격에 매우 약함

        • Flash Memory

          • 전기적으로 읽기 때문에 굉장히 빠르고 조용함

          • 자석을 갖다대도 데이터가 안전함

          • 충격에 약하지 않음

          • 그러나 특정한 지점에 데이터를 썼다면 덮어쓰기가 불가능 하다는 단점이 있음 똑같은 지점에 데이터를 쓰려면 기존에 있던 데이터를 지우고 새로 써야하는데, Flash Memory는 지우기 가능한 횟수가 정해져있음(읽기/쓰기를 반복하면 망가져 사용할 수 없음)

 

Section 10. 파일시스템

  • 파일과 파일시스템

    • 파일들을 하드디스크나 SSD와 같은 저장장치에 저장됨

    • 사용자가 운영체제에게 요청 시, 운영체제가 하드디스크에 안전하게 저장함

    • 운영체제는 파일 관리를 위해 파일 관리자를 둠 → 파일 시스템

    • 파일 시스템

      • 파일 관리자는 가상메모리에서 메모리 관리자가 페이지 테이블을 이용해서 가상주소를 물리주소로 변환하는 것처럼 파일 테이블을 이용해서 파일을 관리함

      • 파일 시스템의 기능

        • 파일과 디렉토리를 만듦

        • 파일과 디렉토리의 수정, 삭제를 함

        • 다른 사용자로부터 파일을 보호하기 위해 접근권한을 관리함 (요즘 운영체제는 다중 사용자 기능을 지원하기 때문에 파일을 보호하기 위해서 꼭 필요한 기능임)

        • 파일의 내용이 손상되지 않도록 무결성을 보장함

        • 예기치 못한 사고로부터 백업과 복구를 함

        • 파일을 암호화해 파일을 보호함

      • 파일시스팀 전송단위

        • 하드디스크와 Flash Memory는 블록 디바이스임 따라서 전송단위가 블록임

        • 저장 단위는 블록이지만, 사용자는 바이트 단위로 파일에 접근이 가능해야하기 때문에 파일관리자가 중간에서 관리해줌

      • 파일확장자

        • 유닉스 운영체제에는 파일확장자가 없음

        • 윈도우즈는 파일확장자가 있음

        • 파일 내부 구성

          • 헤더, 데이터로 이루어져있음

          • 헤더

            • 파일의 속성들이 담겨 있음

      • 파일 디스크립터(File Descriptor)

        • 운영체제는 파일을 관리하기 위해 정보를 보관하는 파일제어블록(File Control Block, FCB)을 가지고 있는데, 이를 파일 디스크립터(File Descriptor)라고 부름

        • 파일 디스크립터는 파일마다 독립적으로 존재하고, 저장장치에 존재하다가 파일이 오픈되면 메모리로 이동함

        • 파일 디스크립터는 파일시스템(운영체제)이 관리하고, 사용자가 직접 참조할 수는 없음

        • 사용자는 파일시스템이 건내준 파일 디스크립터로 파일에 접근할 수 있음

      • 파일 종류 분류

        • 파일은 데이터의 집합으로, 데이터의 집합을 어떻게 구성하느냐에 따라 종류를 나눌 수 있음

        • 순차파일구조

          • 파일의 내용이 연속적으로 이어진 상태 (ex, 카세트테이프)

          • 파일시스템이 사용자에게 전달해준 파일디스크립터는 파일의 맨 앞에 위치해서 사용자가 쓰거나 읽기를 시작하면 처음부터 진행함

          • 파일의 다른영역으로 가고 싶을 때 - lseek함수를 이용해 파일디스크립터 위치를 옮김

             

          • 장점

            • 모든 데이터가 순서대로 기록되기 때문에 공간의 낭비가 없고 구조가 단순함

          • 단점

            • 특정지점에 바로 이동이 어려워 데이터를 삽입하거나 삭제하려면 탐색하는데 시간이 많이 걸림

        • 직접파일구조

          • 저장하려는 데이터를 해시함수를 통해 저장위치를 결정하는 파일구조

          • 자료구조에서 해시 테이블이라는 이름으로 불리는 방식

          • json도 이 방식임

             

          • 장점

            • 해시함수를 이용하기 때문에 데이터 접근이 굉장히 빠르다는 것

          • 단점

            • 해시함수의 선정이 굉장히 중요하기 때문에 해시함수를 잘 골라야한다는 점과 저장공간이 낭비될 수 있다는 점

        • 인덱스파일구조

          • 순차접근과 직접접근 방식의 장점을 취한 것으로 두가지 방식 모두 가능함

          • ex, 음악재생 프로그램의 재생목록

             

  • 디렉토리

    • 디렉토리란?

      • 파일을 하나의 공간이 아닌, 관련있는 파일을 모아둘 수 있게 하기 위함

      • 한 개 이상의 파일을 가질 수 있고, 자식 디렉토리도 가질 수 있음

      • 디렉토리는 여러층으로 구성됨

        • 최상위에 있는 디렉토리 - 루트 디렉토리

        • 유닉스, 리눅스에서는 루트 디렉토리를 “/”로 표시함, 디렉토리 별 구분을 위해서도 “/”를 사용함

        • 윈도우즈는 루트 디렉토리를 파티션 이름으로 사용하는데, 보통 “C:”으로 표시함

        • 윈도우즈는 디렉토리와 디렉토리 구분을 “\”로 함

        • 디렉토리도 파일임. 단지 일반 파일에는 데이터가 저장되어 있고, 디렉토리에는 파일 정보가 저장되어 있음

           

    • 디렉토리 구조

      • 과거 - 루트 디렉토리에만 하위 디렉토리 존재했었음

      • 파일이 많아지면서 다단계 디렉토리구조가 등장함

      • 다단계 디렉토리구조

        • 어떤 디렉토리에서도 하위 디렉토리를 만들 수 있는 트리구조

        • 운영체제는 트리구조에서 순환이 생기는데, 바로가기 기능이 있기 때문임

           

  • 파일과 디스크

    • 파일은 메모리와 비슷한데, 페이징과 같이 전체 디스크 공간을 일정한 크기로 나누고, 그 공간에 주소를 할당해 관리함

    • 일정한 크기로 나눈 공간을 파일시스템에서는 블록이라고 함 (메모리에서는 페이지라고 부름)

    • 한 블록의 크기는 1~8KB

    • 파일시스템은 파일정보를 파일테이블로 관리하는데, 파일이 시작하는 블록의 위치정보도 담겨있음

    • 파일 내 블록 분류

      • 여러 개의 블록들로 이루어져 있는 하나의 파일에서, 그 블록들이 어떻게 연결되었는지에 따라 분류됨

      • 연속할당

        • 파일을 구성하는 블록들을 디스크에 연속적으로 저장하는 방식임

        • 파일의 시작 블록만 알면 파일의 전체를 찾을 수 있음

        • 메모리에서 세그멘테이션 기법처럼 외부 단편화가 발생하기 때문에 실제로 사용되지 않는 방식임

      • 불연속할당

        • 디스크에 비어있는 공간에 데이터를 분산해 저장하는 방식

        • 분산된 블록은 파일시스템이 관리함

        • 연결할당, 인덱스 할당이 있음

        • 연결할당

          • 파일에 속한 데이터를 연결리스트로 관리함

          • 파일테이블에는 시작 블록에 대한 정보만 저장하고, 나머지는 연결리스트를 이용해 다른 블록에 접근하는 방식

             

        • 인덱스할당

          • 테이블의 블록포인터가 데이터 블록에 직접 연결하는 것이 아니라 데이터들의 인덱스를 가지고 있는 인덱스 블록을 연결함

             

          • 인덱스 할당은 데이터가 많아서 테이블이 꽉 찬 경우 인덱스 블록을 더 만들어서 연결하기 때문에 테이블을 확장할 수 있음

          • 파일의 크기가 작다면, 데이터를 바로 참조하는 블록 포인터를 이용하고, 파일의 크기가 크다면 간접 포인터를 이용해 많은 데이터에 접근할 수 있음

          • 만약 더 큰 데이터가 필요하다면, 이중 간접 포인터, 삼중 간접 포인터를 이용할 수 있음 (i-node라는 이름으로 유닉스와 리눅스에서 많이 사용되고 있음)

    • free block list

      • 빈 공간을 찾기위해 매번 모든 메모리를 찾지 않기 위해 빈 공간을 모아둠

      • 만약 특정 파일 삭제 시, 파일시스템은 파일의 모든 정보를 지우는 것이 아니라 파일 테이블의 헤더를 삭제하고 free block list에 추가함

 


회고

  • 일주일 동안 스스로 칭찬하고 싶은 점, 아쉬웠던 점, 보완하고 싶은 점

    • 칭찬하고 싶은 점 : 이번주 강의가 조금 어렵게 느껴졌지만 포기하지 않고 끝까지 잘 학습한 점

    • 아쉬웠던 점 : 이번주에 회사일이 많아서 내용 중 이틀 치를 몰아서 듣게 되었는데 충분한 학습을 하지 못했다는 아쉬움이 남음

    • 보완하고 싶은 점 : 중간중간 이해가 안되는 부분들이 있었는데, 그 부분을 반복학습 해야겠습니다🙌

  • 다음주에는 어떤 식으로 학습하겠다는 스스로의 목표

    • 수료식 전까지 따로 스터디 스케쥴이 없는 것 같으니 이번주 강의를 다시한번 봐야겠습니다💪

댓글을 작성해보세요.

채널톡 아이콘