https://www.yes24.com/Product/Goods/122109062
그림으로 배우는 리눅스 구조 - 예스24
선배가 옆에서 하나하나 알려주듯 친절히 설명해주는실습과 그림으로 배우는 리눅스 지식의 모든 것 * Go 언어와 Python, Bash 스크립트 실습 코드 제공* 이 도서는 『실습과 그림으로 배우는 리눅
www.yes24.com
우선 파일에 접근할 수 있는 권한은 커널이 가지고 있으며, 일반적으로 다음과 같은 인터페이스를 사용한다.
- 디바이스 파일을 조작
- 블록 장치에 구축한 파일 시스템을 조작(7장)
- 네트워크 인터페이스 카드(NIC)는 속도 문제로 디바이스 파일 대신 소켓(socket) 구조를 사용
이 장에서는 디바이스 파일을 사용해 파일에 접근하는 방법을 설명한다.
1. 디바이스 파일
디바이스 파일은 장치마다 존재하고, 예를 들면 저장 장치라면 /dev/sda나 /dev/sdb 같은 것들이 있다. 리눅스는 프로세스가 디바이스 파일을 조작하면 커널 내부의 디바이스 드라이버(device driver)라고 부르는 소프트웨어가 사용자 대신에 장치에 접근한다. 그림으로 보면 다음과 같다.
프로세스는 일반 파일과 똑같은 방식으로 디바이스 파일을 조작할 수 있다. 즉 open(), read(), write() 같은 시스템 콜을 사용해서 각각의 장치에 접근하고, 장치 고유의 복잡한 조작은 ioctl() 시스템 콜을 사용한다. 디바이스 파일에 접근할 수 있는 건 보통 루트뿐이다.
디바이스 파일엔 다음과 같은 정보가 저장된다.
- 파일 종류 : 캐릭터 장치(character device) 혹은 블록 장치(block device)
- 디바이스 메이저 번호, 마이너 번호 : 메이저 번호와 마이너 번호 조합이 같다면 동일한 장치에 해당하고, 그렇지 않다면 다른 장치이다.
디바이스 파일은 보통 /dev/ 디렉터리 아래에 존재하므로, 여기에서 디바이스 파일을 나열해 보자.
정보는 다음과 같다. 첫 번째 필드가 c로 시작하면(crw- ~ ) 캐릭터(character) 장치, b로 시작한다면 볼록 장치이다. 다섯 번째 필드가 메이저 번호, 여섯 번째가 마이너 번호이다. 따라서 /dev/console 은 캐릭터 장치, /dev/ram0 은 블록 장치이다. 이제 구체적인 장치에 대해 알아보자.
2. 캐릭터 장치
캐릭터 장치는 읽고 쓰기는 가능하지만, 장치 내부에서 접근할 장소를 "변경"하는 탐색(seek) 조작이 불가능하다. 캐릭터 장치의 예시는 다음과 같다.
- 단말
- 키보드
- 마우스
그럼 실제로 디바이스 파일에 접근해서 단말 장치를 조작해 보자. 우선 프로세스에 해당하는 단말과, 대응하는 디바이스 파일을 찾아보자. 단말은 ps ax의 두 번째 필드에서 확인할 수 있다.
zsh는 pts/0 단말에 있는 것을 확인할 수 있고, /dev/ 아래의 pts/0 파일이 단말에 해당하는 디바이스 파일임을 알 수 있다.
sudo su 명령을 이용해 루트 권한을 얻고 단말 장치에 hello 문자열을 작성했다. 결국 필자가 실행한 zsh에서 hello를 쓴 것이기 때문에 사실 echo hello와 출력 결과는 당연히 같다. echo 명령어는 stdout에 hello를 쓰고, 리눅스에서 stdout은 단말(pts/0)과 연결되어 있기 때문이다.
이번에는 현재 사용중이지 "않은" 단말에 출력해보자. pts/5 에 하면 적당하겠다.
이번에는 예상대로 아무 것도 출력되지 않는다. pts/5 zsh의 stdout에 출력되었을 것이다.
3. 블록 장치
블록 장치는 읽기, 쓰기 뿐만 아니라 탐색도 가능하다. 대표적인 블록 장치는 HDD, SSD같은 저장 장치이다. 하지만 보통 디바이스 파일로 저장 장치를 조작하지는 않고, 파일 시스템을 경유해서 데이터를 읽고 쓴다. 이 실습에서는 파일 시스템을 거치지 않고 블록 디바이스 파일을 조작해서 변경한다.
이때 "비어 있는" 파티션에서 파일 시스템을 만들어야 한다. 하지만 필자는 비어 있는 파티션이 없기 때문에 루프 장치(loop device) 기능을 사용할 것이다.
이렇게 하면 loopdevice.img 파일이 /dev/loop0 루프 장치와 연결되고, 이후 /dev/loop0 을 블록 장치와 똑같이 다룰 수 있다. 이제 비어 있는 파티션에 ext4 파일 시스템을 만들어 보자.
이어서 mnt 폴더를 생성 후 /dev/loop0 에 마운트하고,
이제 mnt 폴더에 파일을 조작하면 loopdevice.img 안에 있는 파일 시스템 데이터가 변경된다. 예를 들면, 다음과 같이 testfile을 만들고 hello world를 입력한 다음, strings -t x 명령으로 파일 내부에 있는 문자열 데이터가 한 줄에 하나씩 출력되는데 첫 번째 필드는 파일 오프셋(file offset), 두 번째 필드는 찾은 문자열 형식이다. lost+found는 ext4 작성 시 반드시 작성되는 파일이다.
위 결과에서는 디렉터리 및 파일명, 그리고 파일에서 찾은 문자열이 출력된다. 특이한 점은 디렉토리 및 파일명이 두 번씩 출력된다는 것이다. 그 이유는 ext4의 저널링(journaling) 기능 때문인데, 저널링은 데이터를 쓰기 전에 저널 영역이라는 장소에 기록하므로 같은 문자열이 두 번 등장한다는 것을 알 수 있다. 문자열을 입력을 완료했으므로 umount로 mount를 해제했다.
이번에는 testfile 내용을 블록 장치에서 변경해보자.
실행 내용은 다음과 같다.
- 현재 작업 폴더에 testfile-overwrite라는 파일에 "HELLO WORLD" 문자열 입력 후 저장
- /dev/loop0의 파일 시스템에서 hello world 문자열이 있던 위치(0x8200000)를 testfile-overwrite의 내용(HELLO WORLD)로 업데이트
- 현재 작업 폴더의 mnt 폴더를 마운트 후 testfile를 출력 -> HELLO WORLD로 업데이트된 걸 확인
사용이 끝났으면 마운트를 해제하고 img를 정리해주자.
다음 포스트에서는 디바이스 드라이버 커널 기능에 대해 알아보자.
'Linux > 그림으로 배우는 리눅스 구조' 카테고리의 다른 글
[그림으로 배우는 리눅스 구조] 7. 파일 시스템 (0) | 2024.08.30 |
---|---|
[그림으로 배우는 리눅스 구조] 6. 장치 접근(2) (0) | 2024.08.30 |
[그림으로 배우는 리눅스 구조] 5. 프로세스 관리(응용편) (0) | 2024.08.29 |
[그림으로 배우는 리눅스 구조] 4. 메모리 관리 시스템(2) (0) | 2024.08.29 |
[그림으로 배우는 리눅스 구조] 4. 메모리 관리 시스템(1) (0) | 2024.08.29 |