Aufsatz zu Problemen bei der Entwicklung von Linux-Treibern

1. Kernel-Space- und User-Space-Datenaustauschmethode

Es gibt zwei Situationen:
1> Wenn die Datenmenge, die ausgetauscht werden muss, groß ist;
2> Wenn die Datenmenge Das, was ausgetauscht werden muss, ist klein;< /span>

Im ersten Fall wird die folgende Funktion verwendet:

unsigned long copy_to_user(void __user* to, const void* from, unsigned long n);
unsigned long copy_from_user(void* to, const void __user* from, unsigned long n). );

Der Rückgabewert gibt die Anzahl der erfolgreich kopierten Bytes an.

Im zweiten Fall verwenden Sie die unten gezeigte Makrodefinition:

#include <asm/uaccess.h>
put_user(local, user);
get_user(local, user);

2. Was ist der Unterschied zwischen der von MKDEV beantragten Gerätenummer und der von register_chrdev_region beantragten Gerätenummer?

Die in beiden Methoden beschriebene „Gerätenummer“ ist dieselbe. Der Unterschied lässt sich in einem Satz zusammenfassen: ob er vom System erkannt wurde.

MKDEV (ma, mi) ist eine Makrodefinition. Ihre Funktion besteht darin, die Parameter Major und Minor aus zwei verstreuten Werten zu einem einheitlichen dev_t-Typ (unsigned long) zu kombinieren. Die nach der Ausführung dieser Makrodefinition erhaltene „Gerätenummer“ bedeutet, dass Sie diese Gerätenummer erhalten und der Welt erklären möchten, dass sie Ihnen gehört, aber zu diesem Zeitpunkt handelt es sich nur um Ihre einseitige Erklärung.

Die Verwendung von register_chrdev_region() besteht normalerweise darin, die Gerätenummer von MKDEV() als Parameter zu übergeben. Es versteht sich, dass, nachdem der Entwickler einseitig erklärt hat, dass er eine bestimmte Gerätenummer monopolisieren möchte, diese Gerätenummer dem Betriebssystem zur Genehmigung vorgelegt wird. Wenn die Funktion den Wert 0 zurückgibt, bedeutet dies, dass das Linux-System die Anwendung des Entwicklers bestanden hat und die zuvor von MKDEV() generierte Gerätenummer sowohl vom Entwickler als auch vom Betriebssystem erkannt wurde.

3. Was ist der Unterschied zwischen register_chrdev_region() und alloc_chrdev_region()?

Die Prototypen der beiden Funktionen lauten wie folgt:

int register_chrdev_region(dev_t from, unsigned int count, const chr* name);
int alloc_chrdev_region(dev_t* dev, unsigned int baseminor, unsigned int count, const char* name) ;

Der Zweck beider Funktionen ist derselbe: Beide dienen dazu, eine exklusive Gerätenummer vom System zu erhalten (zu beantragen). Ersteres wird jedoch für die „statische Anwendung“ und Letzteres für die „dynamische Anwendung“ verwendet.

Statische Anwendung bedeutet, dass der Entwickler einem Gerät statisch eine Gerätenummer zuweist und diese direkt an das System zur Genehmigung übermittelt.

Allerdings sind die Ressourcen für die Gerätenummer begrenzt. Bei einigen dynamisch geladenen Treibern kann es vorkommen, dass die statisch angegebene Gerätenummer belegt ist. Die beste Lösung besteht derzeit darin, direkt beim System eine verfügbare Gerätenummer zu beantragen.

4. Erstellen Sie einen Kernel-Thread

kann mit der Makrodefinition kthread_run erstellt werden. Sein Prototyp lautet wie folgt:
#define kthread_run(threadfn, data, namefmt, …)
  Der Parameter threadfn stellt den Funktionsnamen dar, der im untergeordneten Thread ausgeführt wird . Der Prototyp der Sub-Thread-Funktion lautet: int (*threadfn)(void *data)
  Der Parameter data stellt die Datenadresse dar, die an die Sub-Thread-Funktion übergeben werden soll.
  Der Parameter namefmt und die folgenden Parameter variabler Länge werden verwendet, um den Namen dieses Unterthreads zu ergeben.
  
  Dieses Makro definiert den Rückgabewert als Adresse einer struct task_struct-Struktur. Sie können IS_ERR(ts) verwenden, um festzustellen, ob der untergeordnete Thread erfolgreich erstellt wurde.

5. Speicherzuweisung im Kernel

Es gibt zwei gängige Funktionen zum Zuweisen von Speicher in der Kernel-Entwicklung:

static inline void* kmalloc(size_t size, gfp_t flags);
void* vmalloc(unsigned long size);

Die kmalloc-Funktion ähnelt der malloc-Funktion. Der von ihr zugewiesene Speicherplatz ist physikalisch adresskontinuierlich. Es kann jedoch nur maximal 128 KB Speicherplatz im Kernel zuweisen. Für den zweiten Parameter dieser Funktion gibt es zwei häufig verwendete Werte: 1. GFP_KERNEL; 2. GFP_ATOMIC; jeweils entsprechend, ob der Aufruf blockiert werden soll, wenn nicht genügend Speicher vorhanden ist.
Der von der vmalloc-Funktion zugewiesene Speicherplatz ist in der virtuellen Adresse kontinuierlich, jedoch nicht unbedingt in der physischen Adresse. Daher kann diese Funktion verwendet werden, um großen Speicherplatz von bis zu 1 GB zuzuweisen.

Wenn die Kernelentwicklung eine häufige Anwendung und Freigabe von Speicherplatz erfordert, kann zur Vermeidung einer Speicherfragmentierung die Speicherpooltechnologie zur Lösung des Problems eingesetzt werden.

Ich denke du magst

Origin blog.csdn.net/weixin_45639314/article/details/134466529
Empfohlen
Rangfolge