Considerations for writing Linux device drivers

1ShyJn25 2022-06-24 07:57:00 阅读数:341


Considerations for writing device drivers

The difference between application development and driver development

stay Linux There are generally two kinds of program development on , One is kernel and driver development , The other is application development . These two types of development correspond to Linux Two states of , They are kernel mode and user mode . Kernel mode is used to manage user mode programs , Complete the user status request ; The user mode handles the software work of the upper layer . The driver interacts with the underlying hardware , So it works in kernel mode .
Most programmers work on application development , A few programmers are devoted to the development of kernel and driver . Relative to application development , The development of kernel and driver is very different . The most important differences include the following :

  • The kernel and driver cannot be accessed during development C library , because C Libraries are implemented using system calls in the kernel , And it is implemented in user space .
  • Kernel and driver development must use GNU C, because Linux The operating system has been used from the beginning GNU C, Although you can also use other compilation tools , But you need to make a lot of changes to the previous code .
  • The kernel supports asynchronous terminals 、 Preemption and SMP,, Therefore, the kernel and driver development must always pay attention to synchronization and concurrency .
  • The kernel has only a small fixed length stack .
  • Kernel and driver development lacks memory protection mechanisms like user space .
  • Floating point numbers are difficult to use in kernel and driver development , Integer should be used .
  • Portability should be considered in kernel and driver development , Because for different platforms , The driver is incompatible .

GUN C Develop drivers

GUN C Language originated from a GUN plan ,GUN It means “GUN is not UNIX”.GUN The plan begins with 1984 year , The aim of this project is to develop a similar UNIX And a complete operating system with free software . The plan has been going on , until Linus Development Linux Operating system time ,GNU The project has developed a lot of high-quality free software , Among them is the famous GCC compiler ,GCC The compiler can compile GUN C Language .Linus in consideration of GUN Freedom and free planning , So I chose GCC Compiler to write kernel code , Later, many developers also used this compiler , So until now , Driver developers also use GUN C Language to develop drivers .

Out of commission C Library development driver

Unlike user space applications , The kernel cannot call standard C function library , The main reason is that the kernel is complete C The library is too big . The size of a compiled kernel can be 1MB about , And a standard C The size of the language library can be manipulated 5MB. For embedded devices with small storage capacity , It's not practical . Missing flag C Language library , It doesn't mean that drivers can only do good things .
Most commonly used C Library functions have been implemented in the kernel . For example, the function group that operates the string is located in the kernel file lib/string.c in . Just include <linux/string.h>, You can use them . Another example is that the memory allocation function has been included in include/linux/slab_def.h Implemented in the . Be careful : The header file contained in the kernel program refers to the kernel header file in the kernel code tree , It does not refer to the external header file when developing the application . The print function in the library function implemented in the kernel printk(), It is C Library function printf() The kernel version of .printk() Functions and printf() Functions have basically the same usage and functions .

There is no memory protection mechanism

When a user application has a programming error , Trying to access an illegal memory space , Then the operating system kernel will end the process , And return the error code . Applications can be recovered with the help of the operating system kernel , And the application does not have much impact on the operating system kernel . But if the operating system kernel accesses an illegal memory , Then it is possible to destroy the kernel code or data . This will cause the kernel to be in an unknown state , The kernel will pass through oops Errors give the user some hints , But these tips are not supported 、 Difficult to analyze .
In kernel programming , Illegal memory should not be accessed , In particular, null pointers , otherwise , The kernel will suddenly die , There is no opportunity to prompt the user . For bad drivers , It is very common to cause a system crash , So for driver developers , You should attach great importance to the correct access to memory . A good suggestion is , After applying for memory , The returned address should be detected .

Small kernel stack

User space programs can allocate a large amount of space from the stack to store variables , Even using the stack to store huge data structures or arrays is no problem . This is possible because the application is very memory resident , They can dynamically request and free all available memory space . The kernel requires a fixed resident memory space , Therefore, it is required to occupy the resident memory as little as possible , And set aside as much memory as possible for user programs to use . So the length of the kernel stack is fixed , Not dynamically growing 32 The kernel stack of bit machine is 8KB;64 The kernel stack of bit machine is 16KB.
Because the kernel stack is small , So when writing a program , Small kernel stacks should be fully considered . Try not to use recursive calls , In the application , Recursively call 4000 It may overflow many times , In kernel , The number of recursive calls is very small , Can hardly complete the function of the program . In addition, press after using the memory space , Memory should be freed as soon as possible , To prevent resource leakage , Cause kernel crash .

Value portability

For user space applications , Portability has always been an important issue . General portability is achieved in two ways . One way is to define a set of portable API, And then on this set API It is implemented on these two platforms that need to be ported . Application developers , Just use this portable API, You can write portable programs . In the embedded field , More common API The kit is QT. Another way is to use something like Java、Actionscript And other languages that can be ported to many operating systems . These languages are usually executed by virtual machines , So it can be ported to many platforms .
For drivers , Portability requires attention to the following issues :

  • Consider byte order , Some devices use large endian byte order , Some devices use small endian byte order .Linux The kernel provides the function of byte node order conversion at the large and small ends .
#define cpu_to_le16(v16) (v16)
#define cpu_to_le32(v32) (v32)
#define cpu_to_le64(v64) (v64)
#define le16_to_cpu(v16) (v16)
#define le32_to_cpu(v32) (v32)
#define le64_to_cpu(v64) (v64)
  • Even drivers of the same device , If different chips are used , You should also write different drivers , But it should provide a unified programming interface for users .
  • Try to use macros instead of the physical address of the device port , And you can use ifdefine Macro determines version and other information .
  • For different processors , You should use the functions of the relevant processor .
copyright:author[1ShyJn25],Please bring the original link to reprint, thank you.