| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- 화이팅
- 청내공만기
- Provider AWS
- 너무어려워...
- 정신력승리
- 테라폼만세
- 청내공화이팅
- 저것도꾸준히읽어야지ㅠㅠ
- 몸이고되고머리가힘들다
- 무탈히가길
- 이놈의기사또해내야돼
- 청년내일채움공제 끝
- 해내자
- 청년내일채움공제
- 청내공
- aws책은읽다말았는데
- 청내공만기오긴오냐
- IaC코드자동화
- 만기오긴오냐
- 청내공해내자
- 정신력승리함
- 나름신중하게할거다하고있음
- 윽짜증
- 2025년 1회차
- 은우쌤
- 존버존버
- 합격률15.18%
- 해낼수있어
- 어렵다
- 자동화구현만세
- Today
- Total
시나브로
6. 장치 접근 본문
프로세스가 장치에 접근하는 방법
ㄴ 직접 접근하지못함
이유 : 여러 프로그램이 동시에 장치를 조작하면 (예상할수없는 방식으로 인해) 작동할 위험성이 있음
접근해서는 안되는 데이터를 훼손하거나 훔쳐볼 위험성이 있음
ㄴ 커널이 장치에 접근함
ㄴ 디바이스 파일을 조작함 (특수 파일)
블록 장치에 구축한 파일 시스템을 조작함
NIC(네트워크 인터페이스 카드)는 속도 등의 문제로 소켓 구조를 사용함
디바이스 파일
예) /dev/sda, /dev/sda1, /dev/sdb 등
리눅스는 프로세스가 디바이스 파일을 조작, (디바이스 파일에 접근하는건 루트 뿐)
커널 안의 디바이스 드라이버(소프트웨어)가 장치에 접근함 (사용자 대신에)

장치 0 : /dev/AAA
장치 1 : /dev/BBB
프로세스는 open(), read(), write() 등 시스템 콜 호출해서 각 장치에 접근함
복잡한 조작은 ioctl() 등 사용함
● 디바이스 파일 종류 : 캐릭터 장치, 블록 장치
메이저, 마이너 번호 조합이 같음 == 동일한 장치
디바이스 파일은 /dev 아래에 있음
c는 캐릭터 장치, b는 블록 장치


캐릭터 장치
예) 단말, 키보드, 마우스 등
읽기 쓰기 가능
접근할 장소 변경하는 탐색 조작 불가능
write() : 단말에 데이터를 출력
read() : 단말에서 데이터를 입력
각 프로세스와 연결된 단말 조회 : ps ax | grep bash

교재의 경우, bash는 두 번째 필드인 pts/9 단말을 사용 중인걸 알수있음
/dev/pts/9

AWS로 서버 생성하여 확인해보니 해당 서버는 pts/0 단말을 사용 중이었음

단말 장치에 hello 쓰면 그대로 출력됨
ㄴ 리눅스에서 표준 출력은 단말과 연결되어있기 때문

탭 추가하니 pts/1 생김

두번째 탭에 hello 입력했는데 첫번째 탭에 출력됨
블록 장치
읽기 쓰기 탐색 가능
예) HDD, SSD 등 저장 장치
데이터를 읽고 쓰면 일반 파일처럼 저장 장치에 있는 데이터에 접근 가능
블록 디바이스 파일을 사용 → 블록 장치를 조작
사용자가 블록 디바이스 파일을 직접 조작하지않음
보통 파일 시스템 경유해서 데이터를 읽고 쓴다
데이터 들어있는 파티션은 손상될 위험으로 주의하기
ext4 파일 시스템 내용을 파일 시스템 거치지않고 블록 디바이스 파일을 조작해서 변경
교재는 비어있는 파티션 /dev/sdc7 을 전제로 진행함

해당 서버에 비어있는 파티션이 없어 볼륨 추가하고 연결함

파티션 생성


마운트하고 파일에 문자열 기록해서 출력함
string 명령어로 파일시스템 데이터에 들어있는 문자열 정보만 추출하기

각각의 문자열이 두 번 출력된 건 ext4의 저널링(journaling) 기능 때문인데
저널링은 데이터를 쓰기 전에 저널 영역이라고 부르는 장소에 함께 기록함
ㄴ 해당 서버에 입력하니 수백만 줄이 출력됨...........
루프 장치 (loop)
예) 파일 시스템 다루는 실험해보고 싶어도 불가능할때
비어있는 장치, 파티션이 없을때
디스크에 저장된 내용이 손상될 위험 있을때
ㄴ 파일을 디바이스 파일처럼 다룰수있는 기능




