Linux kernel space and user space information interaction method

  
 

Abstract: When developing system-level developments such as device drivers and kernel function modules, it is often necessary to exchange information between the kernel and the user program. Linux provides a variety of methods to accomplish these tasks. This article summarizes the various commonly used methods of information exchange, and demonstrates the characteristics and usage of these methods with simple examples. There are methods that are very familiar to everyone, and there are also means available under special conditions. By comparing these methods, we can deepen our understanding of the Linux kernel and, more importantly, allow us to be more proficient in linux kernel-level application development techniques.


Kernel-space VS User-space As a Linux developer, you should first understand the difference between kernel space and user space. There is a lot of relevant information on this topic, which we briefly describe here:

Storage management in modern computer architectures usually includes protection mechanisms. The purpose of providing protection is to prevent a task in the system from accessing a storage area belonging to another or belonging to the operating system
. As in the Intel X86 architecture, a privilege-level protection mechanism is provided to limit access to the storage area by privilege level differences. Based on this architecture, the Linux operating system
divides itself: some core software is independent of normal applications and runs at a higher privilege level (Linux uses the privilege level 3 of the Intel system to run the kernel). They reside in the protected memory space and have all the permissions to access the hardware device. Linux refers to this as kernel space.

Relative, other parts are executed as application in user space. They can only see some of the system resources that they are allowed to use, and they cannot use certain system functions, they can't access the hardware directly, they can't directly access the kernel space, and of course there are other specific usage restrictions. (Linux uses the privilege level 0 of the Intel system to run user programs.)

It is very effective to put user space and kernel space under this asymmetric access mechanism from a security perspective. It can defend against malicious users. The snooping can also prevent the infringement of poor quality user programs, thus making the system run more stable and reliable. However, if the user program does not allow access to and use of kernel space resources like this, then our system will not provide any meaningful features. In order to facilitate the user program to use resources that can be fully controlled in the kernel space without violating the above privilege rules, a standard access interface is defined from the hardware architecture itself to the operating system. For details on the X86 system, please refer to Resources 1

General hardware architectures provide a "door" mechanism. The meaning of "door" means that a low privileged application can enter a highly privileged kernel space through these "doors" when a specific event occurs. For the Intel X86 system, the Linux operating system utilizes the "system gate" hardware interface (by calling int $0x80 machine instructions), constructing a variety of system calls as a software interface, for the application from the user state into The kernel state provides the channel. By using “system call"""system gate"; does not require special permissions, but the specific location of the kernel is not arbitrary, this location is specified by “ system call & rdquo; Keep the kernel safe and secure. We can visually describe this mechanism: as a tourist, you can buy a ticket to enter the safari park, but you must sit on the sightseeing car and follow the prescribed route. Of course, you are not allowed to get off, because it is too dangerous, not to let you lose your life, or to scare you wild animals.

For efficiency and code size considerations, kernel programs cannot use standard library functions (of course there are other concerns, please refer to Resources 2 for detailed reasons). Therefore, kernel development is not as convenient as user program development. And because the current (linux2.6 has not been officially released) kernel is "non-preemptive", so the process running in kernel space will not be replaced by other processes (unless the process voluntarily give up CPU control, such as calling Sleep(), schedule(), etc.), so whether in the process context (such as running a read system call) or in the interrupt context (in the interrupt service routine), the kernel program can not occupy the CPU for a long time, otherwise other programs Will not be able to execute, only wait.

Interaction between kernel space and user space Nowadays, more and more applications need to write kernel-level and user-level programs to accomplish specific tasks together. Usually the following modes are used: First, write a kernel service program. Use the permissions and services provided by kernel space to receive, process, and cache data; then write user programs to interact with previously completed kernel service programs. Specifically, you can use user programs to configure kernel server parameters and extract kernel service programs. The data provided, of course, can also be entered into the kernel service program.

A typical application includes: Netfilter (kernel server: firewall) VS Iptable (user level program: rule setting program); IPSEC (kernel server: VPN protocol part) VS IKE (user level program: vpn Key negotiation processing); of course, a large number of device drivers and corresponding application software are also included. These applications are all done by kernel-level and user-level programs that exchange information together to accomplish specific tasks.

Information interaction method The information exchange between the user program and the kernel is two-way, that is, it can actively send information from the user space to the kernel space, or submit data from the kernel space to the user space. Of course, the user program can also actively extract data from the kernel. Below we will summarize and summarize the methods of kernel and user interaction data.

Information interaction According to the information transmission initiator can be divided into two categories: the user transmits/extracts data to the kernel and the kernel submits the request to the user space. First, the information interaction initiated by the user-level program is initiated.

User-level program initiated information interaction A write your own system call As can be seen from the foregoing, system calls are the most basic method for user-level programs to access the kernel. Currently Linux provides more than 200 standard system calls (see include/asm-i386/unistd.h and arch/i386/kernel/entry.S files in the kernel code tree) and allows us to add our own system calls. To achieve information exchange with the kernel. For example, we want to create a system call log system that records all system call actions for intrusion detection. At this point, we can write a kernel server. This program is responsible for collecting all system call requests and logging these call information to a self-built buffer in the kernel. We can't implement complex intrusion detection procedures in the kernel, so the records in this buffer must be extracted into user space. The most straightforward way is to write a new system call to implement this function of extracting buffered data. After the kernel service program and the new system call are implemented, we can write the user program in the user space for the intrusion detection task. The intrusion detection program can periodically, rotate, or call the new system call to extract data from the kernel when needed, and then Intrusion detection.

B Writing Drivers One of the features of Linux/UNIX is to treat everything as a file (every thing is a file). The system defines a simple and complete driver interface, and the client program can interact with the kernel driver through this interface in a unified way. Most users and developers of the system are already familiar with this interface and the corresponding development process.

The driver runs in kernel space, and the user-space application interacts with it through a file in the /dev/directory of the file system. This is the file operation flow we are familiar with: open() —— read() —— write() —— ioctl() —— close(). (It should be noted that not all kernel drivers are this interface. The use of network drivers and various protocol stacks is not consistent. For example, socket programming has concepts such as open()close(), but it The kernel implementation and external usage are quite different from normal drivers.) For details on programming in this section, see Resources 3 and 4.

Copyright © Windows knowledge All Rights Reserved