Scenario analysis of go language scheduler source code eight: system call

The following content is reproduced from  https://mp.weixin.qq.com/s/CXhc71UZtbdbAo15xbJ6_Q

Awa love to write original programs Zhang  source Travels  2019-04-24

We will discuss preemptive scheduling related to system calls in the last chapter, so it is necessary to have a basic understanding of system calls.

System call refers to the use of similar function calls to call the API provided by the operating system.

Although conceptually system calls are similar to function calls, they are essentially different. The code of the operating system is located in the kernel address space, and the CPU has a low privilege level when executing user code, and no access requires the highest priority. The code and data of the kernel address space can only be accessed, so the functions provided by the operating system cannot be directly called by simple call instructions, but special instructions need to be used to enter the operating system kernel to complete the specified functions.

In addition, the user code calls the operating system API not directly based on the function name, but needs to be called based on an integer number provided by the operating system for each API. The AMD64 Linux platform agrees to use the rax register to store the system call when making a system call. Number, and it is agreed to use rdi, rsi, rdx, r10, r8 and r9 to pass the first 6 system call parameters.

Some readers may say that we don't use system calls in our usual programming? ! In fact, it is not that it is not used, but we did not feel its existence. For example, the simplest way to output strings to the screen, open files, read and write files, and create sockets in network programming, etc., all use system calls. We do not I feel the existence of system calls mainly because the function library or package we use encapsulates them into functions, and we only need to call these functions directly. For example, there is the following piece of go code:

package main 

import ( 
"os" 
) 

func main() { 
        fd, err := os.Open("./syscall.go") // will use the system call to open the file 
        ... 
        fd.Close() // The file will be closed using a system call 
}

The os.Open() and fd.Close() functions here will eventually enter the operating system kernel through system calls to complete the corresponding functions. Take os.Open as an example, it will finally execute the following piece of assembly code to open the file through the openat system call:

mov 0x10(%rsp),%rdi #The first parameter 
mov 0x18(%rsp),%rsi #The second parameter 
mov 0x20(%rsp),%rdx #The third parameter 
mov 0x28(%rsp),% r10 #4th parameter 
mov 0x30(%rsp),%r8 #5th parameter 
mov 0x38(%rsp),%r9 #6th parameter 
mov 0x8(%rsp),%rax #System call number rax = 267 , Means to call the openat system call 
syscall #system call instruction, enter the Linux kernel

Here, the code first saves the 6 parameters and the number 267 of the openat system call in the corresponding register, and then uses the syscall instruction to enter the kernel to execute the function of opening the file.


Finally, if you think this article is helpful to you, please help me click on the “Looking” at the bottom right corner of the article or forward it to the circle of friends, thank you very much!

image

Guess you like

Origin blog.csdn.net/pyf09/article/details/115235476