| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- BFS
- Optimization
- Seoul National University
- do it! 알고리즘 코딩테스트: c++편
- Machine Learning
- paper review
- Python
- C++
- System Call
- Humble
- Baekjoon
- computer vision
- Linux
- cs231n
- Process
- deep learning
- file system
- On-memory file system
- DFS
- CNN
- Multimedia
- RNN
- SQLD
- 밑바닥부터 시작하는 딥러닝2
- ROS2
- Operating System
- CPP
- Robocup@Home 2026
- Data Science
- Gentoo2
- Today
- Total
newhaneul
[Operating System] Final Exam Class 1 Fall 2018 (Week 9-10, 11-12: File System, Memory File System) 본문
[Operating System] Final Exam Class 1 Fall 2018 (Week 9-10, 11-12: File System, Memory File System)
뉴하늘 2025. 12. 8. 20:36본 포스팅은 인하대학교 김기창 교수님의 [202502-EEC4406-001] Operating System을 수강하고 공부한 내용을 정리하기 위한 포스팅입니다.
Question:
1. Try "ln" command in "myfd" and show all the changes in the ext2 file system.
myfd 디스크 위에서 ln 명령을 실행해 보고, 그에 따라 ext2 파일 시스템 내부에서 어떤 변화들이 일어나는지 모두 보여라.
mount –o loop myfd temp
cd temp
ls
f1 lost+found
ln f1 f2
ls
f1 f2 lost+found
cd
umount temp
xxd –g1 myfd > x
vi x
2. Try "ln –s" command in "myfd" and show all the changes in the ext2 file system.
myfd 디스크 위에서 ln -s 명령을 실행해 보고, 그에 따라 ext2 파일 시스템 내부에서 어떤 변화들이 일어나는지 모두 보여라.
ln -s f1 f3
3. Show and explain the kernel code that implements dup() system call as detail as possible.
dup() 시스템 콜을 구현하는 커널 코드를 가능한 한 자세하게 보여 주고 설명하라.
4. Modify the kernel such that it displays all page fault addresses caused by "ex1" process. Compare this result with the virtual address map (/proc/pid/maps) of “ex1” and explain why the page faults have happened for the faulted addresses. Write ex1 as follows:
커널을 수정하여 "ex1" 프로세스에서 발생하는 모든 페이지 폴트 주소를 출력하도록 하라. 그 다음 이 결과를 "ex1"의 가상 주소 맵(/proc/pid/maps)과 비교하고, 각 페이지 폴트가 왜 그 주소에서 발생했는지 설명하라. (= 2018 Class 1과 동일하므로 생략)
void main(){
int x;
x=3;
for(;;);
}
(1) Answer:
1. myfd 디스크 생성

