In Linux, system calls are the only means for the user space to access the kernel, and they are the only legal entry to the kernel. In fact, other methods, such as device files and/proc, must be called by the system..
Generally, ApplicationsProgramYou can use an application programming interface (API) instead of a system call. In fact, this programming interface does not need to correspond to the system call provided by the kernel. An API defines a groupThe programming interface used by the application. They can be implemented as one system call, or by calling multiple system calls, even if no system call is used, there is no problem. In fact, APIs can beTo provide identical interfaces for applications, but their implementations on these systems may be different.
In the Unix world, the most popular application programming interfaces are based on the POSIX standard, and Linux is compatible with POSIX.
From the programmer's point of view, they only need to deal with the API, while the kernel only deals with system calls. The kernel does not care about how library functions and applications use system calls.
System calls (syscils in Linux) are usually called through functions. They usually need to define one or several parameters (input) and may have some side effects. These side effects are returned by a long typeReturn Value indicates success (0 value) or error (negative value ). When an error occurs in a system call, the error code is written to the global variable errno. By calling the perror () function, you can translate the variable into an error word that you can understand.String.
The implementation of system calls has two special features: 1) the function declaration contains asmlinkage restrictions, which are used to notify the compiler to extract only the parameters of this function from the stack. 2) System Call getxxx () is defined as sys in the kernel_ Getxxx (). This is the naming rule that should be followed by all system calls in Linux.
System Call number: in Linux, each system call is assigned a system call number, which can be associated with the system call. When a user space process executes a system call, the systemThe call number is used to specify the system call to be executed. The process does not mention the name of the system call. Once assigned, the system call number cannot be changed (otherwise, the compiled application will crash ).The Unified Call is deleted, and the system call number it occupies cannot be recycled. In Linux, a "not used" system calls sys_ni_syscall (). It does not do any work except-enosys. This error numberIt is designed specifically for invalid system calls. It is rare, but if a system call is deleted, this function is responsible for filling in the space ".
The kernel records the list of all registered system calls in the system call table and stores them in sys_call_table. It is related to the architecture, which is generally defined in entry. S. For each valid system call in this tableSet the unique system call number.
the user space program cannot directly execute the kernel Code . They cannot directly call functions in the kernel space, because the kernel resides in the protected address space, and the application should notify the system in some way, tell the kernel self you need to execute a system call and switch the system to the kernel state, in this way, the kernel can execute the system call on behalf of the application. This notification kernel mechanism is implemented through Soft Interrupt. Soft interruptions on x86 systems are generated by the int $0x80 command. This command will trigger an exception and cause the system to switch to the kernel state and execute the 128th Exception Processing Program, which is the system call processing program named system_call (). it is closely related to hardware architecture, usually in entry. s files are written in assembly languages.
All system calls fall into the kernel in the same way, so it is not enough to just fall into the kernel space. Therefore, the system call number must be sent to the kernel together. On x86, this transfer action is triggeredThe call number is loaded into the eax register before it is disconnected. In this way, once the system calls the processing program, the data can be obtained from eax. The system_call () mentioned above compares the given system call number with nr_syscall.To check its validity. If it is greater than or equal to nr_syscils, the function returns-enosys. Otherwise, the system call: Call * sys_call_table (, % eax, 4 );
Because the table items in the system call table are stored in the 32-bit (4-byte) type, the kernel needs to multiply the given system call number by 4, then, use the obtained result to locate the queryer in the table. Figure 1:
As mentioned above, in addition to the system call number, some external parameter inputs are required. The simplest way is to store these parameters in registers like passing system call numbers. On x86 systems, EBX, ECx,EdX, ESI, and EDI store the first five parameters in sequence. It is rare to have more than six parameters. In this case, a separate register should be used to store pointers pointing to all these parameters in the user space address. The returned values to the user space are also transmitted through registers. On the x86 system, it is stored in the eax register.
System calls must carefully check whether all their parameters are valid and valid. The system call is executed in the kernel space. If users are allowed to pass illegal input to the kernel, the security and stability of the system will be greatly tested. The most important check is to check whether the pointer provided by the user is valid. Before the kernel receives a pointer from the user space, the kernel must ensure that:
1) The memory area pointed to by the pointer belongs to the user space. 2) The memory area pointed to by the pointer is in the address space of the process. 3) For read, The READ memory should be marked as readable. If it is a write operation, the memory should be marked as writable. |
The kernel provides two methods to check required information and copy back and forth data between the kernel space and the user space. Either of the two methods must be called.
Copy_to_user (): write data to the user space. Three parameters are required. The first parameter is the destination memory address in the process space. The second is the source address in the kernel space. The third is the length of data to be copied (in bytes ). Copy_from_user (): read data from the user space. Three parameters are required. The first parameter is the destination memory address in the process space. The second is the origin of the kernel space. The third is the length of data to be copied (in bytes ). Note: Both of them may cause blocking. This happens when pages containing user data are swapped out of the hard disk rather than in the physical memory. At this time, the process will sleep until the page missing handler reswitches the page from the hard disk to the physical memory. |
The kernel is in the process context when executing the system call. The current Pointer Points to the current task, that is, the process that triggers the system call. In the context of a process, the kernel can sleep (for example, during system call blocking or explicitWhen schedule () is called, it can be preemptible. When the system calls the returned data, the control is still in system_call (). It is responsible for switching to the user space and continuing the execution of the user process.
It is easy to add a system call time for Linux. It is difficult to design and implement a system call. The first step in implementing a system call is to determine its purpose. This purpose is clear and unique. Do not write a multi-purpose system call. IOCTL is a negative textbook. The parameters, returned values, and error codes of the new system call are all critical. Once a system call is compiled, registering it as a formal system call is trivial. The following steps are generally taken:
1) Add a table entry at the end of the system call table (usually in entry. s. Starting from 0, the position of the system table item in the table is its system call number. For example 10 system calls are allocated to System Call Number 9 2) system call numbers of any architecture must be defined in include/ASM/unistd. h. 3) system calls must be compiled into the kernel image (modules cannot be compiled ). You only need to put it into a related file under the kernel. |
Generally, system calls are supported by the C library. A user program can use the system call by including the standard header file and linking it with the C library (or using the library function, and then actually calling the library function ). Fortunately, Linux itself provides a set of macros for direct access to system calls. It sets the register and calls the int $0x80 command. These macros are _ syscalln (), where N ranges from 0 to 6, representing the number of parameters to be passed to the system call. This is because the macro must know how many parameters are pushed into the register in what order. Take the open system call as an example:
Open () system call is defined as follows: Long Open (const char * filename, int flags, int Mode) The macro called directly by the system is as follows: # Define nr_open 5 _ Syscall3 (long, open, const char *, filename, Int, flags, Int, Mode) |
In this way, the application can directly use open (). Call open () System Call to directly place the above macro in the application. Each macro has 2 + 2 * n parameters. The meaning of each parameter is simple and clear, which is not described in detail here.