윈도우즈 입출력 완료 포트

입출력 완료 포트
                   
                               
하나.기본 개념:
장치---windows 운영체제에서 통신을 허용하는 모든 것, 예를 들어 파일, 디렉터리, 직렬 인터페이스, 병렬 인터페이스, 메일 슬롯, 이름 파이프, 이름 없는 파이프, 플러그인, 컨트롤러, 논리 디스크, 물리 디스크 등.장치와 접촉하는 절대 다수의 함수는CreateFile/ReadFile/WriteFile 등이다.그래서 우리는 **File 함수를 볼 수 없고 파일 장치만 생각할 수 있습니다.
장치와 통신하는 데는 두 가지 방식이 있는데, 동기화 방식과 비동기화 방식이다.동기화 방식에서 ReadFile 함수를 호출할 때 함수는 시스템이 요구하는 작업을 수행한 후에 되돌아옵니다.비동기적으로, ReadFile과 같은 함수는 직접 되돌아와 시스템 스스로 장치에 대한 작업을 완성한 다음에 어떤 방식으로 작업이 완성되었음을 알린다.
중첩 I/O -- 말 그대로 어떤 함수(예를 들어 ReadFile)를 호출하면 바로 자신의 다른 동작을 할 때 시스템도 I/0 장치에 대해 당신이 요구하는 조작을 하고 있다. 이 시간 동안 당신의 프로그램과 시스템의 내부 동작은 중첩되어 있어 더욱 좋은 성능을 가진다.따라서 중복 입출력은 비동기적으로 입출력 디바이스를 사용하는 데 사용됩니다.
입출력을 중첩하는 데 필요한 매우 중요한 데이터 구조인 OVERLAPPED
완료 포트 - WINDOWS 커널 객체입니다.완료 포트가 비동기적으로 중첩 I/0에 사용되는 경우 중첩 I/O가 반드시 완료 포트를 사용하지 않으면 안 되는 것은 아니며 장치 커널 객체, 이벤트 객체, 경고 I/0 등이 있습니다.그러나 포트 내부를 완성하면 스레드 탱크의 관리를 제공하여 반복적으로 스레드를 만드는 비용을 피할 수 있고 CPU의 개수에 따라 스레드 개수를 유연하게 결정할 수 있으며 스레드 스케줄링 횟수를 줄여 성능을 향상시킬 수 있다.
 
 
둘.OVERLAPPED 데이터 구조
typedef struct _OVERLAPPED {
ULONG_PTR Internal;                 
ULONG_PTR InternalHigh;
 DWORD Offset;
DWORD OffsetHigh;
HANDLE hEvent;
} OVERLAPPED;
 
이 구조에는 Offset, Offset Hign, hEvent가 ReadFile과 WriteFile을 호출하기 전에 초기화해야 하고, 다른 두 구성원은 드라이버가 설정하여 입출력 작업이 끝났을 때 값을 검사할 수 있습니다.
 
hEvent 구성원: 입출력 완료 알림을 받는 4가지 방법(장치 핵 트리거 대상, 트리거 시간 핵 대상, 알림 입출력 사용, 입출력 완료 포트 사용) 중 하나(입출력 완료 포트 사용)가 이 구성원에게 사용됩니다.
 
셋.입출력 완료 포트 생성
I/O 완료 포트는 스레드 풀과 함께 사용하여 서비스 어플리케이션의 성능을 향상시키도록 설계되었습니다.
서비스 응용 프로그램의 두 가지 구조 모델:
- 직렬 모델: 한 라인이 고객의 요청을 기다리고 요청이 도착했을 때 라인이 깨어나 고객의 요청을 처리한다
- 병렬 모델: 하나의 라인이 고객의 요청을 기다리고 요청이 도착했을 때 새로운 라인을 만들어서 요청을 처리합니다
직렬 모형의 단점은 여러 개의 요청을 동시에 처리할 수 없다는 것이다. 병렬 모형에서 윈도우즈 핵은 실행 가능한 라인 사이의 프로세스 상하문 전환에 너무 많은 시간이 걸린다.
입출력 완료 포트 뒤에는 동시 실행 스레드의 최대 수가 있어야 한다는 이론이 있습니다.
입출력 완료 포트는 매우 복잡한 핵 대상으로CreateIoCompletionPort를 사용하여 입출력 완료 포트를 만들 수 있습니다
 
HANDLE CreateIoCompletionPort (
HANDLE FileHandle,//handle to file
HANDLE ExistingCompletionPort,//handle to I/O completion port
ULONG_PTR CompletionKey,//completion key
DWORD NumberOfConcurrentThreads//number of threads to execute concurrently
);
 
