2012-03-26 2 views
5

WaitNamedPipe 기능을 사용하면 파이프 클라이언트 응용 프로그램이 명명 된 파이프 서버에서 사용 가능한 연결을 동 기적으로 대기 할 수 있습니다. 그런 다음 CreateFile을 호출하여 파이프를 클라이언트로 엽니 다. 의사 코드 :WaitNamedPipe 대신 겹쳐진 I/O 란 무엇입니까?

// loop works around race condition with WaitNamedPipe and CreateFile 
HANDLE hPipe; 
while (true) { 
    if (WaitNamedPipe says connection is ready) { 
     hPipe = CreateFile(...); 
     if (hPipe ok or last error is NOT pipe busy) { 
      break; // hPipe is valid or last error is set 
     } 
    } else { 
     break; // WaitNamedPipe failed 
    } 
} 

문제는 모두 동기식 호출을 차단하는 것입니다. 이것을 비동기 적으로 수행하는 좋은 방법은 무엇입니까? 예를 들어, 중복 된 I/O를 사용하는 API를 찾을 수없는 것 같습니다. 예를 들어, 파이프 서버ConnectNamedPipe 함수 비동기 클라이언트 기다려야하는 서버 lpOverlapped 허용하는 매개 변수를 제공한다. 그런 다음 파이프 서버는 WaitForMultipleObjects을 호출하여 I/O 작업이 완료되거나 다른 이벤트가 신호 될 때까지 기다릴 수 있습니다 (예 : 스레드가 보류중인 I/O를 취소하고 종료하도록 알리는 이벤트).

내가 생각할 수있는 유일한 방법은 WaitNamedPipe을 짧은 시간 제한의 루프에서 호출하고 시간이 초과되면 다른 신호를 확인하는 것입니다. 또는 루프 호출 CreateFile에서 다른 신호를 확인한 다음 짧은 지연 (또는 WaitNamedPipe)으로 Sleep으로 전화하십시오. 예를 들면 다음과 같습니다.

HANDLE hPipe; 
while (true) { 
    hPipe = CreateFile(...); 
    if (hPipe not valid and pipe is busy) { 
     // sleep 100 milliseconds; alternatively, call WaitNamedPipe with timeout 
     Sleep(100); 
     // TODO: check other signals here to see if we should abort I/O 
    } else 
     break; 
} 

그러나이 방법은 내 생각에 높은 천국으로 악취를냅니다. 파이프를 잠시 사용할 수 없다면 스레드는 계속 실행됩니다. CPU 사용, 전원 사용, 메모리 페이지가 RAM에 남아 있어야합니다. 내 생각에 Sleep 또는 짧은 시간 제한에 의존하는 스레드는 제대로 수행되지 않습니다. 엉성한 멀티 스레드 프로그래밍의 징조이다.

하지만이 경우 대체 방법은 무엇입니까?

+1

하나의 분명한 해결책은 별도의 스레드에서 WaitNamedPipe를 호출하는 것입니다. IIRC에서 몇몇 비동기 IO 함수는 실제적으로 스레딩을 사용하기 때문에 비효율적이지 않습니다. –

+0

이 코드로 해결되는 경쟁 조건에 대해 더 자세히 알려주십시오. MS 설명서 샘플 클라이언트 코드는 CreateFile을 먼저 호출하고 Create가 파이프 바쁨으로 실패하면 WaitNamedPipe 만 호출합니다. 루프에서 적절한 대기 시간 초과와 함께 수행하십시오. 그것은 항상 내 경험에서 일했습니다. 이 오류는 두 클라이언트가 하나의 파이프에 대해 수행 할 때만 발생하지만 경쟁이 아닙니다. 한 명의 고객이 연결되고 다른 고객이 잠을 잘 때까지 기다렸다가 다시 시도합니다. –

+1

@ 마크 : 문서에 있습니다. WaitNamedPipe가 성공하면 다른 스레드가 처음으로 건너 뛰어서 CreateFile이 계속 실패 할 수 있습니다. 경쟁 조건입니다. 두 개 이상의 스레드가 파이프를 열기 위해 경쟁 중입니다. 경합 조건 주위에서 루프를 작동 시키므로 OP 코드의 주석이 사용됩니다. 그것은 그가 우리에게 풀어야 할 문제는 아닙니다. –