mount 상태

umount 과정

디바이스 드라이버
프로세스 입장에서 보는 장치 조작 순서

디바이스 드라이버 커널 기능
ㄴ 프로세스가 디바이스 파일에 접근할때 동작함
ㄴ 장치를 직접 조작하려면 각 장치에 내장된 레지스터 영역을 읽고 써야 함
레지스터 종류와 조작법 등 정보는 각 장치 사양에 따라 달라짐
프로세스 입장에서 보는 장치 조작 순서
1 프로세스가 디바이스 파일을 사용해서 디바이스 드라이버에 '장치를 조작하고싶음' 을 요청함
2 CPU가 커널 모드로 전환됨
디바이스 드라이버가 레지스터를 사용해서 장치에 요청 전달함
3 장치가 요청에 따라 처리함
4 디바이스 드라이버가 장치의 처리 완료를 확인하고 결과를 받음
5 CPU가 사용자 모드로 전환됨
프로세스가 디바이스 드라이버 처리 완료를 확인 후 결과를 받음
메모리 맵 입출력 MMIO
현대 장치는 MMIO 구조를 사용해서 디바이스 레지스터에 접근함
x86_64 아키텍처는 리눅스 커널이 자신의 가상 주소 공간---물리 메모리를 모두 매핑함

커널의 가상 주소 공간이 0~1000바이트 이면, 0~500에 물리 메모리를 매핑함

MMIO로 장치를 조작하면 주소 공간에 메모리와 레지스터도 매핑함 → 장치 0 ~ 장치 2 존재하는 시스템
장치 조작 흐름
| 레지스터 오프셋 | 역할 |
| 0 | 읽고 쓰기에 사용하는 메모리 영역의 시작 주소 |
| 10 | 저장 장치 내부의 읽고 쓰기에 사용하는 데이터 영역의 시작 주소 |
| 20 | 읽고 쓰기 크기 |
| 30 | 처리 요청에 사용함 0이면 읽기 요청 / 1이면 쓰기 요청 |
| 40 | 요청한 처리가 끝났는지 여부를 나타내는 플래그 처리 요청한 시점에 0이 됨 / 처리 끝나면 1이 됨 |

메모리 영역 100~200으로
저장 장치 내부 주소 300~400 영역에 있는
데이터를 읽어온다고 하면
저장 장치 레지스터가 메모리 주소 500부터 매핑된다고 하면 읽기 요청 처리
읽기 요청 매핑 흐름
1 디바이스 드라이버가 저장 장치의 데이터를 메모리의 어디로 가져올지 지정함
ㄴ 메모리 주소 500에 읽은 데이터를 저장할 주소 100을 기록함
ㄴ 메모리 주소 510에 저장 장치 내부의 읽을 주소 300을 기록함
ㄴ 메모리 주소 520에 읽을 데이터 크기 100을 기록함
2 디바이스 드라이버가 메모리 주소 530에 읽기 요청을 뜻하는 0을 기록함
3 장치가 메모리 주소 540에 요청 처리 중인 상태를 뜻하는 0을 기록함

매핑 동작 이후의 흐름
1 저장 장치의 주소 300~400 영역의 데이터를
메모리 주소 100 이후로 전송함
2 저장 장치가 요청된 처리를 완료했다는 표시로
메모리 주소 540에 값을 1로 변경함
3 디바이스 드라이버가 요청된 처리 완료를 확인함
3에서 처리 완료 확인하려면 폴링 or 인터럽트 2가지 방법 중 하나를 사용함

폴링
디바이스 드라이버가 능동적으로 장치에서 처리 완료했는지 확인함
장치는 디바이스 드라이버가 요청한 처리를 완료하면 → 처리 완료 통지용 레지스터의 값을 변화시킴
드라이버는 이 값을 주기적으로 읽음 (처리 완료 확인함)
예) 스마트폰에서 채팅 앱 실행 → 상대방에게 질문함
폴링의 역할 - 주기적으로 앱을 열어서 답변 왔는지 확인하는 행위에 해당
가장 단순한 폴링
드라이버가 장치에 요청 후 완료할 때까지 레지스터를 계속 확인하는 것
예)
두 개의 프로세스 p0, p1 존재할때 p0이 드라이버에 처리 요청했고,
드라이버가 정기적으로 실행되어 장치 처리 완료를 기다리는 동작 흐름

