> Java > java지도 시간 > Java I/O는 내부적으로 어떻게 작동하나요?

Java I/O는 내부적으로 어떻게 작동하나요?

伊谢尔伦
풀어 주다: 2016-11-26 09:10:03
원래의
1164명이 탐색했습니다.

이 블로그 게시물은 주로 하위 수준에서 I/O가 작동하는 방식에 대해 설명합니다. 이 기사는 Java I/O 작업이 머신 레벨에서 매핑되는 방식과 애플리케이션이 실행될 때 하드웨어가 수행하는 작업을 이해하고자 하는 독자를 대상으로 합니다. Java I/O API를 통한 파일 읽기 및 쓰기와 같은 기본 I/O 작업에 익숙하다고 가정합니다. 이러한 내용은 이 기사의 범위를 벗어납니다.

Java I/O는 내부적으로 어떻게 작동하나요?

캐시 처리와 커널 대 사용자 공간

버퍼링 처리 방식과 버퍼링은 모든 I/O 작업의 기본 . "입력, 출력"이라는 용어는 캐시 안팎으로 데이터를 이동하는 경우에만 의미가 있습니다. 이 점을 항상 염두에 두십시오. 일반적으로 운영 체제 I/O 요청을 수행하는 프로세스에는 버퍼에서 데이터를 빼내고(쓰기 작업) 버퍼를 데이터로 채우는(읽기 작업) 작업이 포함됩니다. 이것이 I/O의 전체 개념입니다. 운영 체제 내부에서 이러한 전송 작업을 수행하는 메커니즘은 매우 복잡할 수 있지만 개념적으로는 매우 간단합니다. 기사의 작은 부분에서 이에 대해 논의하겠습니다.

Java I/O는 내부적으로 어떻게 작동하나요?

위 이미지는 블록 데이터가 디스크와 같은 외부 소스에서 프로세스의 저장 영역(예: RAM) 중간. 첫째, 프로세스는 read() 시스템 호출을 통해 버퍼를 채워야 합니다. 이 시스템 호출은 커널이 디스크 제어 하드웨어에 명령을 실행하여 디스크에서 데이터를 얻도록 합니다. 디스크 컨트롤러는 메인 CPU의 추가 지원 없이 DMA를 통해 커널의 메모리 버퍼에 직접 데이터를 씁니다. read() 작업이 요청되면 디스크 컨트롤러가 캐시 채우기를 완료하면 커널은 커널 공간의 임시 캐시에서 프로세스별 캐시로 데이터를 복사합니다.

한 가지 주의할 점은 커널이 데이터를 캐시하고 프리페치하려고 할 때 커널 공간의 프로세스에서 요청한 데이터가 이미 준비되어 있을 수 있다는 것입니다. 그렇다면 프로세스에서 요청한 데이터가 복사됩니다. 데이터를 사용할 수 없으면 프로세스가 일시 중지됩니다. 커널은 데이터를 메모리로 읽어 들입니다.

가상 메모리

가상 메모리에 대해 많이 들어보셨을 겁니다. 다시 한번 소개하겠습니다.

모든 최신 운영 체제는 가상 메모리를 사용합니다. 가상 메모리는 물리적(하드웨어 RAM) 메모리 주소 대신 인공 또는 가상 주소를 의미합니다. 가상 주소에는 두 가지 중요한 이점이 있습니다.

여러 가상 주소를 동일한 물리적 주소에 매핑할 수 있습니다.

가상 주소 공간은 실제 사용 가능한 하드웨어 메모리보다 클 수 있습니다.

위 설명에서 커널 공간에서 최종 사용자 캐시로 복사하면 추가 작업이 추가되는 것 같습니다. 디스크 컨트롤러에게 데이터를 사용자 공간 캐시로 직접 보내도록 지시하는 것은 어떨까요? 음, 이것은 가상 메모리로 구현됩니다. 1. 위의 장점을 활용하세요.

커널 공간 주소를 사용자 공간 가상 주소와 동일한 물리적 주소에 매핑함으로써 DMA 하드웨어(물리적 메모리 주소만 주소 지정할 수 있음)가 캐시를 채울 수 있습니다. 이 캐시는 커널 및 사용자 공간 프로세스 모두에 표시됩니다.

Java I/O는 내부적으로 어떻게 작동하나요?