사실 이 함수는 두 선의 다른 임무를 확실히 집행했다.입출력 완료 포트 생성2. 입출력 완료 포트에 디바이스 연결
첫 번째 단계: I/O 완료 포트를 하나만 생성하기 위해CreateIoCompletionPort의 처음 세 개의 매개 변수에 대해 INVALIDHANDLE_VALUE,NULL,0.
2단계: 디바이스를 I/O 완료 포트와 연결하고 수신된 매개변수 ExistingCompletionPort 값이 NULL이 아니면 FileHandle과 연결합니다.
입출력(I/O) 완료 포트를 생성하면 시스템 커널은 실제로 다음과 같은 5개의 다른 데이터 구조를 생성합니다.
1. 장치 목록: 포트와 연결된 하나 이상의 장치를 나타냅니다.
2. 입출력 완료 대기열(선입선출): 디바이스의 비동기식 입출력 요청이 완료되면 디바이스가 입출력 완료 포트와 연결되어 있는지 확인하고 해당하는 경우 입출력 요청을 입출력 완료 대기열 끝에 추가합니다.
3. 대기 스레드 대기열(후입선출): 스레드 탱크의 모든 스레드가GetQueuedCompletionStatue(스레드를 수면 상태로 전환)를 호출할 때 호출 스레드의 스레드 식별자는 이 대기 스레드 대기열에 추가되어 입출력 완성 포트 핵 대상이 항상 알 수 있도록 합니다.완료된 입출력 요청이 처리될 때까지 대기 중인 스레드(즉, 입출력 완료 대기열에 항목이 추가될 때까지 대기 중)
4. 방출된 스레드 목록: 이 스레드가 실행 상태로 전환될 수 있음을 이해할 수 있으며, 스레드 대기열과 중단된 스레드 목록의 스레드가 깨어나면 이 목록에 추가할 수 있습니다.
5. 정지된 스레드 목록: 방출된 스레드가 함수를 호출하여 자신을 마운트할 때 이 스레드의 스레드 표식자를 이 목록에 추가하고 마운트된 스레드가 깨어날 때 방출된 스레드 목록에 추가합니다
 
이 다섯 개의 데이터 구조를 이해하면 입출력 완료 포트가 다중 스레드를 어떻게 관리하는지 쉽게 알 수 있습니다.
 
입출력 완료 포트 및 스레드 풀
I/O 완료 포트 아키텍처는 실행 가능한 스레드 수가 허용되는 최대 스레드 수보다 짧은 시간 안에 높다고 가정합니다. 스레드가 다음 순환에 들어가고 GetQueuedCompletionStatus를 호출하면 실행 가능한 스레드 수가 급격히 감소합니다. 즉, 스레드 풀의 스레드 수가 완성 포트에 설정된 병렬 스레드 수보다 많아야 하는 이유입니다.
어떻게 스레드 탱크에 반드시 여러 개의 스레드가 있어야 하는지를 확정합니까?계발식 알고리즘을 사용하여 스레드 탱크를 관리할 수 있다.
 
스레드 간 데이터 전송:
스레드 간에 데이터를 전달하는 데 가장 자주 사용하는 방법은beginthreadex 함수에서 매개 변수를 라인 함수에 전달하거나 전역 변수를 사용합니다.하지만 포트를 완성하고 데이터를 전달하는 방법도 있다. 답은CompletionKey와 OVERLAPPED 파라미터에 있다.
CompletionKey는 완성 포트의 장치 테이블에 저장되어 장치 핸들과 일일이 대응한다. 우리는 장치 핸들과 관련된 데이터를 CompletionKey에 저장하거나 CompletionKey를 구조 지침으로 표시하면 더욱 풍부한 내용을 전달할 수 있다.이 내용들은 포트와 장치 핸들을 처음 연결할 때만 할 수 있기 때문에 나중에 동적으로 바꿀 수 없습니다.
OVERLAPPED 매개 변수는 ReadFile과 같은 지원 중첩 I/0 함수를 호출할 때마다 완성 포트에 전달됩니다.만약 우리가 파일 장치를 조작하지 않았다면, 이 구조의 구성원 변수는 우리에게 거의 아무런 작용이 없었을 것이다.우리는 자신의 구조를 만들고 OVERLAPPED 구조 변수를 우리의 구조 변수의 첫 번째 구성원으로 하고 첫 번째 구성원 변수의 주소를 ReadFile 함수에 전달할 수 있는 추가 정보를 필요로 한다.형식이 일치하기 때문에, 당연히 컴파일을 통과할 수 있습니다.GetQueued Completion Status 함수가 되돌아올 때, 우리는 첫 번째 구성원 변수의 주소를 얻을 수 있고, 간단한 강제 변환을 통해 완전한 사용자 정의 구조의 지침으로 사용할 수 있으며, 이렇게 하면 많은 추가 데이터를 전달할 수 있다.잘 됐다!단 한 가지 주의해야 할 것은, 만약 크로스 라인이 전달된다면, 데이터를 더미에 분배하고, 수신자는 데이터를 다 쓴 후에 방출해야 한다는 것이다.GetQueuedCompletionStatus가 되돌아올 때 사용자 정의 구조의 버퍼 변수에 I/0 작업의 데이터가 저장됩니다.
 
CompletionKey와 OVERLAPPED 매개 변수는GetQueuedCompletionStatus 함수를 통해 얻을 수 있습니다.
 
 
 
 

좋은 웹페이지 즐겨찾기