Open gh-liu opened 4 months ago
系统调用描述的是用户程序进入内核后执行的任务。 用户程序利用系统调用能执行许多操作:创建进程、网络、文件以及I/O操作等。
用户程序
内核
man page for syscalls(2) 列出了全部系统调用。
// syscall/syscall_linux.go func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {} func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {} func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {} func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno){} // 不带 Raw 函数会在进入/退出系统调用的时候,通知 runtime // 不通知 runtime,则没有办法通过调度,把这个 G 的 M 的 P 调度走
// runtime/internal/syscall/asm_linux_amd64.s // func Syscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr) // // We need to convert to the syscall ABI. // // arg | ABIInternal | Syscall // --------------------------- // num | AX | AX // a1 | BX | DI // a2 | CX | SI // a3 | DI | DX // a4 | SI | R10 // a5 | R8 | R8 // a6 | R9 | R9 // // r1 | AX | AX // r2 | BX | DX // err | CX | part of AX // // Note that this differs from "standard" ABI convention, which would pass 4th // arg in CX, not R10. TEXT ·Syscall6<ABIInternal>(SB),NOSPLIT,$0 // a6 already in R9. // a5 already in R8. MOVQ SI, R10 // a4 MOVQ DI, DX // a3 MOVQ CX, SI // a2 MOVQ BX, DI // a1 // num already in AX. SYSCALL CMPQ AX, $0xfffffffffffff001 JLS ok NEGQ AX MOVQ AX, CX // errno MOVQ $-1, AX // r1 MOVQ $0, BX // r2 RET ok: // r1 already in AX. MOVQ DX, BX // r2 MOVQ $0, CX // errno RET
以上函数的实现都是汇编,按照linux的syscall调用规范: 在汇编中把参数依次传入相关寄存器,并调用SYSCALL指令即可进入内核处理逻辑,系统调用执行完毕之后,返回值放在 RAX 中。
linux
syscall
SYSCALL
syscall/syscall_linux_amd64.go
阻塞的系统调用,定义成:
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
非阻塞的系统调用,定义成:
//sysnb socket(domain int, typ int, proto int) (fd int, err error)
根据这些注释,mksyscall.pl 脚本会生成对应的平台的具体实现: 标记 //sys 的系统调用使用的是 Syscall 或者 Syscall6,因为阻塞调用需要通知runtime调度p 标记 //sysnb 的系统调用使用的是 RawSyscall 或 RawSyscall6
提供给用户的 syscall 库,在使用时,会使 G 和 P 分别进入 Gsyscall 和 Psyscall 状态(使用 entersyscall/exitsyscall 与调度交互) 而 runtime 封装的这些 syscall 无论是否阻塞,都不会调用 entersyscall 和 exitsyscall
go syscall
man page for syscalls(2) 列出了全部系统调用。
SYSCALL 定义
阻塞的系统调用,定义成:
非阻塞的系统调用,定义成:
根据这些注释,mksyscall.pl 脚本会生成对应的平台的具体实现: 标记 //sys 的系统调用使用的是 Syscall 或者 Syscall6,因为阻塞调用需要通知runtime调度p 标记 //sysnb 的系统调用使用的是 RawSyscall 或 RawSyscall6
runtime 中的 SYSCALL