먼저 "myfd"의 디스크를 위와 같이 생성할 수 있습니다. 'dd bs=1024 count=1440 if=/dev/zero of=myfd' 명령어를 사용하여 생성할 수 있고, 디스크의 정보는 아래와 같습니다.
- block size = 1024 (=1K Bytes)
- count = 1440 (block 개수)
- if=/dev/zero (입력 파일)
- of=myfd (출력 파일 이름이 myfd인 디스크 생성
따라서 총 1.44 MB (1KB * 1440 = 1440KB) 크기의 디스크를 생성합니다.
2. 기본적인 디스크 구조
| Name | Super Block | Group Descriptor | DBM | IBM | Inode Table |
| Block Num | 1 | 2~7 | 8 | 9 | 10~32 |
| Address | 0x400 | 0x800 | 0x2000 | 0x2400 | 0x2800 |
처음에 디스크 안에 무수히 많은 0으로 채워진 "/dev/zero" 파일이 입력되었기 때문에 0x400에 위치하는 Super Block은 모두 0으로 되어져 있음을 확인할 수 있습니다.


이제 "mkfs -t ext2 myfd" 명령어를 이용해 myfd를 "ext2" 형식으로 변환해줍니다.

변환한 다음 myfd 디스크의 Super Block 위치를 다시 확인해보면, 이전과 다르게 정보들이 담겨져 있음을 확인할 수 있습니다.

Super Block이 시작되는 위치에서 값들의 의미들은 아래와 같습니다.
- 0~4Byte (b8 00 00 00): m_inodes_count에 해당되고, 10진수로 변환하면 184임을 알 수 있다. 즉, 최대 184개의 inodes를 사용할 수 있다.
- 5~8Byte (a0 05 00 00): m_blocks_count에 해당되고, 10진수로 변환하면 1440임을 알 수 있다. 즉, 블록 크기 1KB로 format했을 때의 총 Block 수와 일치한다.
- 9~12Byte (48 00 00 00)/ 13~16Byte (71 05 00 00): 각각 m_r_blocks_count와 m_free_blocks_count에 해당되고, 10진수로 변환하면 각각 72, 1393임을 알 수 있다.
3. mount

"temp" 디렉토리를 만들고 "mount -o loop myfd temp" 명령어를 통해 myfd 디스크와 temp 디렉토리를 서로 연결해주었습니다.
-------- 기본 가정 --------
지금까지가 문제의 파일 시스템 변화를 보기 전까지의 기본 가정입니다. 이 상태가 기본적으로 유지되었다고 전제 하에 디스크와 디렉토리를 서로 연결하고 디렉토리 내에 파일 변화를 준 뒤 파일 시스템을 분석하는 것입니다.
우선 디렉토리 안에 새로운 파일이나 디렉토리를 만들면 DBM (Data Bitmap), IBM (Inode Bitmap)의 비트가 1만큼 증가하게 됩니다. 그 변화를 먼저 확인해보겠습니다.
temp가 빈 디렉토리일 때의 DBM (0x2000)과 IBM (0x2400)을 분석합니다.

DBM (0x2000)

IBM (0x2400)

temp 디렉토리 안에 "f1" 파일을 새로 생성해주었습니다.

DBM (0x2000)

DBM의 경우 'ff ff ff ff ff 3f' → 'ff ff ff ff ff 7f'로 변화한 것을 확인할 수 있습니다.
변환을 진행하면 '3f ff ff ff ff' → '7f ff ff ff ff'이 되고, 16진수를 4비트로 변환하면
'0011 1111 1111 1111 1111 1111 1111 1111 1111 1111' → ' 0111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 '이 된다. 따라서 Block 개수는46개에서 47개로 바뀌었고 1 Block이 더 사용되었음을 알 수 있습니다.
IBM (0x2400)

IBM의 경우 'ff 07' → 'ff 0f'로 변화한 것을 확인할 수 있습니다.
변환을 진행하면 '07 ff' → '0f ff'이 되고, 16진수를 4비로 변환하면
'0000 0111 1111 1111' → '0000 1111 1111 1111'이 된다. 따라서 Block 개수는11개에서 12개로 바뀌었고 1 Block이 더 사용되었음을 알 수 있습니다.
root Inode table (0x2880)

root 디렉토리에 대한 정보를 확인하기 위해 Inode table의 주소인 0x2800으로 이동합니다. 이때 root 디렉토리는 inode table 2번에 위치하기 때문에 root 디렉토리의 inode table 주소는 0x2880입니다. 여기에서 확인해야할 것은 Block location을 가리키는 (2100 0000) 입니다.
root 디렉토리의 파일 위치는 앞서 확인한 block location을 사용하여 0x21 * 0x400 = 0x8400임을 계산할 수 있습니다.

0x8400을 확인해보니 root 디렉토리 안에 생성된 f1 파일이 존재함을 확인하였습니다. struct를 참고하여 해석해 보면
1)
m_inode = '02 00 00 00' → '00 00 00 02 ' → 2번 inode
m_inode = '0c 00' → '00 0c' → 12 recode length
m_name_len = '01' → 1 name length
m_file_type = '02' → 2 directory file
m_name = '2e 00 00 00' → “.” name
2)
m_inode = '02 00 00 00' → '00 00 00 02' → 2번 inode
m_inode = '0c 00' → '00 0c' → 12 recode length
m_name_len = '02' → 2 name length
m_file_type = '02' → 2 directory file
m_name = '2e 2e 00 00' → “..” name
3)
m_inode = '0b 00 00 00' → '00 00 00 0b' → 11번 inode
m_inode = '14 00' → '00 14' → 20 recode length
m_name_len = '0a' → 10 name length
m_file_type = '02' → 2 directory file
m_name = '6c 6f 73 74 2b 66 6f 75 6e 64' → “lost+found” name
4)
m_inode = '0c 00 00 00' → '00 00 00 0c' → 12번 inode
m_inode = 'd4 03' → '03 d4' → 980 recode length
m_name_len = '02' → 2 name length
m_file_type = '01' → 1 file
m_name = '66 31 00 00' → “f1” name
"f1" 파일의 inode가 12번임을 확인하였으니, 0x2800 + 0x80 * (12 - 1) = 0x2d80 계산을 통해 "f1" 파일의 inode table 주소로 이동합니다.
f1 Inode Table (0x2d80)

