지옥에서 네트워킹 데이터 경쟁 조건
다른 개발자가 작성한 실제로 오래된 (Encore 32/77) 워크 스테이션에서 유사한 응용 프로그램과 작동하도록 네트워킹 클라이언트 / 서버 (Windows XP / C #)를 작성하고있었습니다.
응용 프로그램은 기본적으로 PC의 다중 모니터 터치 스크린 UI로 시스템을 실행하는 호스트 프로세스를 제어하기 위해 호스트의 특정 데이터를 공유 / 조작했습니다.
3 계층 구조 로이 작업을 수행했습니다. 통신 프로세스는 호스트와의 데이터 읽기 / 쓰기, 필요한 모든 형식 변환 (엔디안, 부동 소수점 형식 등)을 수행하고 데이터베이스에서 값을 쓰거나 읽었습니다. 데이터베이스는 통신 및 터치 스크린 UI 간의 데이터 중개 역할을했습니다. 터치 스크린 UI의 앱은 PC에 연결된 모니터 수에 따라 터치 스크린 인터페이스를 생성했습니다 (자동 감지).
주어진 시간 프레임에서 호스트와 PC 사이의 값 패킷은 왕복 당 ~ 110ms의 최대 대기 시간으로 한 번에 최대 128 개의 값을 전송할 수 있습니다 (UDP는 직접 x-over 이더넷 연결과 함께 사용되었습니다 컴퓨터). 따라서 연결된 터치 스크린의 변수 수에 따라 허용되는 변수 수는 엄격하게 제어됩니다. 또한 호스트 (실시간 컴퓨팅에 사용되는 공유 메모리 버스가있는 매우 복잡한 다중 프로세서 아키텍처를 가지고 있음에도 불구하고)는 휴대 전화의 처리 능력의 약 1/100을 가졌으므로 가능한 한 적은 처리를 수행해야하며 서버입니다. / client는 이것을 보장하기 위해 어셈블리로 작성해야했습니다 (호스트는 프로그램에 영향을받지 않는 전체 실시간 시뮬레이션을 실행하고있었습니다).
문제였습니다. 터치 스크린에서 변경 될 때 일부 값은 새로 입력 한 값만 가져 가지 않고 해당 값과 이전 값 사이에서 무작위로 순환합니다. 특정 페이지 조합이있는 특정 페이지의 일부 특정 값에서만 증상이 나타납니다. 초기 고객 수락 프로세스를 통해 문제를 시작하기 전까지는 문제를 거의 놓치지 않았습니다.
문제를 해결하기 위해 진동 값 중 하나를 선택했습니다.
- 터치 스크린 앱을 확인했는데 진동하고있었습니다
- 데이터베이스를 확인하고 진동
- 통신 앱을 확인하고 진동
그런 다음 wireshark를 중단하고 패킷 캡처를 수동으로 디코딩하기 시작했습니다. 결과:
- 진동하지 않지만 패킷이 제대로 보이지 않아 너무 많은 데이터가있었습니다.
결함 / 오류가없는 것을 발견하면서 통신 코드의 모든 세부 사항을 수백 번 밟았습니다.
마지막으로 나는 다른 개발자에게 이메일이 없어지기 시작했습니다. 그런 다음 찾았습니다.
분명히, 그는 데이터를 전송할 때 전송하기 전에 데이터 배열을 플러시하지 않았으므로 본질적으로 이전 값을 덮어 쓰는 새 값과 함께 사용 된 마지막 버퍼를 덮어 쓰지만 덮어 쓰지 않은 이전 값은 여전히 전송됩니다.
따라서 값이 데이터 배열의 위치 80에 있고 요청 된 값 목록이 80 미만으로 변경되었지만 동일한 값이 새 목록에 포함 된 경우 두 값 모두 해당 특정 버퍼의 데이터 버퍼에 존재합니다. 주어진 시간.
데이터베이스에서 읽는 값은 UI가 값을 요청한 시간 조각에 따라 다릅니다.
수정은 매우 간단했습니다. 데이터 버퍼에 들어오는 항목 수 (실제로는 패킷 프로토콜의 일부로 포함됨)를 읽고 해당 항목 수를 초과하여 버퍼를 읽지 마십시오.
교훈:
현대 컴퓨팅 능력을 당연한 것으로 여기지 마십시오. 컴퓨터가 이더넷을 지원하지 않았고 어레이를 플러시 할 때 비용이 많이들 수 있습니다. 우리가 얼마나 멀리 왔는지보고 싶다면, 동적 메모리 할당 형태가 거의없는 시스템을 상상해보십시오. IE의 경영진 프로세스는 모든 프로그램의 모든 메모리를 순서대로 사전 할당해야했으며, 그 범위를 넘어서는 프로그램은 성장할 수 없었습니다. IE는 전체 시스템을 다시 컴파일하지 않고 프로그램에 더 많은 메모리를 할당하면 막대한 충돌이 발생할 수 있습니다. 사람들이 언젠가 같은 시각에 쓰레기 수거 전날에 대해 이야기할지 궁금합니다.
사용자 정의 프로토콜로 네트워킹을 수행하거나 일반적으로 이진 데이터 표현을 처리 할 때 파이프를 통해 전송되는 모든 값의 모든 기능을 이해할 때까지 사양을 읽으십시오. 내 눈이 아플 때까지 읽어봐 사람들은 개별 비트 또는 바이트를 조작하여 데이터를 처리하며 매우 영리하고 효율적인 방식으로 작업을 수행합니다. 아주 작은 디테일이 없으면 시스템이 손상 될 수 있습니다.
문제를 해결하는 데 걸리는 시간은 대부분 2 ~ 3 일이며 대부분의 시간은 내가 이것에 좌절했을 때 다른 일을하는 데 소비했습니다.
참고 : 해당 호스트 컴퓨터는 기본적으로 이더넷을 지원하지 않았습니다. 이 카드를 구동하는 카드는 맞춤형으로 개조되었으며 프로토콜 스택은 사실상 존재하지 않았습니다. 내가 함께 일한 개발자는 프로그래머의 지옥이었다.이 프로젝트를 위해 시스템에서 제거 된 UDP 버전과 최소 가짜 이더넷 스택 (프로세서가 전체 이더넷 스택을 처리 할만 큼 강력하지는 않음)을 구현했을뿐만 아니라 그러나 그는 일주일도 채 걸리지 않았습니다. 그는 처음에 OS를 설계하고 프로그래밍 한 최초의 프로젝트 팀 리더 중 한 사람이었습니다. 컴퓨터 / 프로그래밍 / 아키텍처에 관해 그가 얼마나 오래 감아 왔는지, 또는 이미 얼마나 새로운 지에 상관없이 그가 말해야 할 것은 무엇이든 말입니다.