장치에서 처리가 끝나고, 드라이버가 완료 확인할때까지
CPU는 확인 외에 다른 일을 할수없음
p0은 요청이 끝나기 전에는 다음 처리로 진행할수없으니 문제가 없음
p1은
장치 처리와 관계없는데 동작하지 못함 → CPU 자원 낭비
ㄴ 보통 장치에 처리 요청 및 완료하기까지 필요한 시간 : 밀리초, 마이크로초 단위
ㄴ CPU 명령 하나를 실행하는데 소요 시간 : 나노초 단위 or 훨씬 더 작은 시간 → 큰 낭비
| 밀리초(ms) < 마이크로초(μs) < 나노초(ns) 단위 범위: 1초 = • 1,000 밀리초 • 1,000,000 마이크로초 • 1,000,000,000 나노초 |
따라서 낭비를 줄이기 위해 일정 간격을 두고레지스터 값을 확인하는 폴링 방법

단점 : 정교하지만 디바이스 드라이버가 복잡해짐
p0이 처리 요청 후 완료하는동안 p1이 동작하면
p1 처리하는동안 중간중간 레지스터 값을 읽는 코드를 삽입해야함
ㄴ 확인 간격을 늘린다 → 어느 정도 간격을 줘야 할지 정하기 쉽지않음
ㄴ 간격이 길어지면 처리 완료가 프로세스에 전달되는 시간이 늦어짐
ㄴ 너무 짧으면 자원 낭비 심해짐
인터럽트
1 디바이스 드라이버가 장치에 처리 요청함
CPU는 다른 처리를 실행함
2 장치가 처리 완료하면 인터럽트 방식으로 CPU에 알림
3 CPU는 미리 드라이버가 인터럽트 컨트롤러 하드웨어에 등록해둔 인터럽트 핸들러 처리를 호출함
4 인터럽트 핸들러가 장치의 처리 결과를 받음
예) 채팅 앱에서 질문하면, 답변 왔을때 즉시 알림을 보내는 방식에 해당

p0, p1이 존재하고 p0이 디바이스 드라이버에 처리 요청하는 경우
1 처리 완료할때까지 CPU는 p1 실행 가능함
2 처리 완료 즉시 확인 가능함
곧바로 p0이 동작 가능함
3 처리가 이뤄지는동안 p1 (동작 중)은 장치에서 무슨 일이 일어나는지 신경 쓸 필요 없음
→ 인터럽트를 장치 처리 완료 확인 방법으로 사용하는 경우가 많다

해당 서버 인터럽트 조회
첫번째 필드 - 인터럽트 요청 (IRQ)
두번째 ~ 논리 CPU 개수

인터럽트 발생시킬때 사용하는
타이머 인터럽트의 발생 횟수를 1초마다 출력함
디바이스 파일명
같은 종류의 장치를 여러 개로 연결한 경우
파일명을 조심해서 다뤄야 함
여러 장치가 연결되어있다면 커널이 일정한 규칙에 따라
각 다른 이름으로 디바이스 파일에 대응시킴
예) SATA or SAS → /dev/sda, /dev/sdb, /dev/sdc 등
NVMe SSD → /dev/nvme0n1, /dev/nvme1n1 등
* 주의 - 대응 관계는 PC 기동할때마다 바뀐다
ㄴ 장치 인식 순서에 따라 다름

장치 인식 순서가 바뀜
증설(추가) / 위치변경 / 고장

장치명이 바뀌면 일어나는 일
예) 장치 추가 후 C에 파일 시스템을 만들기
mkfs.ext4 /dev/sdc 실행 → 기존 B를 파일 시스템 만드는 명령이 되어 데이터 파괴 위험성 있음
(단, mkfs는 파일 시스템이 존재하면, 있기 때문에 지울수없다는 메시지가 출력됨
-F 옵션을 실행해서 실수로 지우는 경우가 생김)
udev 영구 장치명을 이용해서 해결
영구 장치명 /dev/disk/by-path 아래에 존재하는, 디스크 설치된 경로 위치 정보가 있는 디바이스 파일이 있음
레이블 /dev/disk/by-label
UUID /dev/disk/by-uuid

마운트할 파일시스템의 실수를 방지할 목적이면
mount 명령어에 레이블 or UUID 지정
예) cat /etc/fstab


UUID에 대응하는 장치를 커널에서 마운트 가능함
'Cloud > [스터디] 그림으로 배우는 리눅스 구조' 카테고리의 다른 글
| 4. 메모리 관리 시스템 (0) | 2025.10.26 |
|---|