Cehennemden gelen ağ veri yarış durumu
Başka bir geliştirici tarafından yazılmış, gerçekten eski (Encore 32/77) bir iş istasyonunda benzer bir uygulamayla çalışmak için bir ağ istemcisi / sunucusu (Windows XP / C #) yazıyordum.
Uygulamanın temelde yaptığı şey, sistemi çalıştıran ana bilgisayarı kontrol etmek için fantezi PC tabanlı çoklu monitör dokunmatik ekran kullanıcı arayüzümüzle belirli verileri paylaşmak / üzerinde değişiklik yapmaktı.
Bunu 3 katmanlı bir yapıyla yaptı. İletişim süreci, ana bilgisayara veri okudu / yazdı, gerekli tüm format dönüşümlerini (endianness, kayan nokta formatı, vb.) Yaptı ve değerleri bir veritabanına yazdı / okudu. Veritabanı, iletişim ve dokunmatik ekran kullanıcı arayüzleri arasında bir veri aracı olarak görev yaptı. Dokunmatik ekran UI'nin uygulaması, PC'ye kaç monitör eklendiğine bağlı olarak dokunmatik ekran arayüzleri oluşturdu (bunu otomatik olarak algıladı).
Ev sahibi ile bilgisayar arasında bir değer paketi verilen zaman çerçevesinde, tel gezintisi başına maksimum ~ 110ms gecikme süresi olan bir seferde tel boyunca maksimum 128 değer gönderebilir (UDP, arasında bir x-over ethernet bağlantısı ile kullanıldı) bilgisayarlar). Bu nedenle, eklenen dokunmatik ekranların değişken sayısına bağlı olarak izin verilen değişken sayısı sıkı kontrol altındaydı. Ayrıca, ana bilgisayar (gerçek zamanlı hesaplama için kullanılan paylaşılan bellek veriyolu ile oldukça karmaşık bir çok işlemcili mimariye sahip olmasına rağmen), cep telefonumun işlem gücünün yaklaşık 1 / 100'üne sahipti, bu yüzden mümkün olduğu kadar az işlem yapması gerekiyordu ve sunucusuydu. / istemcinin bunu sağlamak için montajda yazılması gerekiyordu (ev sahibi programımızdan etkilenmeyen tam zamanlı bir simülasyon kullanıyordu).
Sorun buydu. Dokunmatik ekranda değiştirildiğinde bazı değerler sadece yeni girilen değeri almayacak, ancak bu değer ile önceki değer arasında rasgele bir döngü oluşturacaktı. Bu ve sadece belirli bir sayfa kombinasyonuyla belirli bir sayfadaki birkaç belirli değerde belirti ortaya çıktı. İlk müşteri kabul süreci boyunca yayınlamaya başlayana kadar sorunu neredeyse tamamen kaçırdık
Bu sorunu çözmek için salınan değerlerden birini seçtim:
- Dokunmatik ekran uygulamasını kontrol ettim, salınım yapıyordu
- Veri tabanını kontrol ettim, salınımlı
- İletişim uygulamasını kontrol ettim, salınımlı
Daha sonra wireshark'tan ayrıldım ve paket yakalamalarını el ile çözmeye başladım. Sonuç:
- Salınımlı değil, paketler doğru görünmüyordu, çok fazla veri vardı.
Haberleşme kodunun her detayında yüzlerce kez hata / hata bulamadım.
Sonunda, diğer uçta e-postaları ateşlemeye başladım, detaylı bir şekilde eksik olduğum bir şeyin olup olmadığını görmek için nasıl çalıştığını sordum. Sonra onu buldum.
Görünüşe göre, veri gönderdiğinde, iletimden önce veri dizisini temizlemediği için, aslında esasında, eskinin üzerine yazılan yeni değerlerle birlikte kullanılan son tamponun üzerine yazıyordu, ancak eski değerlerin üzerine yazılmıyordu.
Bu nedenle, bir değer veri dizisinin 80. konumundaysa ve istenen değerlerin listesi 80'den küçükse, ancak aynı değer yeni listede mevcutsa, o zaman her iki değer de belirli bir arabellek için veri arabelleğinde mevcut olacaktır. verilen zaman.
Veritabanından okunan değer, UI'nin değeri istediği zaman dilimine bağlıdır.
Düzeltme acı vericiydi. Veri arabellekten gelen öğelerin sayısını okuyun (Aslında paket protokolünün bir parçası olarak bulunurdu) ve arabellek bu sayıdaki öğelerin ötesinde okunmadı.
Dersler öğrenildi:
Verilmiş olan modern bilgi işlem gücünü almayın. Bilgisayarların ethernet'i desteklemediği ve bir diziyi temizlerken pahalı sayılabilecek bir zaman vardı. Gerçekten ne kadar geldiğimizi görmek istiyorsanız, neredeyse hiç dinamik bellek ayırma şekli olmayan bir sistem hayal edin. IE, yürütme sürecinin tüm programların belleğini tüm programlar için önceden tahsis etmesi gerekiyordu ve hiçbir program bu sınırın ötesine geçemezdi. IE, tüm sistemi yeniden derlemeden bir programa daha fazla bellek ayırmak büyük bir çökmeye neden olabilir. İnsanların çöp toplama günleri hakkında bir gün aynı ışıkta konuşup konuşmayacaklarını merak ediyorum.
Özel protokollerle ağ kurarken (ya da genel olarak ikili veri sunumunu kullanırken), borudan gönderilen her değerin her fonksiyonunu anlayana kadar spesifikasyonu okuduğunuzdan emin olun. Demek istediğim, gözlerin acıtıncaya kadar oku. İnsanlar verileri, tek tek bitleri veya baytları manipüle ederek ele alırlar; işleri yapmanın çok akıllıca ve verimli yolları vardır. En küçük ayrıntıyı kaçırmamak sistemi bozabilir.
Düzeltmek için gereken genel süre 2-3 gündü ve çoğu zaman bununla uğraşmak zorunda kaldığımda başka şeyler üzerinde çalışmakla geçti.
SideNote: Söz konusu ana bilgisayar varsayılan olarak ethernet'i desteklemiyordu. Sürmek için kullanılan kart özel olarak yapıldı ve güçlendirildi ve protokol yığını neredeyse yoktu. Çalıştığım geliştirici, bir cehennem programcısıydı, bu proje için sistemde UDP'nin soyulmuş bir versiyonunu ve basit bir sahte ethernet yığınını (işlemci tam bir ethernet yığınını idare edecek kadar güçlü değildi) uygulamıştı. ama bir haftadan az bir sürede yaptı. Ayrıca, işletim sistemini ilk başta tasarlayan ve programlayan özgün proje ekibi liderlerinden biri olmuştu. Diyelim ki, ne kadar sarıldığına veya ne kadar yeni olduğumdan bağımsız olarak bilgisayarlar / programlama / mimarlık hakkında paylaşmak zorunda olduğu her şeyi, her kelimeyi dinlerdim.