답변

4

WaitNamedPipe 완전히 쓸모없는, 당신은 시간 제한을 지정하고 대기중인 서버가 존재하지 않는 경우는 단지 모든 CPU를 사용합니다.

Sleep과 같이 CreateFile을 계속 호출하고 적절하게 다른 스레드로 이동하십시오. API 대안이 없습니다.

오직 "이점"WaitNamedPipe은 네임드 파이프에 연결할 수 있지만 실제로 연결을 원하지 않는다는 것을 알고 싶을 때 제공됩니다. 쓰레기 야.

정말 철저하고 싶다면

는 유일한 옵션은

  • 이 명명 된 파이프는 항상 다시는 파이프라는 것 직후 CreateNamedPipe를 호출 여는 어떤 프로그램이이에 연결되어 있는지 확인합니다.
  • 프로그램이 실제로 실행 중인지 확인하십시오.
  • 실제적으로 추가 연결이 필요하지 않다면 여전히 CreateNamedPipe으로 전화를 걸어 다른 사람이 연결되면 지정된 시간 동안 기다릴 때까지 사라지라고 지시하고 파이프를 닫으십시오.
+0

다른 어떤 것도 경쟁하고 있지 않다면 모든 CPU를 사용한다고 추측합니다. 적어도 클럭 틱당 한 번 CPU를 산출해야합니다. 이는 실제로 의미가 있습니다. 즉, 기본 프로토콜이 연결을 대기열에 넣을 수있는 방법을 제공하지 않는다는 것을 의미합니다. 이는 비동기 버전이없는 이유를 설명합니다. TCP 연결에서도 마찬가지입니다. 서버 측이 듣지 않는다면 "아, 그럼, 당신이 자유 로울 때 다시 전화 해"라고 말할 수있는 방법이 없습니다. 주기적으로 다시 시도해야합니다. –

+0

그것은 마이크로 소프트가 방치 한 것입니다. 'WaitNamedPipe'를 타임 아웃으로 호출하면 cpus 중 하나가 % 100에 도달 할 때가 있습니다. 즉, 라이브 록이라고하는 것입니다. 다른 것들은 실행될 수 있지만, 그 CPU에서는 유휴 사이클이 전혀 없습니다. 나는 그들이 10 년이나 2 년 안에 그것을 고쳐 줄 것이라고 생각한다. – fcrick

+0

나는 제한된 타임 아웃을 사용하여 감았습니다. –

2

왜 서버가 파이프를 더 만들 수 없습니까? 당신이 묘사하는 시나리오에서의 성과는 그것이 드문 경우 문제가되지 않습니다.

e.e. 대개 충분한 파이프가 있다면 WaitForMultipleObjects 대신 CreateFile/Sleep을 사용하면 무엇이 중요할까요? 성능에 영향을 미치지 않습니다.

또한 클라이언트에서 중복 된 IO의 필요성에 대해서도 질문해야합니다. 한 번에 얼마나 많은 서버가 통신합니까? 대답이 10보다 적 으면 연결 당 스레드를 합리적으로 만들 수 있습니다.

는 기본적으로 나는 이유는 더 그것을 필요로 합리적인 사용 사례가 없기 때문에 WaitforNamedPipe는 중복이 없다고 생각 말하고있다.

+0

클라이언트는 서버를 제어 할 수 없으므로 최악의 상황을 가정해야합니다. (이 경우 서버는 한 번에 하나의 클라이언트 만 처리하지만 서버가 한 번에 여러 클라이언트를 처리하더라도 클라이언트는 여전히 전체 서버를 준비해야합니다.) –

+0

@JamesJohnston : 서버 코드? 명명 된 파이프는 주로 클라이언트와 서버가 함께 쓰는 데 사용됩니다. –

+0

@Ben WaitNamedPipe의 겹쳐진 입출력 버전을 필요로하는 유스 케이스는 클라이언트가 기다리는 동안 무엇인가하고 싶어하는 곳이다. 그러나 자신의 스레드에 대기를 두는 것은 옵션이 아니다. 드물게 사용 사례는 거의 없습니다! –