0x2d80에서 "f1'의 block location을 확인한 결과 0x2f = 47번째 block에 위치하는 것을 알 수 있습니다.
따라서 "f1"의 파일 주소는 0x2f * 0x400 = 0xbc00에 존재하고 있습니다.
f1 File Location (0xbc00)

파일 주소로 이동하여 확인해본 결과, "hi f1" 텍스트가 존재함을 알 수 있습니다.
이제 문제에서 요구한대로 '/root/temp' 으로 이동하고 'ln f1 f2'를 진행하여 원본 파일 "f1"과 동일한 데이터를 가리키는 또 다른 파일 이름 "f2"를 생성한 뒤 차이를 확인해보겠습니다.

이때 ln 명령어는 새 데이터 블록을 할당하지 않고, 새 inode도 만들지 않는다.
DBM (0x2000)

DBM의 경우 'ff ff ff ff ff 7f ' 그대로 비트 패턴에 변화가 없는 것을 확인할 수 있다. 따라서 DBM은 ln 명령어 전후로 값이 동일하다.
IBM (0x2400)

마찬가지로 IBM의 경우 'ff 0f' 그대로 비트 패턴에 변화가 없는 것을 확인할 수 있다. 따라서 IBM도 ln 명령어 전후로 값이 동일하다.
Root File Location (0x8400)

0x8400을 확인해보니 root 디렉토리 안에 생성된 f2 파일이 존재함을 확인하였습니다. struct를 참고하여 해석해 보면
5)
m_inode = '0c 00 00 00' → '00 00 00 0c' → 12번 inode
m_inode = 'c8 03' → '03 c8' → 968 recode length
m_name_len = '02' → 2 name length
m_file_type = '01' → 1 file
m_name = '66 32 00 00' → “f2” name
즉, "ln f1 f2" 명령어를 사용하여 생긴 변화는 root 디렉토리에서 "f2" 엔트리만 새로 생기고, inode 번호는 기존 f1과 같은 값을 갖는 것 뿐이다. inode가 갖기 때문에 "f1"과 "f2' 둘 다 동일한 데이터를 갖고 있는 것이다.
(2) Answer:
이번에는 "ln -s" 명령어를 실행해 보고, 그에 따라 파일 시스템 내부에서 어떤 변화들이 일어나는지 확인해본다.
ln -s f1 f3
위의 명령어는 새로운 파일 "f3"을 만들되, 심볼릭 링크로 생성하는 것이다. 즉, 내용에 "f1"이라는 문자열만 저장된다. 따라서 이번에는 inode가 새로 하나 생성되게 된다.


DBM (0x2000)

DBM의 경우 'ff ff ff ff ff 7f ' 그대로 비트 패턴에 변화가 없는 것을 확인할 수 있다. 따라서 DBM은 ln -s 명령어 전후로 값이 동일하다. 이를 통해 새로운 데이터 블록을 할당하지는 않는 것을 알 수 있다.
IBM (0x2400)

