2014-09-01 7 views
7

Ich schrieb einen einfachen Char-Treiber und möchte es jetzt automatisch in udev mit Klassen registrieren. Mein Code besteht aus der init-Funktion, die aufgerufen wird, wenn der Treiber geladen wird, und der probe-Funktion, die aufgerufen wird, wenn der Treiber seine Geräte lädt (und natürlich ihre Gegenäquivalente und remove). Das Problem: Sobald ein neues Gerät hinzugefügt wird, schlägt die probe-Funktion beim Ausführen des Befehls device_create fehl. Jetzt frage ich mich warum:Debugging eines einfachen Char-Treibers in Linux fehlgeschlagen auf device_create()

Wie kann ich möglicherweise mehr Informationen darüber erhalten, warum dieser Befehl fehlschlägt (abgesehen davon, dass es fehlschlägt)? Irgendein Argument fehlt (wie gibt es ein Problem mit meiner globalen Deklaration fooClass, sollte ich es stattdessen zu der probe Funktion verschieben, die in meinen Augen nicht Sinn macht, aber in vielen Beispielen gezeigt wird)? Oder irgendein anderer übersehener Fehler?

Nach meinem Code, von dem ich die meisten Rückverifizierung entfernt (wie IS_ERR()) und bereinigen Funktionen für die Lesbarkeit. Diese beiden Variablen sind global definiert:

static int foo_majNbr; 
static struct class *fooClass; 

init Funktion:

static int __init foo_init(void) 
{ 
    int rv; 
    dev_t devNbr; 

    /* Registering driver */ 
    rv = pci_register_driver(&foo_driver); 
     /* ----> see answer below for correct order <---- */ 

    /* Create device class */ 
    fooClass = class_create(THIS_MODULE, CLASS_NAME); 

    /* Allocate device number, just one device for the moment */ 
    rv = alloc_chrdev_region(&devNbr, 0, 1, DEVICE_NAME); 
    foo_majNbr = MAJOR(devNbr); 

    ... 
} 

und die probe Funktion:

static int __devinit foo_probe(struct pci_dev *dev, 
    const struct pci_device_id *devId) 
{ 
    struct foo_dev *foo_dev = 0; 
    int rv = 0; 

    /* Allocate memory in Kernel (for parameters) */ 
    foo_dev = kzalloc(sizeof(*foo_dev), GFP_KERNEL); 
    foo_dev->pci_dev = dev; 
    pci_set_drvdata(dev, foo_dev); 

    foo_dev->devNbr = MKDEV(foo_majNbr, 1); 

    /* Add class to device */ 
    foo_dev->dev = device_create(fooClass, NULL, foo_dev->devNbr, 
     foo_dev, DEVICE_NAME); 
    if (IS_ERR(foo_dev->dev)) { 
     /* ----> INDICATES FAILURE HERE <---- */ 
    } 

    /* Add char device */ 
    cdev_init(&foo_dev->cdev, &foo_fops); 
    rv = cdev_add(&foo_dev->cdev, foo_dev->devNbr, 1); 

    /* Enabling device */ 
    rv = pci_enable_device(dev); 

    ... 
} 

Antwort

5

Sie sollten die Fehlernummer zumindest drucken, den Grund zu kennen.

pr_err("%s:%d error code %d\n", __func__, __LINE__, PTR_ERR(foo_dev->dev)); 
  • PTR_ERR():
  • ERR_PTR ein ungültiger Zeiger auf einen Fehlercode konvertieren(): umwandeln einen Fehlercode auf einen ungültigen Zeiger
  • IS_ERR(): Überprüfen, ob ein Zeiger ist ungültig und einen Fehlercode
  • IS_ERR_OR_NULL(), enthaltend: wie oben, plus es überprüft, ob der Zeiger NULL

in der Datei ist Linux/include/uapi/asm-generic/errno-base.h können Sie die häufigsten Fehler finden. Wenn dieser Fehlercode Ihnen nicht hilft, können Sie unter source code of device_create() herausfinden, wo Ihre Art von Fehler generiert wird und warum.

Vielleicht auch die Argumente von device_create() vor dem Aufruf ausdrucken.

Ich weiß, das ist nicht die Art von Antwort, die magisch lösen Sie Problem :), aber es ist ein Weg, um fortzufahren und den Grund herauszufinden.

+0

Vielen Dank, genau, was ich suchte und es half das Problem zu finden :) - Ich habe die Lösung in einer getrennten Antwort unten veröffentlicht. – lorenzli

2

Die Frage fragt nach Informationen zum Debuggen, die in der vorherigen Antwort gut erklärt wurden. Aus Gründen der Vollständigkeit würde Ich mag die Lösung des eigentlichen Problems teilen hinter warum device_create() fehlgeschlagen:

einen Blick auf die dmesg Protokoll der folgenden Aufruf-Geschichte nach dem Laden des Moduls vorgestellt:

[ 2646.982482] [foo_init:246] CALL | Function called. 
[ 2646.982499] [foo_probe:121] CALL | Function called. 
[ 2646.982503] [foo_probe:147] ERR -19 | Failed to add device to class. 
[ 2646.982535] [foo_init:279] OK | Driver loaded, Major number: 235. 

Wie man sieht, beendet die init()-Funktion ihre Routine nicht, bevor probe() aufgerufen wird.Daher existiert keine Klasse, wenn probe() es dem Gerät hinzufügen möchte. Die Reihenfolge der in init() aufgerufenen Befehle ist das Problem: Der Treiber registriert sich selbst bereits im Kernel, bevor er seine Routine beendet hat. pci_register_driver() muss nur am Ende aufgerufen werden. Hier wird der aktualisierte Code:

static int __init foo_init(void) 
{ 
    int rv; 
    dev_t devNbr; 

    /* Create device class */ 
    fooClass = class_create(THIS_MODULE, CLASS_NAME); 

    /* Allocate device number, just one device for the moment */ 
    rv = alloc_chrdev_region(&devNbr, 0, 1, DEVICE_NAME); 
    foo_majNbr = MAJOR(devNbr); 

    ... 

    /* Registering driver */ 
    rv = pci_register_driver(&foo_driver); 
     /* ----> has to be called at the very end! <---- */ 
} 

Die richtige Reihenfolge gilt auch für die exit() Funktion (wie ich herausgefunden habe, nachdem er mit einem anderen Fehler, die zu einer Konfrontation Oops): Zuerst den Treiber abzumelden, um das Gerät abzumelden und nur dann zerstören die Klasse. Der Code ist wie folgt:

+0

Natürlich habe ich nicht auf deinen Code geachtet :) – Federico