2012-07-04 13 views
12

Geliştirdiğim Linux çekirdeği sürücülerinden biri, çekirdek iletişiminde ağ iletişimini kullanıyor (sock_create(), sock->ops->bind(), vb.).Çekirdek soket programlamadaki select() ve poll() yönteminin benzetimini

Sorun, veri almak için birden çok yuva olacaktır. Bu yüzden çekirdek alanında select() veya poll() simüle edecek bir şeye ihtiyacım var. Bu işlevler dosya tanımlayıcılarını kullandığından, sistem çağrılarını yuva oluşturmak için kullanmazsam sistem çağrılarını kullanamıyorum, ancak çekirdekte çalıştığım için gereksiz görünüyor.

Bu nedenle, sock->sk_data_ready işleyiciyi kendi işleyicimde (custom_sk_data_ready()) bir semaforun kilidini açacak şekilde sarmalamayı düşünüyordum. Daha sonra, semaforu kilitlemeye çalışan ve açık olana kadar engellemeyi bekleyen kendi kernel_select() işlevimi yazabilirim. Bu şekilde çekirdek fonksiyonu custom_sk_data_ready() tarafından açılıncaya kadar çekirdek fonksiyonu uykuya girer. kernel_select() kilidi aldığında kilidi açar ve yeniden kilitlemek için custom_sk_data_ready()'u çağırır. Dolayısıyla, tek ek başlatma custom_sk_data_ready()'u bir soketi bağlamadan önce custom_select()'a yapılan ilk çağrı yanlış bir şekilde tetiklememektir.

Olası bir sorun görüyorum. Çoklu alımlar meydana gelirse, custom_sk_data_ready() numarasına yapılan çoklu aramalar semaforun kilidini açmayı deneyecektir. Dolayısıyla, birden fazla çağrıyı kaybetmemek ve kullanılan sock'u takip etmek için, kullanılan soketlere bir tablo veya işaretçi listesi olmak zorundadır. Ve custom_sk_data_ready(), hangi soketten geçtiğini tablo/listede işaretlemek zorunda kalacak.

Bu yöntem ses mi? Veya standart sistem çağrılarını kullanırken sadece kullanıcı/çekirdek alanı sorunuyla uğraşmalı mıyım?

İlk Bulgu: sock yapısında

Tüm geri arama fonksiyonları bir kesme bağlamında denir. Bu, uyuyamadıkları anlamına geliyor. Ana çekirdek iş parçacığının hazır yuvaların bir listesinde uyumaya izin vermek için, muteksler kullanılır, ancak custom_sk_data_ready() muteksler üzerinde bir spinlock gibi davranmalıdır (mutex_trylock()'u art arda çağırarak). Bu ayrıca herhangi bir dinamik ayırmanın GFP_ATOMIC bayrağını kullanması gerektiği anlamına gelir.


Ek ihtimal: Her açık soket için

, yerine her soket en sk_data_ready() özel bir bir (custom_sk_data_ready()) ile ve bir işçi (struct work_struct) ve çalışma kuyruğu (struct workqueue_struct) oluşturun. Her çalışan için ortak bir process_msg() işlevi kullanılacaktır. Her liste öğesinin yuvaya bir göstericiye sahip olduğu ve çalışan yapısını içerdiği çekirdek modül düzeyi genel listesi oluşturun. Veriler bir sokette hazır olduğunda, custom_sk_data_ready(), aynı soketle eşleşen liste öğesini yürütecek ve bulup, liste öğesinin iş kuyruğu ve işçisiyle queue_work() numaralı telefonu arayacaktır. Daha sonra process_msg() işlevi çağrılacak ve eşleştirme listesi öğesini struct work_struct * parametresinin (adres) içeriği aracılığıyla bulabilir veya çalışan yapısını tutan liste yapısının adresini almak için container_of() makrosunu kullanabilirsiniz.

En çok ses hangi tekniktir?

+0

Eğer 'poll' yapan bir kullanıcı uzay yardımcı programını olamaz mı? ile Çoklama girişi 'poll' veya' select' (duraklatma işlemi boşta olduğundan, böylece diğer işlemler çalıştırabilirsiniz) zamanlayıcı ile ilgilidir yüzden çekirdek içinde yapmayacağım! –

+1

@BasileStarynkevitch: Ben sadece ') (seçmek'() 'anket' uyku engelleme taklit ve çalışıyorum nedeni budur. Bu iki sistem çağrısını kullanarak çekirdeği son çare. Bir kullanıcı uzay yardımcıında 'poll()' ve 'select()' işlevini çalıştırmayla ilgili sorunların olduğundan şüpheleniyorum. yardımcı çekirdek uzayda yaşayan bir soket erişmek ve muhtemelen izinsiz (sock_create() '' yapılır değildir) bir dosya tanımlayıcı erişimi olmalıdır. Şimdi soket oluşturma, kullanıcı alanı yardımcısında ortaya çıkmalı ve modül, kullanıcı alanı dosya tanımlayıcısına dayalı olarak soketi bulmalıdır. Şimdi daha karmaşık hale geliyor. – Joshua

+0

Çekirdeğinizde bunu yapmamalısınız. – mpe

cevap

3

İkinci fikriniz işe yarayacak gibi geliyor.benzer bir şey yapar gibi

CEPH kod görünüyor net/ceph/messenger.c bakın.