이렇게 하면 커널과 사용자 공간 간의 복사가 제거되지만 커널과 사용자 버퍼가 동일한 페이지 정렬을 사용해야 합니다. 버퍼는 디스크 컨트롤러 블록 크기의 배수(일반적으로 512바이트 디스크 섹터)를 사용해야 합니다. 운영 체제는 메모리 주소 공간을 고정 크기 바이트 그룹인 페이지로 나눕니다. 이러한 메모리 페이지는 항상 디스크 블록 크기의 배수이며 일반적으로 2x(단순 주소 지정)입니다. 일반적인 메모리 페이지 크기는 1024, 2048 및 4096바이트입니다. 가상 및 실제 메모리 페이지 크기는 항상 동일합니다.

메모리 페이징

가상 메모리의 두 번째 장점(물리적 메모리보다 큰 주소 지정 가능 공간을 가짐)을 지원하려면 가상 메모리 페이징(종종 페이지 스와핑이라고도 함)이 필요합니다. 이 메커니즘은 가상 메모리 공간의 페이지가 외부 디스크 저장소에 유지될 수 있다는 사실에 의존하여 다른 가상 페이지가 실제 메모리에 배치될 수 있는 공간을 제공합니다. 기본적으로 물리적 메모리는 페이징 영역의 캐시 역할을 합니다. 페이징 영역은 물리적 메모리에서 강제로 스왑 아웃될 때 메모리 페이지의 내용이 저장되는 디스크 공간입니다.

커널이 디스크 컨트롤러 하드웨어에 직접 명령을 보내 메모리 페이지를 디스크에 쓰거나 필요할 때 다시 로드할 수 있도록 메모리 페이지 크기를 디스크 블록 크기의 배수로 조정합니다. 모든 디스크 I/O 작업은 페이지 수준에서 수행되는 것으로 나타났습니다. 이는 최신 페이징 운영 체제에서 디스크와 실제 메모리 간에 데이터를 이동할 수 있는 유일한 방법입니다.

최신 CPU에는 MMU(메모리 관리 장치)라는 하위 시스템이 포함되어 있습니다. 이 장치는 논리적으로 CPU와 물리적 메모리 사이에 위치합니다. 가상 주소에서 실제 메모리 주소로의 매핑 정보가 포함되어 있습니다. CPU가 메모리 위치를 참조할 때 MMU는 어떤 페이지가 있어야 하는지 결정하고(일반적으로 주소의 특정 비트를 이동하거나 마스킹하여) 가상 페이지 번호를 물리적 페이지 번호(하드웨어에서 구현되므로 매우 빠릅니다)로 변환합니다.

파일 지향, 블록 I/O

파일 I/O는 항상 파일 시스템 컨텍스트 전환에서 발생합니다. 파일 시스템과 디스크는 완전히 다른 것입니다. 디스크는 데이터를 세그먼트로 저장하며 각 세그먼트는 512바이트입니다. 이는 하드웨어 장치이며 저장된 파일 의미에 대해 아무것도 모릅니다. 그들은 단지 데이터를 저장할 수 있는 특정 수의 슬롯을 제공할 뿐입니다. 이러한 점에서 디스크 세그먼트는 메모리 페이징과 유사합니다. 그것들은 모두 균일한 크기를 가지며 주소 지정이 가능한 하나의 큰 배열입니다.

반면에 파일 시스템은 더 높은 수준의 추상화입니다. 파일 시스템은 디스크(또는 기타 임의 액세스, 블록 지향 장치)에 저장된 데이터를 정렬하고 변환하는 특별한 방법입니다. 작성하는 코드는 거의 항상 디스크가 아닌 파일 시스템과 직접 상호 작용합니다. 파일 시스템은 파일 이름, 경로, 파일 및 파일 속성과 같은 추상화를 정의합니다.

파일 시스템은 (하드 디스크에) 일정한 크기의 일련의 데이터 블록을 구성합니다. 일부 블록은 사용 가능한 블록, 디렉터리, 인덱스 등의 매핑과 같은 메타 정보를 보유합니다. 다른 블록에는 실제 파일 데이터가 포함됩니다. 개별 파일에 대한 메타정보는 파일의 데이터가 포함된 블록, 데이터가 끝나는 위치, 마지막으로 업데이트된 시기 등을 설명합니다. 사용자 프로세스가 파일 데이터 읽기 요청을 보내면 파일 시스템은 디스크에서 데이터 위치를 정확하게 찾습니다. 그런 다음 이러한 디스크 섹터를 메모리에 배치하는 작업이 수행됩니다.

파일 시스템에도 페이지 개념이 있는데, 이는 기본 메모리 페이지와 동일한 크기이거나 그 배수일 수 있습니다. 일반적인 파일 시스템 페이지 크기는 2048~8192바이트이며 항상 기본 메모리 페이지 크기의 배수입니다.

