1. 파일시스템 일반


파일시스템이 하드디스크에 저장하는 정보는 메타 데이터(meta data)와 사용자 데이터(user data)로 나뉜다.

메타 데이터: 파일이름, 파일의 생성시간, 실제 데이터 블록을 인덱싱 하기 위한 정보 등

사용자 데이터: 사용자가 실제로 기록하려던 내용


보통 파일시스템에서 디스크 블록의 크기는 4KB이다.



2. 디스크 구조와 블록 관리 기법



디스크는 원판(platter), 팔(arm), 헤드(head)로 구성된다.

원판에는 원 모양의 트랙(track)들이 존재하며, 모든 원판에서 같은 위치를 갖는 트랙들의 집합을 실린더(cylinder)라고 한다.


트랙은 다시 몇 개의 섹터(sector)로 구분된다. 섹터는 디스크에서 데이터를 읽거나 기록할 때 기본 단위이며, 일반적으로 512byte이다.


디스크에서 데이터를 접근하는 데 걸리는 시간은 탐색 시간(seek time), 회전 지연 시간(rotational latency), 데이터 전송 시간(transmission time)이라는 세 가지로 구성된다.


탐색시간: 헤드를 요청한 데이터가 존재하는 트랙 위치까지 이동하는데 걸리는 시간

회전시간: 요청한 섹터가 헤드 아래로 위치될 때까지 디스크원판을 회전시키는 데 걸리는 시간

데이터전송시간: 헤드가 섹터의 내용을 읽거나 또는 기록하는데 걸리는 시간



디스크 블록을 할당하는 방법에는 크게 연속(sequential)할당과 불연속(non-sequential)할당 두 가지 방법이 있다.


불연속 할당 방법: 디스크 블록들을 연속적으로 저장하지 않는다. 대신 파일에 속한 디스크 블록들이 어디에 위치하고 있는지에 대한 정보를 기록해 두어야 한다. 이를 위한 방법으로 블록체인 기법, 인덱스 블록 기법, FAT(File Allocation Table)기법 등이 있다.


블록체인 기법: 같은 파일에 속한 디스크 블록들을 체인으로(각 블록에 포인터를 두어 다음 블록 위치를 기록, linked list와 유사) 연결해 놓는 방법이다. lseek()같은 시스템 콜을 사용하여 파일의 끝 부분을 읽으려면 어쩔 수 없이 앞부분의 데이터 블록을 읽어야 하며, 중간 한 블록이 유실된 경우 나머지 데이터까지 모두 잃게 된다.


인덱스블록 기법: 



내부단편화

프로세스가 요청한 메모리보다 큰 메모리를 할당했을 경우에 내부단편화가 발생한다. 즉 실제로 요청한 메모리 보다 할당 단위가 커서 해당 단위 자원 내에서 사용하지 않는 부분이 있을 때 발생한다.


외부단편화

남아있는 메모리의 합에 비해서, 실제 할당 단위가 작아서 메모리를 사용할 수 없는 경우이다. 남은 파티션들이 연속되면 사용할 수 있지만, 그렇지 않으면 할당 단위가 작아서 프로세스가 올라갈 수 없는 형태를 말한다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
using namespace std;
 
int main()
{
    int num1 = 1020;        // 변수 선언
    int &num2 = num1;        // 참조자 선언
 
    num2 = 3047;
 
    cout << "Val: " << num1 << endl;        // 3047
    cout << "Ref: " << num2 << endl;        // 3047
 
    cout << "Val: " << &num1 << endl;
    cout << "Ref: " << &num2 << endl;        // &num1 과 &num2의 값은 같다
                                            
    int &num3 = num2;                        // 참조자를 대상으로 참조자 선언
    cout << "num2: " << num2 << endl;
    cout << "num3: " << num3 << endl;
 
    // int &ref = 20;        // 참조자는 변수에 대해서만 선언 가능
    // int %ref;            // 참조자는 미리 선언했다가 후에 참조 불가, 참조 대상 변경 불가
    // int &ref = NULL;     // NULL로 초기화 불가
 
    int num = 12;
    int *ptr = &num;
    int **dptr = &ptr;
 
    int &ref = num;            // 변수 참조
    int *(&pref) = ptr;        // 포인터 변수 참조
    int **(&dpref) = dptr;    // 더블 포인터 변수 참조
 
    cout << ref << endl;
    cout << *pref << endl;
    cout << **dpref << endl;
}
cs




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <iostream>
using namespace std;
 
// Call-by-value 함수
// 주소 값을 이용해 함수의 외부에 선언된 변수에 접근하는 형태가 아님
int* SimpleFunc(int *ptr)
{
    return ptr + 1;
}
 
// Call-by-reference
void SwapByRef(int &ref1, int &ref2)
{
    int temp = ref1;
    ref1 = ref2;
    ref2 = temp;
}
 
// const로 참조자를 선언시, 참조자 ref를 통한 값의 변경을 허용하지 않음
void HappyFunc(const int &ref)
{
 
}
 
 
// 반환형이 참조형
int& RefRetFuncOne(int &ref)
{
    ref++;
    return ref;
}
 
// 반환형이 값
int RefRetFuncTwo(int &ref)
{
    ref++;
    return ref;
}
 
// 지역 변수를 참조형으로 반환하면 안된다.
int& RefRetFuncThree(int n)
{
    int num = 20;
    num += n;
    return num;
}
 
int main()
{
    int val1 = 10;
    int val2 = 20;
    SwapByRef(val1, val2);
    cout << "val1: " << val1 << endl;
    cout << "val2: " << val2 << endl;
 
 
    // 반환형이 참조형인 경우, 반환 값을 무엇으로 저장하느냐에 따라 결과에 차이가 있다.
    int num1 = 1;
    int &num2 = RefRetFuncOne(num1);    // 참조형으로 반환된 값을 참조자에 저장
    int num3 = RefRetFuncOne(num1);        // 참조형으로 반환된 값을 변수에 저장
 
    num1++;
    num2++;
    num3++;
    cout << "num1: " << num1 << endl;
    cout << "num2: " << num2 << endl;
    cout << "num3: " << num3 << endl;
 
    // 반환형이 값인 경우, 값이 반환되므로 반드시 변수에 저장해야 한다.
    int num4 = 1;
    int num5 = RefRetFuncTwo(num4);
 
    num4 += 50;
    num5 += 100;
    cout << "num4: " << num4 << endl;
    cout << "num5: " << num5 << endl;
 
    // int &num6 = RefRetFuncTwo(num4);        // 에러
 
    int &num7 = RefRetFuncThree(10);        // 지역 변수는 소멸되므로 참조형으로 반환하면 안된다.
    cout << "num7: " << num7 << endl;
}
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;
 
int Adder(const int &num1, const int &num2)
{
    return num1 + num2;
}
 
int main()
{
    const int num = 20;
//    int &ref = num;                    // 에러 참조 불가
 
    const int &ref = num;            // 상수화된 변수에 대한 참조자 선언
 
    const int &ref2 = 50;            // 상수 참조 가능, 임시 변수 상수화
 
    cout << Adder(34<< endl;    // const의 상수 참조
}
cs


+ Recent posts