반면에 IBM의 경우 'ff 0f' → 'ff 1f'로 비트 패턴에 변화가 생긴 것을 확인할 수 있다.
변환을 진행하면 '0f ff' → '1f ff'이 되고, 16진수를 4비트로 변환하면
'0000 1111 1111 1111' → '0001 1111 1111 1111'이 된다. 따라서 Block 개수는12개에서 13개로 바뀌었고 1 Block이 더 사용되었음을 알 수 있다.
정리하면 "ln -s" 명령어 전 후로 새로운 inode가 생성되었음을 의미한다.
Root File Location (0x8400)

0x8400을 확인해보니 root 디렉토리 안에 생성된 f3 파일이 존재함을 확인하였습니다. struct를 참고하여 해석해 보면
6)
m_inode = '0d 00 00 00' → '00 00 00 0d' → 13번 inode
m_inode = 'bc 03' → '03 bc' → 956 recode length
m_name_len = '02' → 2 name length
m_file_type = '07' → 7 symbolic link
m_name = '66 33 00 00' → “f3” name
즉, "ln -s f1 f3" 명령어를 사용하면 데이터 블록을 사용하지 않으므로 DBM에 변화는 없고, 새로운 inode를 사용하여 IBM의 비트에만 변화가 생긴다. 또한 생긴 변화는 root 디렉토리에서 "f3" 엔트리를 통해 확인할 수 있다.
"/root/temp/f3" 파일의 inode가 13번임을 확인하였으니, 0x2800 + 0x80 * (13 - 1) = 0x2e00 계산을 통해 inode table 주소로 이동합니다.
f3 Inode Table (0x2e00)

0x2e00에서 "/root/temp/f2'의 block location을 확인한 결과 '66 31' → "f1"의 문자열이 담겨져 있는 것을 확인할 수 있습니다. 따라서 i_block 자리에 block location의 주소가 아니라 문자열 "f1"이 직접 저장되어 있습니다.
(3) Answer:
첫 번째 단계는 system call을 선언하는 것이다. 'arch/x86/kernel/syscall_table_32.S' 경로로 이동하여 98번 syscall을 수정한다.

98번 sys_final_dup으로 정의하였다.
두 번째 단계는 system call을 정의하는 것이다. 'fs/read_write.c' 경로로 이동하여 98번 syscall을 문제에서 요구한 사항을 만족하도록 구현한다.

syscall은 위와 같이 구현하였다. 현재 위치를 출력하기 위해 필요한 file, dentry 등의 자료구조는 아래와 같은 형태이다.
include/linux/sched.h

- current 포인터가 가리키는 데이터 타입에 해당된다.
include/linux/file.h

- current->files → struct files_struct *
include/linux/file.h

- current->files->fdt → struct fdtable *
include/linux/fs.h

- current->files->fdt->fd[i] → struct file *
- struct file 안에는 f_pos, f_op, f_dentry 등이 들어 있고, system call에서 사용하고 있는 f->f_pos, f->f_dentry가 이에 해당된다.
test5.c

세 번째 단계는 사용자 정의 파일 'test5.c'를 구현하는 것이다. 'test5.c'를 문제에서 요구한 사항을 만족하도록 구현한다. 사용자 정의 파일은 위와 같이 “f1” 파일을 읽은 뒤 fd2에 구현한 'sys_final_dup'의 출력값을 저장하고 실제로 dup가 잘 작동되는지 확인하도록 구현하였습니다.
/f1

현재 “f1” 파일에는 “hello1”가 저장되어 있고, “f1”에는 5byte를 초과하는 텍스트가 저장되어져 있습니다.
“test5.c” 파일을 컴파일하고 실행한 결과는 아래와 같습니다.

실행 결과를 보면 두 fd가 같은 파일 위치를 공유하고 있으므로 dup의 동작이 정상적으로 되었음을 알 수 있습니다.