1. What is system call
In the Linux World, we often encounter the term system call. The so-called system call is a series of functions provided by the kernel with very powerful functions. These system calls are implemented in the kernel, and then the system is called to the user in a certain way. Generally, they are implemented through gate traps. System calling is an interface for user programs to interact with the kernel.
Ii. Functions of system calls
System calling plays a huge role in the Linux system. Without system calling, the application will lose the Kernel support.
Many functions we use in programming, such as fork and open, are finally implemented in system calls. For example, we have such a program:
Here we use two functions, fork and exit, both of which are functions in glibc. However, if we track the function execution process, looking at the implementation of the fork and exit functions in glibc, we can find that the implementation code in glibc falls into the kernel in a soft interrupt mode and then implements the function through system calls. The specific process is described in detail in the implementation process of the system call.
It can be seen that system calls are implemented by user interfaces in the kernel. Without system calls, users cannot use the kernel.
Iii. system call reality and call Process
We have also discussed some protection mechanisms in Linux before giving a detailed description of system calls.
The Linux system provides four levels of privilege in the CPU protection mode. Currently, the kernel only uses two levels of privilege, namely "privileged level 0" and "privileged level 3 ", level 0 is the kernel mode we usually talk about. Level 3 is also the user mode we usually talk about. These two levels are mainly used to protect the system. In kernel mode, you can execute some privileged commands and enter user mode, but not in user mode.
It is particularly pointed out that the kernel mode and the user mode use their own stacks respectively, and stack switching is also required when mode switching occurs.
Each process has its own address space (also called process space). The address space of a process is divided into two parts: user space and system space, in user mode, you can only access the user space of the process. In kernel mode, you can access all the address spaces of the process. The address in this address space is a logical address, through the system segment-plane management mechanism, the actual memory to be accessed must be converted to a second-level address, that is, the logical address? Linear address? Physical address.
System calling is equivalent to a function for the kernel. The key issue is the conversion from user mode to kernel mode, stack switching, and parameter passing.
The following process is analyzed based on the kernel source code. The following analysis environment is FC2 and kernel 2.6.5.
The following is a piece of code of arch/i386/kernel/entry. s in the kernel source code.
The above Code defines two very important macros, namely, save_all and restore_all.
Save_all first saves the registers and stack information in user mode, and then switches to kernel mode. Macro _ switch_kernelspace converts the address space to restore_all, which is the opposite of save_all.
There is a system call table in the original kernel code: (in the entry. s file)
In kernel 2.6.5, there are more than 280 system calls. The names of these system calls are all in this system call table.
In this original file, there is a very important section.
This section completes the execution of system calls.
The system_call function finds the corresponding system call in the system call table based on the system call number sent by the user and then executes it.
A very important part from glibc functions to system calls is the system call number.
The system call number is defined in include/asm-i386/unistd. h.
Each system call number corresponds to a system call.
The next step is to expand the macro of the system call.
Macro expansion of system calls without Parameters
!!! Code 6 ::
Macro development of system calls with one parameter
!!! Code 7 ::
Two Parameters
Code 8 ::
# DEFINE _ syscall2 (type, name, type1, arg1, type2, arg2)
The
Code 9 ::
# DEFINE _ syscall3 (type, name, type1, arg1, type2, arg2, type3, arg3)
The
Code 10 ::
# DEFINE _ syscall4 (type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4)
The
Code 11 ::
# DEFINE _ syscall5 (type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4,
Type5, arg5)
The
Code 12 ::
# DEFINE _ syscall6 (type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4,
Type5, arg5, type6, arg6)
_ Res );
From this code, we can see that int $0x80 is used to trigger the system call through a soft disconnection. When a call occurs, the name in the function will be replaced by the system call name. Then call system_call. This process includes the initialization of the system call. The original code for the initialization of the system call is as follows:
In ARCH/i386/kernel/traps. C, whenever the user executes int 0x80, the system will interrupt the processing and give the control to the kernel system_call.
The entire system call process can be summarized as follows:
1. Execute the user program (for example, fork)
2. According to the function implementation in glibc, get the system call number and execute int $0x80 to generate an interruption.
3. Switch the address space and stack, and run save_all. (Kernel Mode)
4. Perform Interrupt Processing and call kernel functions according to the system call table.
5. Run the kernel function.
6. Execute restore_all and return to user mode
After resolving the implementation and calling process of system calls, we can modify or add the system calls of the kernel as needed.
The system calls are described in more detail, so I will talk about the differences between the following database functions and system calls:
In the long-term programming, people find that using system calling has a major disadvantage, so the portability of the program. For example, the system calling functions provided by Linux are different from those provided by windows, the two are not just implemented in different ways. The function names and parameters provided to the user are different. This is understandable. Therefore, if a program that has been implemented uses the Linux system to call the wait4 function for example, it cannot be compiled on Windows. So people think of a way to encapsulate Windows and Linux system calls and give everyone a unified function (I used to call it as an interface), so the program portability problem is solved.
Therefore, we can think that the library function is an encapsulation of system calls (not all library functions), in order to solve some public problems and provide unified system call interfaces, he and the advantages and disadvantages of system calling are: the system calling speed is obviously faster than the library function (not all are, but most are), but the system calling lacks portability. Library functions are slow, but the porting problem is solved. In the development process, you need to decide which one to use based on your actual situation.
What is system call?
A group of subprograms are set in the Linux kernel to implement various system functions, which are called system calls. You can use system invocation commands to call them in your own applications. From a certain perspective, system calls are very similar to common function calls. The difference is that system calls are provided by the core of the operating system and run in the core State. Common function calls are provided by function libraries or users and run in the user State. The two have similarities in usage, which will be mentioned below.
With Linux core, some C language function libraries are provided. These libraries pack and expand system calls because these library functions are closely related to system calls, these functions are also called system calls.
How many system calls are there in Linux?
This question is not so easy to answer, even if Linus torvaldz does not know it all at once.
In the 2.4.4 kernel, there are a total of 221 system calls in a narrow sense, you can go to the <kernel source directory>/include/asm-i386/unistd. h. You can also run the "Man2 syscils" command to view their directories (manpages versions are generally old, and many of the latest calls may not be included ). In a broad sense, system calls are implemented in the form of library functions. The number of these functions has never been counted. This is a thankless activity, and new kernels are constantly being launched, no one cares about the number of changes in each new kernel, at least not even the kernel modifier, because they have never published such a statement.
There is a sorted list together with this article, which cannot be very comprehensive, but common system calls are basically included. Only a few of them are commonly used, this topic will introduce them selectively.
Why use system call?
In fact, many c-language standard functions that we have become accustomed to. The implementation on the Linux platform relies on system calls. Therefore, if you want to have a deep understanding of the underlying principles of the system, understanding various system calls is a preliminary requirement. Furthermore, if you want to become a programming expert in Linux, which we often call hacker, one of the symbols of hacker can also have a thorough understanding of various system calls.
Even with the above reasons, you will find that in common programming, in many cases, system calling is a simple and effective way to implement your ideas, therefore, if possible, you should master some system calls as much as possible, which will bring unexpected help to your program design process.
How does a system call work?
Generally, a process cannot access the kernel. It cannot access the memory occupied by the kernel or call kernel functions. CPU Hardware determines this (that is why it is called "protection mode "). System calls are an exception to these rules. The principle is that the process first fills the register with appropriate values, and then calls a special command, which will jump to a location in a pre-defined kernel (of course, this location is readable but not writable by the user process ). In intelcpu, this is implemented by the 0x80 interrupt. The hardware knows that once you jump to this position, you are not a user running in restricted mode, but the operating system kernel-so you can do whatever you want.
The kernel that a process can jump to is called sysem_call. This process checks the system call number, which tells the kernel process which service to request. Then, it looks at the system call table (sys_call_table) and finds the called kernel function entry address. Then, call the function and wait for some system checks to return to the process (or to other processes if the process time is exhausted ). If you want to read this code, it is in the next line of <kernel source code directory>/kernel/entry. S, entry (system_call.
How to Use System Call?
Let's look at an example:
# Include <Linux/unistd. h>/* define macro _ syscall1 */# include <time. h>/* define the type time_t */_ syscall1 (time_t, time, time_t *, tloc)/* macro, and then obtain the prototype of the time () function */main () {time_t the_time; the_time = Time (time_t *) 0);/* call time system call */printf ("the time is % LD \ n", the_time );} the system calls time to return the number of seconds that have elapsed since GMT, January 1, January 1, 1970. This is the most standard form of system calling. The macro _ syscall1 () is expanded to obtain a function prototype. I will explain it in detail later. But in fact, if you change the program to the following, the program can run the same result. # Include <time. h> main () {time_t the_time; the_time = Time (time_t *) 0);/* call time system call */printf ("the time is % LD \ n ", the_time );} |
This is because in time. H, the system call time has actually been implemented in the form of library functions, saving the call _ syscall1 macro for us to develop the function prototype.
Most system calls are implemented in various C language function libraries. Therefore, in general, we can call system calls just like calling common library functions, we have the opportunity to use the _ syscall * () macros.
_ Syscall?
Seven macros are defined in unistd. H, which are
_syscall0(type,name)_syscall1(type,name,type1,arg1)_syscall2(type,name,type1,arg1,type2,arg2)_syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)_syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5)_syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) |
They do not seem like macros, but they are actually
# Define Max size 100
There is no difference in maxsize.
Their role is to form a prototype of the system call function for us to call in the program. We can easily find that the number behind _ syscall is as large as the number of typen and argn. In fact, the number following _ syscall indicates the number of parameters that form the function after expansion. Let's look at an instance, that is, the time system call we just used:
_syscall1(time_t,time,time_t *,tloc) |
The expanded scenario is as follows:
time_t time(time_t * tloc){ long __res; __asm__ volatile("int $0x80" : "=a" (__res) : "0" (13),"b" ((long)(tloc))); do { if ((unsigned long)(__res) >= (unsigned long)(-125)) { errno = -(__res); __res = -1; } return (time_t) (__res); } while (0) ;} |
We can see that _ syscall1 (time_t, time, time_t *, tloc) is expanded into a function named time. The original parameter time_t is the return type of the function, the original parameter time_t * And tloc constitute the parameters of the new function respectively. In fact, the prototype of the time function used in the program is it.
What is errno?
To prevent confusion with normal return values, the system does not directly return error codes, but puts the error codes in a global variable named errno. If a system call fails, you can read the errno value to confirm the problem.
The error messages represented by different errno values are defined in errno. H. You can also view them by running the "Man 3 errno" command.
It should be noted that the errno value is set only when a function error occurs. If the function does not have an error, the errno value is not defined and is not set to 0. In addition, it is best to store the value of errno into another variable before processing errno, because during error handling, the value of errno is changed even when a function like printf () fails.
Is the system call compatible?
Unfortunately, the answer is-not good. However, this does not mean that your program will crash after three days, because the system calls are provided by the Linux kernel, so they work very stably and do not have to worry about this point, in most cases, system calls are much more reliable and efficient than the code you write.
However, the compatibility of system calls between Linux kernel versions is not as good as imagined, which is determined by the nature of Linux itself. Linux is developed by a group of programming experts in their spare time. Most of them do not regard Linux as a serious commercial software (the current situation is somewhat different, with the growth of Linux commercial companies and Linux-based users, the brains of many people have changed .) The result is that if there is a conflict between the efficiency and compatibility of the new solution, they tend to discard compatibility and pursue efficiency. In this way, if they think that a system call is poorly implemented, they will not hesitate to make changes, and sometimes even get rid of interfaces. what's even more terrible is that they don't even say hello to their modifications, the modification prompt cannot be found in any document. In this way, whenever the new kernel is launched, it is very likely that some system calls will be quietly updated, and user-compiled applications will also go wrong.
Speaking of this, do you feel that your future is dark? Well, don't be too nervous. As we mentioned earlier, as more and more people regard Linux as their own rice bowl, incompatibility is becoming increasingly rare. Linux Kernel Versions later than Version 2.2 are already very stable. However, it is still necessary to test the compatibility of your applications after each new kernel is released to prevent unexpected occurrence.
How can I learn how to use a Linux system?
You can use the "Man 2 system call name" command to view the introduction of each system call, but this requires you to have a good basic English, secondly, you have to have some skills in programming and system programming. manpages won't involve too many application details, because it is just a manual rather than a tutorial. If what manpages provides cannot satisfy you very much, come with me. This column will show you the Infinite Charm of programming for Linux system calls.
Although this column is not an extremely advanced technical article, it has two small requirements for readers: 1) Readers must have some experience in C programming, and this column will not be overly entangled in language details; 2) Readers must have certain experience in using Linux, and this column is not intended to be used in Linux applications. Take a small test standard. If you can fully understand what this article says from the beginning to here, you will be qualified. Pack your bags and prepare for departure!
Appendix: Linux system call list
References
- Linux man pages
- The Linux programmer's guider, Sven goldt & Sven van der Meer & Scott Burkett & Matt Welsh, 1995
- Computer Operating System, Tang Zi Zhe Feng Ping Tang xiaodan, Xi'an University of Electronic Science and Technology Press, 2000
The above is the integration of the two reprinted articles. The materials are still comprehensive and gradually absorbed.