2009-03-05 15 views
1

Ben Linux çekirdeğinde bir istemci/sunucu yazıyorum (Evet. Çekirdeğe içinde. Onun tasarım kararı alınmış ve kesinleşmiş. Onun değişmeyecek)Linux çekirdeğinde çalışan sunucu. Dinlemeyi bir iş parçacığında mı yapmalıyım?

sunucu ham soketinden gelen paketleri okur. Bu paketler için aktarım protokolü (üzerinde ham soketin dinlediği) özel ve UDP gibi. Kısacası, gelen bağlantıları dinlemem ve sonra bu bağlantıyı işlemek için bir iş parçacığı çatalıyorum.

Bu ham soketten gelen tüm IP datagramlarını işlemek zorundayım. Ham soket üzerinde sonsuz bir döngüde paketler için okumaya devam edeceğim. Kullanıcı düzeyinde eşdeğer programda, ayrı bir iş parçacığı oluşturup gelen paketleri dinlemeye devam ederdim.

Şimdi çekirdek düzeyinde bir sunucu, ben ayrı bir konu çalıştırmak gerektiği konusunda şüphelerim var ya, çünkü değil:

  1. I() bir I/O operasyonu okumak düşünüyorum. Bu nedenle, read() 'ın içinde bir yerde, çekirdek işlemcinin denetimini bırakmak için program() işlevini çağırmalıdır. Böylece ham soket üzerindeki read() 'i çağırdıktan sonra, mevcut kernel aktif içerik paketler mevcut olana kadar beklemeye alınabilir (belki de bir uyku kuyruğuna konabilir). Paketler geldiğinde, çekirdek çakışması bağlamı, sırada uyuyan okunan içeriğin bir kez daha çalışmaya hazır olduğunu işaret edecektir. Burada 'thread' yerine 'context' kullanıyorum. Bu yüzden ayrı bir çekirdek iplik gerektirmemeliyim. Diğer yandan, eğer() kontrol() 'i terk etmezse, tüm çekirdek engellenecektir.

Sunucumu nasıl tasarlamalıyım konusunda ipuçları veren herhangi biri var mı? 1 numaralı maddede sunulan argümanın yanlışlığı nedir?

+0

Eğer çekirdekte iseniz bir kesinti yoksa veri olduğunda ne yapacağınızı bildirmek için kullanabilirsiniz. Yoksa bu düşük seviye değil mi? – grieve

+0

Bir düzeyde bir geri arama kaydedebilirsiniz - Yanıtımı gör. – MarkR

cevap

2

Çekirdeğinizde hiç bir ham sokete ihtiyacınız olup olmadığından emin değilim. Çekirdeğin içinde bir netfilter kanca ekleyebilir veya tüm paketleri alacak başka bir şey (???) kaydedebilirsiniz; istediğin bu olabilir.

Çekirdeğin içinde bir ham soket kullandıysanız, büyük olasılıkla bir çekirdek iş parçacığına sahip olmanız gerekir (yani, kernel_thread tarafından başlatılmış). Ama bir çekirdek iş parçacığı olması gerekmez, bu sadece istenen bir kernel modu rutinini çağırmak için özel bir çağrı veya aygıt çağrısı yapan bir kullanıcı alanı olabilir.

Kayıtlı bir kanonuz varsa, çağrılan içerik büyük olasılıkla çok fazla işlem yapmaması gereken bir şeydir; Tam olarak bunun ne olduğunu tam olarak bilmiyorum, her ne olursa olsun (bu tür kontrol yapıları bir versiyondan diğerine değişmeye devam ediyor) bir “alt yarım işleyici” veya “görev” olabilir. Umarım aslında bir kesinti servisi rutini değildir. Orijinal soruya yanıt olarak


:

  1. Evet, sys_read bir çekirdek parçacığı ya userspace biri olsun, çağıran iş parçacığı engeller. Sistem asılmayacak.Ancak, çağıran iş parçacığı, engellemenin mantıklı olduğu bir durumda değilse, çekirdek panik yapar (kesmede veya bir şeyde zamanlama)

Evet, bunu ayrı bir iş parçacığında yapmanız gerekecek, hayır olmaz sistemi as. Bununla birlikte, çekirdek modunda sistem çağrısı yapmak çok işe yaramıyor olsa da, her ne kadar işe yarayabilir (çeşit).

Ancak bunun yerine bir çeşit kanca taktıysanız, bunlardan herhangi birini yapmanız gerekmez.

+0

Protokol sürücüleri, bu türdeki her paket için çağrılan bir geri bildirimi kaydeden bir paket türü eklemek için dev_add_pack (linux/netdevice.h) kullanır. Bu oldukça aşırı ve düşük seviyededir. – MarkR

0

Bence en iyi bahisten, sürücülerin nasıl yazılacağını taklit etmek olabilir, sunucunun isteklerin geldiği şeylerin üstünde sanal bir aygıt olarak düşünmesini sağla. Örnek: Bir fare sürücüsü sürekli girişi kabul eder, ancak doğru şekilde programlanmışsa sistemi kilitlemez ve bir ağ bağdaştırıcısı büyük ihtimalle davanıza daha benzer.