Linux driver development issues essay

1. Kernel space and user space data exchange method

There are two situations:
1> When the amount of data that needs to be exchanged is large;
2> When the amount of data that needs to be exchanged is small;< /span>

In the first case the following function is used:

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);

The return value indicates the number of bytes successfully copied.

In the second case, use the macro definition shown below:

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

2. What is the difference between the device number applied for by MKDEV and the device number applied for by register_chrdev_region?

The "device number" described in the two methods is the same. The difference can be summed up in one sentence: whether it has been recognized by the system.

MKDEV(ma, mi) is a macro definition, its function is to combine the parameters major and minor from two scattered values ​​into a unified dev_t type (unsigned long). The "device number" obtained after executing this macro definition means that you want to get this device number and declare to the world that it belongs to you, but at this time it is just your unilateral declaration.

The usage of register_chrdev_region() is usually to pass in the device number from MKDEV() as a parameter. It can be understood that after the developer unilaterally declares that he wants to monopolize a certain device number, the device number is submitted to the operating system for approval. When the function returns a value of 0, it means that the Linux system has passed the developer's application, and the device number previously generated by MKDEV() has been recognized by both the developer and the operating system.

3. What is the difference between register_chrdev_region() and alloc_chrdev_region()?

The prototypes of the two functions are as follows:

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);

The purpose of the two functions is the same, both to obtain (apply for) an exclusive device number from the system. But the former is used for "static application" and the latter is used for "dynamic application".

Static application means that the developer statically assigns a device number to a device and submits it directly to the system for approval.

However, device number resources are limited. For some dynamically loaded drivers, you may encounter the situation that the statically specified device number has been occupied. The best solution at this time is to apply directly to the system for an available device number.

4. Create a kernel thread

can be created using the kthread_run macro definition. Its prototype is as follows
#define kthread_run(threadfn, data, namefmt, …)
  The parameter threadfn represents the function name used to be executed in the child thread. The prototype of the sub-thread function is: int (*threadfn)(void *data)
  The parameter data represents the data address to be passed to the sub-thread function.
  The parameter namefmt and the following variable-length parameters are used to combine into the name of this sub-thread.
  
  This macro defines the return value as the address of a struct task_struct structure. You can use IS_ERR(ts) to determine whether the child thread is successfully created.

5. Memory allocation in the kernel

There are two common functions for allocating memory in kernel development:

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

The kmalloc function is similar to the malloc function. The memory space it allocates is physically address-continuous. But it can only allocate a maximum of 128KB of memory space in the kernel. There are two commonly used values ​​for the second parameter of this function: 1. GFP_KERNEL; 2. GFP_ATOMIC; respectively corresponding to whether to block the call when there is insufficient memory.
The memory space allocated by the vmalloc function is continuous in the virtual address, but not necessarily in the physical address. Therefore this function can be used to allocate large memory space, up to 1GB.

If the kernel development involves frequent application and release of memory space, in order to avoid memory fragmentation, memory pool technology can be used to solve the problem.

Guess you like

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