2012-04-01 5 views
4

userland에서 디스크 IO를 수행하는 것은 C 라이브러리 또는 사용자가 모험을하는 경우 시스템 호출을 직접 수행하는 것처럼 쉽게 연결됩니다. 커널 자체가 어떻게 IO를 수행하는지 궁금합니다.디스크 IO 작업은 일반적으로 커널 수준 어셈블리에서 어떻게 나타 납니까?

즉, 권한이 부여 된 모드에서 베어 메탈에 응용 프로그램을 실행한다고 가정 해 보겠습니다. SATA 연결을 통해 연결된 디스크 하드웨어에 어떻게 접근합니까? 미리 결정된 주소에서로드를 수행합니까? io 관련 지시가 있습니까?

답변

4

리눅스에는 함수 호출 추적 프로그램이 있습니다. 입출력 요청을 추적하는 것이 좋습니다.

경고 : 다음 내용은 실제 내용을 알지 못해 저에게 작성되었습니다.

기본적으로 디스크 블록 (또는 이더넷 프레임)을 한 번에 한 바이트 씩 읽지 않으므로 PCI API를 사용하여 직접 메모리 액세스를 설정하려면 디스크 장치와 통신해야합니다. 따라서 메모리의 일부 영역 (주소 X 및 길이 N 바이트로 시작)이 DMA 영역임을 하드웨어에 알립니다. 또한 메모리 캐싱을 설정하여 RAM의 해당 영역에있는 데이터가 CPU에 쓰기 작업없이 변경 될 수 있음을 알기 때문에 유니 프로세서 라하더라도 휘발성이 있습니다.

하드웨어가 한 번에 하나의 DMA 트랜잭션 만 지원한다고 가정합니다. 그런 다음 "512 바이트 섹터 번호 X (즉, 바이트 X < < 9 번 ((X + 1) < < 9) -1)를 읽고 DMA 영역에 넣습니다. 완료, 인터럽트 발생 ". 디스크 컨트롤러는 그 일을합니다 (ARM CPU 및 모든 것을 갖추고 있습니다), PCI를 통해 북쪽 브리지 허브에 전달하고 RAM을 통해 CPU를 우회합니다. 쓰기가 완료되면 (또는 오류가 발생하면) 인터럽트가 발생합니다. 이런 일이 발생하는 동안 기다리십시오 (프로세스가 잠자기 상태 일 때 커널이 다른 프로세스를 실행합니다). 수백만 CPU 사이클 (나중에 10ms는 2Ghz 칩의 영원)인데 인터럽트가 발생합니다. OS가 읽기가 완료되었음을 알립니다. OS는 RAM에있는 데이터를 볼 수 있습니다. 그런 다음 사용자 프로세스 메모리에 복사하거나 공유 페이지에 있으며 사용자 프로세스가 거기에서 읽을 수 있습니다. 사용자 프로세스가 재개됩니다 (대기열을 실행할 대기 상태에 놓고 결국 스케줄러가 느껴질 때 실행됩니다).

데이터를 DMA 공간에 복사하고 "DMA 영역의 데이터를 디스크의 섹터 번호 X에 기록하고 완료되면 인터럽트를 실행"명령을 전송하여 쓰기 작업을 수행합니다. 그런 다음 디스크 쓰기가 끝나거나 RAM에서 데이터를 읽는 즉시 인터럽트를 발생시킬 수 있습니다.이 경우 fsync가 실제로 작동하지 않고 데이터베이스 및 파일 시스템이 정전으로 인해 손상됩니다.

OS 블록 캐시는 전체 4KB RAM 페이지에서 작동하므로 한 번에 8 섹터를 읽지 만 생각은 같습니다. 새 디스크에는 4KB sectors과 작동하는 기본 API가 있지만 아이디어는 같습니다. USB는 PCI와는 다르지만 아이디어는 같습니다.다양한 고성능 하드웨어에는 이러한 모든 작업을 신속하게 처리 할 수있는 똑똑한 API가 있으며 동시에 여러 개의 트랜잭션을 처리하고 순서에 대한 다양한 제어 기능을 제공합니다.

NIC가 TCP/IP 헤더를 인식하기 때문에 TCP/IP를 오프로드하는 네트워크 인터페이스는 아마도 이더넷 프레임 대신 패킷 주위에 API를 가지고 있습니다.

실제 네트워크 장치 인 블록 장치는 하드웨어의 일부, 펌웨어의 일부, 소프트웨어의 일부를 번역 어딘가에 숨 깁니다. 리눅스에서

, 내 하드웨어, 나는 이렇게되면 생각 :

모듈 sata_piix is loaded, 그것은 장치의 PCI 장치 ID가 그것을 지원하고 OS를 사용한다 callsbacks OS를 알려줍니다

하는 모든 described 구조체. 일반 OS PCI 토폴로지 코드는 ID가 8086 : 27c0이고 ICH7 인 장치를 발견하고 driver's table에서 찾으면 OS가이 하드웨어에 적합한 드라이버라고 결정합니다. 이 표에서 운전자는이 장치를 나중에 an ICH6 SATA device으로 처리해야한다는 것을 알게됩니다. 드라이버가 장치를 지원한다고 했으므로 OS registers은 드라이버가있는 장치입니다.

거기에서 장치의 제어 영역이 할당되고 prepared입니다. DMA is set up. PCI Bus Masteringis enabled (이것은 CPU가 전송을 시작하기를 기다리는 대신 데이터 준비가되었을 때 컨트롤러가 자체적으로 RAM으로 PCI 데이터 전송을 시작하도록 허용 함). 인터럽트 핸들러 are set up.

코드는 일반적이며, 연대순으로, 하드웨어의 여러 세대를 지원합니다

  1. PIO
  2. Single/Multi-word DMA
  3. UDMA
  4. SATA
  5. AHCI

그래서 읽기가 어렵습니다. 추적으로 훨씬 쉽게 할 수 있습니다.

1

이것은 많은 요소에 달려 있습니다. ARM에 대해 많이 알지는 못하지만 버스를 통해 데이터를 보낼 수있는 outportb 명령어가 있다고 생각합니다. I/O 디바이스와의 통신은 벤더에 따라 다르지만 일반적으로 커널은 디바이스의 레지스터를 메모리 맵핑 (GPU 프레임 버퍼의 경우)하거나 I/O 디바이스가 인식 할 수있는 버스 (일반적으로 디바이스 특정)를 통해 요청을 전송할 수 있습니다. . 요청은 보통 시작 섹터, 길이 및 전송할 버스 I/O에 알려주는 주소가 들어있는 직렬화 된 구조 정보입니다.

커널 (예 : Linux)에서 이러한 작업을 수행하려는 경우 이미 I/O 구조를 만들고 특정 장치에 제출하여 사용자가 직접 할 필요가없는 기능이 있습니다. 자신 만의 OS를 작성한다면 많은 아키텍처에서 어셈블리 레벨에서이를 수행하는 방법의 예가있는 Linux 소스 코드를 살펴 보는 것이 좋습니다.

관련 문제