2012-08-16 14 views
11

Not: Bugünkü gibi bir sorunum varsa, bu sorunu listeliyorum. (), uygulamanın değiştirilmesini (örneğin, sınıfın oluşturulmasını ortak bir alana taşıma) tersine çevirir. Sadece nasıl yapılacağından emin değilim. : Son NotLinux'ta, device_create'i mevcut bir sınıfta nasıl kullanıyorsunuz?

İki linux çekirdek modülüm var ve bunlar için/sys girdilerini güncellemeye çalışıyorum. google ve diğer kaynaklardan etrafında arama, ben çizgisinde çok fazla kod gördüm:

static dev_t MyDev; 
static struct class *c1; 

static int __init start_func(void) 
{ 
    ... 
    MyDev = MKDEV(nMajor, MINOR_VERSION); 
    register_chrdev_region(MyDev, 1, MODULE_NAME); 
    c1 = class_create(THIS_MODULE, "chardrv"); 
    device_create(c1, NULL, MyDev, NULL, MODULE_NAME); 
    .... 

Ve bu kod çalışır benim ilk modülü için doğrulanmış ettik ve doğru bir oluşturur:

/sys/class/chardrv/<MODULE_NAME> 

girişi. Bilmek istediğim, mevcut bir sınıfta nasıl bir cihaz oluşturuyorsunuzdur. Başka bir deyişle, modüllerimden biri bu yeni chardrv sınıfını yarattı, şimdi diğer modülümün aynı sınıftaki cihazlarını da kaydetmesini istiyorum.

o "chardrv" sınıfı zaten var çünkü

yüzden görmek için bir kontrolü çalıştırabilirsiniz ..., (ikinci modülde) tekrar class_create() çağrı yapamazsınız eğer/sys/class/chardrv var ve bu, class_create() 'ı çağırmam gerekip gerekmediğine karar vermeme yardımcı olabilir, bu sorun değil. Benim sınıf zaten var ve sadece ikinci modülde itibaren buna içine benim yeni cihaz eklemek istiyorsanız

if (path "/sys/class/chardrv" does not exist) 
    new_class = class_create("chardrv") 
else 
    new_class = some how get class "chardrv" handle, or properties, or whatever 
device_create(new_class, ...) 

Yani bu örnekte göre, İhtiyacım varsayalım: netleştirmek için buraya biraz sözde kodu koymak sağlar Bir sınıf yapısı oluşturmak ve bir şekilde doğru "chardrv sınıfı" öznitelikleriyle doldurmak ve sonra device_create'i önceki gibi çağırmak, ancak bunu nasıl yapacağımı bilmiyorum.

cevap

-1

Linux çekirdeği bunu yapmaya izin vermeyecektir. Bu alacaksın HATA.

**[ 865.687824] kobject_add_internal failed for net with -EEXIST, don't try to register things with the same name in the same directory. 
[ 865.687835] Pid: 6382, comm: insmod Tainted: P  W O 3.2.16.1JeshuLinux #1 
[ 865.687840] Call Trace: 
[ 865.687849] [<c1584382>] ? printk+0x2d/0x2f 
[ 865.687859] [<c12a5438>] kobject_add_internal+0x138/0x1d0 
[ 865.687869] [<c12a5a11>] kset_register+0x21/0x50 
[ 865.687879] [<c137b63d>] __class_register+0xcd/0x1b0 
[ 865.687888] [<f8d0a0aa>] hello_init+0x4a/0x80 [sysfs_Dev] 
[ 865.687897] [<c1003035>] do_one_initcall+0x35/0x170  
[ 865.687909] [<f8d0a060>] ? enable_show+0x40/0x40 [sysfs_Dev]  
[ 865.687919] [<c10928d0>] sys_init_module+0x2c0/0x1b50  
[ 865.687941] [<c159485f>] sysenter_do_call+0x12/0x28  
[ 865.687947] Registering Class Failed** 

If you want to understand sysfs read: [mochel.pdf](www.kernel.org/pub/linux/kernel/people/mochel/doc/papers/ols-2005/mochel.pdf) 
+1

Burada yapmaya çalıştığım zaman açık olduğun konusunda emin değilim ... en azından bu hata sorumu akla getirmiyor. Örneğin bir "chardrv" sınıfı oluşturmak istiyorum, daha sonra bir çekirdek modülüne bir cihaz kaydettirmek istiyorum. "Device1" deyin. Daha sonra ikinci bir çekirdek modülü aynı cihaza "device2" içine ikinci bir cihaz kaydedecektir. Yani şimdi/sys/class/chardrv üzerinde bir liste komutu çalıştırarak her iki cihazı da gösterecektir. Linux'ta bunu yapmanın bir yolu olmadığını mı söylüyorsunuz? Bana doğru görünmüyor ... – Mike

3

aynı sınıf geçme, sadece tekrar device_create() çağırır, sizin örnek kod izleyin, örneğin:

MyDev = MKDEV(nMajor, MINOR_VERSION); 
register_chrdev_region(MyDev, 1, MODULE_NAME); 
c1 = class_create(THIS_MODULE, "chardrv"); 
device_create(c1, NULL, MyDev, NULL, MODULE_NAME); 
... 
device_create(c1, NULL, MyDev2, NULL, "mydev2"); 

Kesinlikle sırayla yolunu kontrol etmek gerekmez sınıfa olmadığını belirlemek için yaratıldı. Kodunuzda oluşturuyorsunuz, bu yüzden c1 == NULL için test edin veya gerekiyorsa bir bayrak kullanın.

+0

Bu basit kullanım için, evet, işe yarayacak. İkinci bir çekirdek cihazım ne zaman? Sorularımı düzelttiğimde, bir _second_ çekirdek modülünün aynı/sys/class/chardrv directroy içine bir aygıt oluşturmak isteyeceğini de belirttim. Açıkçası, her iki yerde de 'class_create()' işlevine gerek yoktur. Ancak, bu yöntemi çağırmazsam, 'device_create() 'parametresi 1 için gerekli olan chardrv sınıfıma nasıl erişebilirim? Bir kez daha: ** Modül 1 **, class_create()/device_create() 'işlevlerini çağırır. ** Modül 2 ** sadece 'device_create()' işlevini çağırmak ister, ancak sınıf referansını gerektirir. – Mike

+0

Sınıfı almak için bir API eklemeniz gerekiyor. En basit seçenek, çekirdeği doğru bir şekilde (bir modül değil) koymak ve modüllerin buna çağırmasını sağlamaktır. – mpe

+0

Ve ben bununla iyiyim, uygulama esnektir. Ancak hala nasıl emin değilim. Class_create() 'dediğimde, parametre1, THIS_MODULE'dir. Sınıfın yaratımını doğru bir şekilde hareket ettirerek, THIS_MODULE'un artık çalışmayacağını düşünüyorum. Class_create işlevinin tanımı P1'in: "_owner: bu struct sınıfına sahip olan modülün işaretçisi" olduğunu söylüyor. Bu, sahibinin bir modül olması gerektiğini ima eder. – Mike

6

Aynı sınıfla device_create işlevini kullanmak için, aynı sınıfa bir işaretçi iletmeniz yeterlidir.

Sınıfı oluşturduğunuzdan farklı bir modülde device_create'u aramak istediğinizden, işaretçinin sembolünü sınıfa dışa aktarmanız gerekir. Bunu yapmak için EXPORT_SYMBOL makrosunu kullanabilirsiniz. Örneğin


:

module1.c:

extern struct class *c1; /* declare as extern */ 
EXPORT_SYMBOL(c1);   /* use EXPORT_SYMBOL to export c1 */ 

static dev_t mod1_dev; 
static int __init start_func(void) 
{ 
     ... 
     /* define class here */ 
     c1 = class_create(THIS_MODULE, "chardrv"); 

     /* create first device */ 
     device_create(c1, NULL, mod1_dev, NULL, "mod1_dev"); 
     .... 
} 

modül2.c

extern struct class *c1; /* declare as extern */ 

static dev_t mod2_dev; 
static int __init start_func(void) 
{ 
     ... 
     /* c1 is defined in module 1 */ 

     /* create second device */ 
     device_create(c1, NULL, mod2_dev, NULL, "mod2_dev"); 
     .... 
} 

Not: Sınıf işaretçi tanımlanmış ve module1 ihraç edilmektedir beri module1modül2 önce eklemek gerekir. Bir Invalid parameters hatayı alıyorsanız eğer yüklemeye çalıştığınızda, arada

  • /sys/class/chardrv/mod1_dev
  • /sys/class/chardrv/mod2_dev

: Eğer bekliyoruz dizinleri oluşturmalısınız

ikinci modül, add a KBUILD_EXTRA_SYMBOLS line to your Makefile'a sahip olabilirsiniz.

0

Sadece birinci modülünüzün modül init işlevi sınıfını oluşturun, - global sınıf sembolünü EXPORT_SYMBOL ile dışa aktarın ve diğer modülden kullanın.

Sınıfın sahibi ilk modülünüz olduğundan, bu aygıta bir aygıt eklediğinizde, ilk modülün referans sayacı artar: bunu kullanan herhangi birini boşaltamazsınız.

İlgili konular