페이징된 파일 시스템에서 I/O를 수행하는 작업은 다음과 같은 논리적 단계로 요약됩니다.

요청이 어느 파일 시스템 페이지(디스크 세그먼트 모음)에 걸쳐 있는지 결정합니다. 디스크의 파일 내용과 메타데이터는 여러 파일 시스템 페이지에 분산될 수 있으며 이러한 페이지는 연속되지 않을 수 있습니다.

동일한 파일 시스템 페이지를 보관할 수 있을 만큼 충분한 커널 공간 메모리 페이지를 할당합니다.

이러한 메모리 페이지를 디스크의 파일 시스템 페이지에 매핑합니다.

각 메모리 페이지에 대해 페이지 폴트를 생성합니다.

가상 메모리 시스템은 페이징 오류가 발생하고 디스크에서 내용을 읽어 이러한 페이지를 확인하도록 페이지를 예약합니다.

페이지 인이 완료되면 파일 시스템은 원시 데이터를 분해하여 요청된 파일 콘텐츠 또는 속성 정보를 추출합니다.

이 파일 시스템 데이터는 다른 메모리 페이지와 마찬가지로 캐시된다는 점에 유의해야 합니다. 후속 I/O 요청에서는 파일 데이터의 일부 또는 전부가 물리적 메모리에 남아 있으며 디스크에서 다시 읽지 않고도 직접 재사용할 수 있습니다.

파일 잠금

파일 잠금은 프로세스가 다른 프로세스가 파일에 액세스하는 것을 방지하거나 다른 프로세스가 파일에 액세스하지 못하도록 제한할 수 있는 메커니즘입니다. "파일 잠금"이라고 명명되었지만 전체 파일을 잠그는 것을 의미합니다(종종 수행됨). 잠금은 일반적으로 보다 세부적인 수준에서 수행될 수 있습니다. 세분성이 바이트 수준으로 떨어지면 일반적으로 파일 영역이 잠깁니다. 잠금은 특정 파일과 연관되어 파일의 지정된 바이트 위치에서 시작하여 지정된 바이트 범위까지 실행됩니다. 이는 다른 프로세스가 파일의 다른 곳에서 작동하는 것을 방해하지 않고 여러 프로세스가 파일의 특정 영역에 액세스하는 데 협력할 수 있도록 하기 때문에 중요합니다.

파일 잠금에는 공유 잠금과 독점 잠금의 두 가지 형태가 있습니다. 여러 공유 잠금은 동일한 파일 영역에서 동시에 유효할 수 있습니다. 반면에 배타적 잠금은 요청된 지역에 대해 유효한 다른 잠금이 필요하지 않습니다.

스트림 I/O

모든 I/O가 블록 지향적인 것은 아닙니다. 파이프의 프로토타입인 스트림 I/O도 있는데, I/O 데이터 스트림의 바이트는 순차적으로 액세스되어야 합니다. 일반적인 데이터 흐름에는 TTY(콘솔) 장치, 인쇄 포트 및 네트워크 연결이 포함됩니다.

데이터 스트림은 일반적으로 블록 장치보다 느리지만 반드시 그런 것은 아니며 간헐적인 입력을 제공합니다. 대부분의 운영 체제에서는 비차단 모드로 작업할 수 있습니다. 프로세스가 데이터 스트림에 대한 입력이 사용 가능한지 여부를 차단하지 않고 확인할 수 있도록 합니다. 이러한 관리를 통해 프로세스는 입력이 도착할 때 입력을 처리하고 입력 스트림이 유휴 상태인 동안 다른 기능을 수행할 수 있습니다.

논블로킹 모드보다 한 단계 더 발전한 것이 준비 선택입니다. 이는 비차단 모드와 유사하며(종종 비차단 모드를 기반으로 구축됨) 스트림이 준비되었는지 확인해야 하는 부담에서 운영 체제를 덜어줍니다. 운영 체제는 스트림 모음을 관찰하고 스트림이 준비된 프로세스에 명령을 반환하도록 지시할 수 있습니다. 이 기능을 통해 프로세스는 운영 체제에서 반환된 준비 정보를 활용하여 공통 코드와 단일 스레드를 사용하여 여러 활동 스트림을 재사용할 수 있습니다. 이 방법은 많은 수의 네트워크 연결을 처리하기 위해 네트워크 서버에서 널리 사용됩니다. 대량 확장을 위해서는 선택 준비가 중요합니다.


관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