The operating system provides services for the processes running on it through system calls.
When the user-state process initiates a system call, the CPU switches to the kernel state and starts executing a kernel function . Kernel functions are responsible for responding to application requirements, such as manipulating files, making network communications, or requesting memory resources.
Original address: Https://learn-linux.readthedocs.io
Play Linux old group full, please Gabing: 278378501.
Welcome to our public number: Appetizer programming (Coding-fan)
To give the simplest example, the application process needs to output a line of text that calls the write system call:
#include <string.h>#include <unistd.h>int main(int argc, char *argv[]){ char *msg = "Hello, world!\n"; write(1, msg, strlen(msg)); return 0;}
Annotations
Readers may have some questions-does the output text use functions like printf ?
That's true. printf is a higher-level library function, built on top of system calls, to achieve data formatting and other functions. Therefore, it is essentially the system call that plays a decisive role.
Invoke process
So, within the application, what is the process of invoking a system call?
We introduce a hypothetical system called XYZ , for example, to describe all aspects of a system call.
For example, the system call executes the following process:
- The application code calls the system call ( xyz ), which is a library function called by a wrapper system;
- Library Functions ( XYZ ) is responsible for preparing the parameters passed to the kernel and triggering a soft interrupt to switch to the kernel;
- After the CPU is interrupted by a soft interrupt , the interrupt handler function is executed, that is, the system call handler function ( system_call);
- The system call handler calls the system call service routine ( sys_xyz ) and really begins to process the system call;
Execution state Switching
Application ( application program) and the library function ( libc ), the system calls the handler function (systems call handler ) and system call service routines , which are common function calls, are not difficult to understand. But between the library function and the system call processing function , because involves the user state and the kernel state switch, must be more complex.
Linux switches from User state to kernel state through soft interrupts . The user state and the kernel state are independent execution streams, so when switching, you need to prepare the stacks and save the registers .
The kernel implements a number of different system calls (providing different functions), while the system call handler functions only one. Therefore, the user process must pass a parameter to differentiate, which is the system call number . In Linux , system call numbers are typically passed through the eax Register .
In summary, the execution state switching process is as follows:
- The application prepares the call parameters in the user state , executes the int instruction to trigger the soft interrupt , and the interrupt number is 0x80 ;
- After the CPU is interrupted by the soft interrupt, the corresponding interrupt processing function is executed, then the kernel state is entered.
- The system calls the handler to prepare the kernel execution stack , and saves all registers (usually implemented in assembly language);
- The system call handler function calls the corresponding C function According to the system call number --The system invokes the service routine ;
- The system calls the handler function to prepare the return value and restore the register from the kernel stack ;
- The system calls the handler function to perform the ret instruction switch back to the user state ;
Programming practices
Below, through a simple program, see how the application prepares parameters in the user state and triggers a soft interrupt with an int instruction to sink into the kernel state to execute the system call :
.section .rodatamsg: .ascii "Hello, world!\n".section .text.global _start_start: # call SYS_WRITE movl $4, %eax # push arguments movl $1, %ebx movl $msg, %ecx movl $14, %edx int $0x80 # Call SYS_EXIT movl $1, %eax # push arguments movl $0, %ebx # initiate int $0x80
This is an assembly language program, the program entry after the *_start* tag.
Line , prepare the system call number : Put the constant 4 in the register eax . system call Number 4 represents the system call Sys_write , and we will write a string to the standard output through the system call.
Line 14-16 , prepare the system call parameters: The first parameter is put into the register ebx , the second parameter is put into ecx , and so on.
A write system call requires 3 parameters:
- File descriptor, standard output file descriptor is 1 ;
- Write content (buffer) address;
- The length of the write content (in bytes);
Line , the execution of the int instruction triggers the soft interrupt 0x80 , and the program will fall into the kernel state and be called by the kernel system. After the system call executes, the kernel will be responsible for switching back to the user state, and the application continues to execute the instructions (starting with line).
Line 20-24 , call the exit system call to exit the program.
Annotations
Notice that the exit system call must be explicitly called to exit the program. Otherwise, the program will continue to execute down and eventually encounter a segment error ( segmentation fault )!
The reader may be curious-this call is not required when writing C or other programs!
This is because the C library ( libc ) has helped you to get the dirty work dirty dry.
Next, we compile and execute this Assembly language program:
$ lshello_world-int.S$ as -o hello_world-int.o hello_world-int.S$ lshello_world-int.o hello_world-int.S$ ld -o hello_world-int hello_world-int.o$ lshello_world-int hello_world-int.o hello_world-int.S$ ./hello_world-intHello, world!
In fact, putting the system call number and calling parameters into the correct registers and triggering the correct soft interrupts is a recurring nuisance. The C Library has already dried up the dirty dirty-try the Syscall function!
#include <string.h>#include <sys/syscall.h>#include <unistd.h>int main(int argc, char *argv[]){ char *msg = "Hello, world!\n"; syscall(SYS_write, 1, msg, strlen(msg)); return 0;}
Next
Subscribe to the update For more information, please follow our public number:
Reference documents
- Serg Iakovlev
- Write (2)-Linux manual page
- Syscall (2)-Linux manual page
- _exit (2)-Linux manual page
Principles of Linux System invocation