syscall 包详解
概述
syscall 包提供了对底层操作系统原语的接口。具体实现因底层系统而异,默认情况下 godoc 会显示当前系统的 syscall 文档。
核心功能:
- 系统调用接口(文件、进程、网络、信号等)
- 低级操作系统原语访问
- 平台相关的系统调用号
- 错误处理和类型转换
重要说明:
- ⚠️ 平台相关:细节因操作系统而异
- ⚠️ 使用建议:优先使用 os、time、net 等更便携的包
- ⚠️ 现代替代:新代码应优先使用 golang.org/x/sys 包
- ✅ 错误处理:返回 err == nil 表示成功,否则为 Errno 类型错误
包导入
import "syscall"
常量和变量
错误常量(Errno)
// 常见错误号
var (
EPERM Errno = 0x1 // 操作不允许
ENOENT Errno = 0x2 // 文件或目录不存在
ESRCH Errno = 0x3 // 进程不存在
EINTR Errno = 0x4 // 系统调用被中断
EIO Errno = 0x5 // I/O 错误
ENXIO Errno = 0x6 // 设备或地址不存在
E2BIG Errno = 0x7 // 参数列表过长
ENOEXEC Errno = 0x8 // 可执行文件格式错误
EBADF Errno = 0x9 // 文件描述符错误
ECHILD Errno = 0xa // 子进程不存在
EAGAIN Errno = 0xb // 资源暂时不可用
ENOMEM Errno = 0xc // 内存不足
EACCES Errno = 0xd // 权限不足
EFAULT Errno = 0xe // 地址错误
// ... 更多错误号
)
系统调用号常量
// Linux AMD64 常见系统调用号
const (
SYS_READ = 0
SYS_WRITE = 1
SYS_OPEN = 2
SYS_CLOSE = 3
SYS_STAT = 4
SYS_FSTAT = 5
SYS_LSTAT = 6
SYS_POLL = 7
SYS_LSEEK = 8
SYS_MMAP = 9
SYS_MPROTECT = 10
SYS_MUNMAP = 11
SYS_BRK = 12
SYS_EXIT = 60
SYS_FORK = 57
SYS_EXECVE = 59
SYS_GETPID = 39
SYS_GETUID = 102
SYS_GETGID = 104
// ... 300+ 系统调用号
)
信号常量
const (
SIGHUP Signal = 1 // 挂起
SIGINT Signal = 2 // 中断(Ctrl+C)
SIGQUIT Signal = 3 // 退出
SIGILL Signal = 4 // 非法指令
SIGTRAP Signal = 5 // 跟踪陷阱
SIGABRT Signal = 6 // 中止
SIGBUS Signal = 7 // 总线错误
SIGFPE Signal = 8 // 浮点异常
SIGKILL Signal = 9 // 杀死(不可捕获)
SIGUSR1 Signal = 10 // 用户定义信号 1
SIGSEGV Signal = 11 // 段错误
SIGUSR2 Signal = 12 // 用户定义信号 2
SIGPIPE Signal = 13 // 管道破裂
SIGALRM Signal = 14 // 定时器
SIGTERM Signal = 15 // 终止
SIGCHLD Signal = 17 // 子进程状态改变
SIGCONT Signal = 18 // 继续
SIGSTOP Signal = 19 // 停止(不可捕获)
SIGTSTP Signal = 20 // 终端停止
// ... 更多信号
)
类型详解(按 A-Z 分类)
Dirent
type Dirent struct {
Ino uint64 // inode 号
Off int64 // 偏移
Reclen uint16 // 记录长度
Type uint8 // 文件类型
Name [256]int8 // 文件名
}
功能: 表示目录条目。
EpollEvent
type EpollEvent struct {
Events uint32
Fd int32
Pad int32
}
功能: epoll 事件结构。
事件类型:
EPOLLIN- 可读EPOLLOUT- 可写EPOLLERR- 错误EPOLLHUP- 挂起
Flock_t
type Flock_t struct {
Type int16
Whence int16
Start int64
Len int64
Pid int32
}
功能: 文件锁结构。
ProcAttr
type ProcAttr struct {
Dir string
Env []string
Files []uintptr
Sys *SysProcAttr
}
功能: 进程属性,用于 ForkExec。
Rlimit
type Rlimit struct {
Cur uint64 // 当前限制
Max uint64 // 最大限制
}
功能: 资源限制。
Rusage
type Rusage struct {
Utime Timeval // 用户 CPU 时间
Stime Timeval // 系统 CPU 时间
Maxrss int64 // 最大驻留集大小
Ixrss int64
Idrss int64
Isrss int64
Minflt int64 // 次要页面错误
Majflt int64 // 主要页面错误
Nswap int64
Inblock int64 // 输入块操作
Oublock int64 // 输出块操作
Msgsnd int64
Msgrcv int64
Nsignals int64
Nvcsw int64 // 自愿上下文切换
Nivcsw int64 // 非自愿上下文切换
}
功能: 资源使用情况。
Stat_t
type Stat_t struct {
Dev uint64 // 设备 ID
Ino uint64 // inode 号
Nlink uint64 // 硬链接数
Mode uint32 // 文件模式
Uid uint32 // 用户 ID
Gid uint32 // 组 ID
Rdev uint64 // 设备类型
Size int64 // 文件大小
Blksize int64 // 块大小
Blocks int64 // 块数
Atim Timespec // 最后访问时间
Mtim Timespec // 最后修改时间
Ctim Timespec // 最后更改时间
}
功能: 文件状态信息。
Statfs_t
type Statfs_t struct {
Type int64
Bsize int64
Blocks uint64
Bfree uint64
Bavail uint64
Files uint64
Ffree uint64
Fsid Fsid
Namelen int64
Frsize int64
Flags int64
}
功能: 文件系统状态信息。
SysProcAttr
type SysProcAttr struct {
Chroot string
Credential *Credential
Pdeathsig Signal
Setpgid bool
Setctty bool
Setsid bool
Ctty int
Noctty bool
// ... 更多字段
}
功能: 系统特定的进程属性。
Timeval
type Timeval struct {
Sec int64 // 秒
Usec int64 // 微秒
}
功能: 时间值(微秒精度)。
Timespec
type Timespec struct {
Sec int64 // 秒
Nsec int64 // 纳秒
}
功能: 时间值(纳秒精度)。
函数详解(按 A-Z 分类)
A
Access
func Access(path string, mode uint32) (err error)
功能: 检查调用者是否可以访问指定路径。
参数:
path string- 文件路径mode uint32- 访问模式(F_OK、R_OK、W_OK、X_OK)
返回值:
error- 错误
示例:
package main
import (
"fmt"
"syscall"
)
func main() {
// 检查文件是否存在
if err := syscall.Access("/etc/passwd", syscall.F_OK); err != nil {
fmt.Println("文件不存在")
} else {
fmt.Println("文件存在")
}
// 检查是否可读
if err := syscall.Access("/etc/passwd", syscall.R_OK); err != nil {
fmt.Println("文件不可读")
} else {
fmt.Println("文件可读")
}
}
B
BytePtrFromString
func BytePtrFromString(s string) (*byte, error)
功能: 从 Go 字符串创建 C 风格的字符串指针(以 null 结尾)。
参数:
s string- 输入字符串
返回值:
*byte- 指向字节数组的指针error- 错误
示例:
package main
import (
"fmt"
"syscall"
"unsafe"
)
func main() {
ptr, err := syscall.BytePtrFromString("hello")
if err != nil {
fmt.Println("错误:", err)
return
}
// 使用 unsafe 转换为 C 字符串
fmt.Println("指针地址:", uintptr(unsafe.Pointer(ptr)))
}
C
Chdir
func Chdir(path string) (err error)
功能: 改变当前工作目录。
参数:
path string- 目标目录路径
返回值:
error- 错误
示例:
package main
import (
"fmt"
"syscall"
)
func main() {
if err := syscall.Chdir("/tmp"); err != nil {
fmt.Println("改变目录失败:", err)
} else {
fmt.Println("目录已改变到 /tmp")
}
}
Chmod
func Chmod(path string, mode uint32) (err error)
功能: 改变文件权限。
参数:
path string- 文件路径mode uint32- 权限模式
示例:
package main
import (
"fmt"
"syscall"
)
func main() {
// 设置文件为 0755
if err := syscall.Chmod("/tmp/test.txt", 0755); err != nil {
fmt.Println("错误:", err)
}
}
Chown
func Chown(path string, uid int, gid int) (err error)
功能: 改变文件所有者和组。
参数:
path string- 文件路径uid int- 用户 IDgid int- 组 ID
Close
func Close(fd int) (err error)
功能: 关闭文件描述符。
参数:
fd int- 文件描述符
返回值:
error- 错误
示例:
package main
import (
"fmt"
"syscall"
)
func main() {
fd, err := syscall.Open("/tmp/test.txt", syscall.O_RDONLY, 0)
if err != nil {
fmt.Println("打开失败:", err)
return
}
if err := syscall.Close(fd); err != nil {
fmt.Println("关闭失败:", err)
}
}
D
Dup
func Dup(oldfd int) (fd int, err error)
功能: 复制文件描述符。
参数:
oldfd int- 原文件描述符
返回值:
fd int- 新文件描述符error- 错误
Dup2
func Dup2(oldfd int, newfd int) (err error)
功能: 将文件描述符 oldfd 复制到 newfd。
参数:
oldfd int- 原文件描述符newfd int- 新文件描述符
返回值:
error- 错误
E
Environ
func Environ() []string
功能: 返回环境变量。
返回值:
[]string- 环境变量数组
示例:
package main
import (
"fmt"
"syscall"
)
func main() {
env := syscall.Environ()
for _, e := range env {
fmt.Println(e)
}
}
Exec
func Exec(argv0 string, argv []string, envv []string) (err error)
功能: 执行新程序替换当前进程。
参数:
argv0 string- 可执行文件路径argv []string- 参数列表envv []string- 环境变量
返回值:
error- 错误(如果成功则不返回)
注意:
- 成功时不会返回
- 当前进程被新程序替换
Exit
func Exit(code int)
功能: 以指定退出码终止进程。
参数:
code int- 退出码
注意:
- 不会返回
- 不调用 defer
F
Fchdir
func Fchdir(fd int) (err error)
功能: 通过文件描述符改变目录。
参数:
fd int- 目录的文件描述符
Fchmod
func Fchmod(fd int, mode uint32) (err error)
功能: 通过文件描述符改变文件权限。
Fchown
func Fchown(fd int, uid int, gid int) (err error)
功能: 通过文件描述符改变文件所有者。
ForkExec
func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
功能: fork 并 exec 新进程。
参数:
argv0 string- 可执行文件argv []string- 参数attr *ProcAttr- 进程属性
返回值:
pid int- 子进程 IDerror- 错误
示例:
package main
import (
"fmt"
"syscall"
)
func main() {
attr := &syscall.ProcAttr{
Files: []uintptr{0, 1, 2},
}
pid, err := syscall.ForkExec("/bin/ls", []string{"ls", "-l"}, attr)
if err != nil {
fmt.Println("错误:", err)
return
}
fmt.Println("子进程 PID:", pid)
}
Fstat
func Fstat(fd int, stat *Stat_t) (err error)
功能: 通过文件描述符获取文件状态。
参数:
fd int- 文件描述符stat *Stat_t- 状态结构
返回值:
error- 错误
Fsync
func Fsync(fd int) (err error)
功能: 同步文件到磁盘。
Ftruncate
func Ftruncate(fd int, length int64) (err error)
功能: 截断文件到指定长度。
G
Getcwd
func Getcwd(buf []byte) (n int, err error)
功能: 获取当前工作目录。
参数:
buf []byte- 缓冲区
返回值:
n int- 读取的字节数error- 错误
Getegid
func Getegid() (egid int)
功能: 获取有效组 ID。
Getenv
func Getenv(key string) (value string, found bool)
功能: 获取环境变量。
参数:
key string- 变量名
返回值:
value string- 变量值found bool- 是否存在
示例:
package main
import (
"fmt"
"syscall"
)
func main() {
if val, found := syscall.Getenv("HOME"); found {
fmt.Println("HOME:", val)
} else {
fmt.Println("HOME 未设置")
}
}
Geteuid
func Geteuid() (euid int)
功能: 获取有效用户 ID。
Getgid
func Getgid() (gid int)
功能: 获取组 ID。
Getgroups
func Getgroups() (gids []int, err error)
功能: 获取附属组 ID 列表。
Getpagesize
func Getpagesize() int
功能: 获取系统页面大小。
Getpgid
func Getpgid(pid int) (pgid int, err error)
功能: 获取进程组 ID。
Getpid
func Getpid() (pid int)
功能: 获取当前进程 ID。
Getppid
func Getppid() (ppid int)
功能: 获取父进程 ID。
Getpriority
func Getpriority(which int, who int) (prio int, err error)
功能: 获取进程优先级。
Getrlimit
func Getrlimit(resource int, rlim *Rlimit) (err error)
功能: 获取资源限制。
参数:
resource int- 资源类型(RLIMIT_CPU、RLIMIT_FSIZE 等)rlim *Rlimit- 限制结构
Getrusage
func Getrusage(who int, rusage *Rusage) (err error)
功能: 获取资源使用情况。
参数:
who int- 目标(RUSAGE_SELF、RUSAGE_CHILDREN)rusage *Rusage- 使用情况结构
Getsid
func Getsid(pid int) (sid int, err error)
功能: 获取进程会话 ID。
Gettid
func Gettid() (tid int)
功能: 获取线程 ID。
Gettimeofday
func Gettimeofday(tv *Timeval) (err error)
功能: 获取当前时间。
Getuid
func Getuid() (uid int)
功能: 获取用户 ID。
Getwd
func Getwd() (wd string, err error)
功能: 获取当前工作目录。
返回值:
wd string- 工作目录路径error- 错误
示例:
package main
import (
"fmt"
"syscall"
)
func main() {
wd, err := syscall.Getwd()
if err != nil {
fmt.Println("错误:", err)
return
}
fmt.Println("当前目录:", wd)
}
K
Kill
func Kill(pid int, signum Signal) (err error)
功能: 发送信号到进程。
参数:
pid int- 进程 IDsignum Signal- 信号
返回值:
error- 错误
示例:
package main
import (
"fmt"
"syscall"
)
func main() {
// 发送 SIGTERM
if err := syscall.Kill(1234, syscall.SIGTERM); err != nil {
fmt.Println("错误:", err)
}
}
L
Link
func Link(path string, link string) (err error)
功能: 创建硬链接。
Listen
func Listen(fd int, backlog int) (err error)
功能: 监听 socket 连接。
M
Mkdir
func Mkdir(path string, mode uint32) (err error)
功能: 创建目录。
Mmap
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error)
功能: 内存映射文件。
Munmap
func Munmap(b []byte) (err error)
功能: 取消内存映射。
N
Nanosleep
func Nanosleep(time *Timespec, leftover *Timespec) (err error)
功能: 高精度睡眠。
O
Open
func Open(path string, mode int, perm uint32) (fd int, err error)
功能: 打开文件。
参数:
path string- 文件路径mode int- 打开模式(O_RDONLY、O_WRONLY、O_RDWR 等)perm uint32- 权限
返回值:
fd int- 文件描述符error- 错误
示例:
package main
import (
"fmt"
"syscall"
)
func main() {
fd, err := syscall.Open("/tmp/test.txt", syscall.O_RDONLY, 0)
if err != nil {
fmt.Println("错误:", err)
return
}
defer syscall.Close(fd)
fmt.Println("文件描述符:", fd)
}
P
Pipe
func Pipe(p []int) (err error)
功能: 创建管道。
参数:
p []int- 长度为 2 的数组(p[0] 读端,p[1] 写端)
返回值:
error- 错误
示例:
package main
import (
"fmt"
"syscall"
)
func main() {
var p [2]int
if err := syscall.Pipe(p[:]); err != nil {
fmt.Println("错误:", err)
return
}
fmt.Printf("读端:%d, 写端:%d\n", p[0], p[1])
}
Poll
func Poll(fds []PollFd, timeout int) (n int, err error)
功能: 等待文件描述符上的事件。
R
Read
func Read(fd int, p []byte) (n int, err error)
功能: 从文件描述符读取数据。
参数:
fd int- 文件描述符p []byte- 缓冲区
返回值:
n int- 读取的字节数error- 错误
Readdir
func Readdir(fd int, buf []byte) (n int, err error)
功能: 读取目录条目。
Rename
func Rename(oldpath string, newpath string) (err error)
功能: 重命名文件或目录。
Rmdir
func Rmdir(path string) (err error)
功能: 删除目录。
S
Select
func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
功能: 同步多路复用 I/O。
Setenv
func Setenv(key, value string) error
功能: 设置环境变量。
Setgid
func Setgid(gid int) (err error)
功能: 设置组 ID。
Setpgid
func Setpgid(pid int, pgid int) (err error)
功能: 设置进程组 ID。
Setpriority
func Setpriority(which int, who int, prio int) (err error)
功能: 设置进程优先级。
Setrlimit
func Setrlimit(resource int, rlim *Rlimit) (err error)
功能: 设置资源限制。
Setsid
func Setsid() (pid int, err error)
功能: 创建新会话。
Setuid
func Setuid(uid int) (err error)
功能: 设置用户 ID。
Shutdown
func Shutdown(fd int, how int) (err error)
功能: 关闭 socket 连接。
Socket
func Socket(domain, typ, proto int) (fd int, err error)
功能: 创建 socket。
Socketpair
func Socketpair(domain, typ, proto int) (fd [2]int, err error)
功能: 创建 socket 对。
Stat
func Stat(path string, stat *Stat_t) (err error)
功能: 获取文件状态。
参数:
path string- 文件路径stat *Stat_t- 状态结构
返回值:
error- 错误
示例:
package main
import (
"fmt"
"syscall"
)
func main() {
var stat syscall.Stat_t
if err := syscall.Stat("/etc/passwd", &stat); err != nil {
fmt.Println("错误:", err)
return
}
fmt.Printf("文件大小:%d 字节\n", stat.Size)
fmt.Printf("inode: %d\n", stat.Ino)
fmt.Printf("模式:%o\n", stat.Mode)
}
Statfs
func Statfs(path string, buf *Statfs_t) (err error)
功能: 获取文件系统状态。
Symlink
func Symlink(oldpath string, newpath string) (err error)
功能: 创建符号链接。
T
Truncate
func Truncate(path string, length int64) (err error)
功能: 截断文件。
U
Umask
func Umask(mask int) (oldmask int)
功能: 设置文件创建掩码。
Unlink
func Unlink(path string) (err error)
功能: 删除文件。
Unsetenv
func Unsetenv(key string) error
功能: 删除环境变量。
W
Wait4
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error)
功能: 等待子进程状态改变。
Write
func Write(fd int, p []byte) (n int, err error)
功能: 写入数据到文件描述符。
参数:
fd int- 文件描述符p []byte- 数据
返回值:
n int- 写入的字节数error- 错误
示例:
package main
import (
"fmt"
"syscall"
)
func main() {
fd, err := syscall.Open("/tmp/test.txt", syscall.O_WRONLY|syscall.O_CREAT, 0644)
if err != nil {
fmt.Println("错误:", err)
return
}
defer syscall.Close(fd)
n, err := syscall.Write(fd, []byte("Hello, World!"))
if err != nil {
fmt.Println("写入错误:", err)
return
}
fmt.Println("写入了", n, "字节")
}
典型示例
示例 1:文件操作
package main
import (
"fmt"
"syscall"
)
func main() {
// 打开文件
fd, err := syscall.Open("/tmp/test.txt", syscall.O_RDWR|syscall.O_CREAT, 0644)
if err != nil {
fmt.Println("打开失败:", err)
return
}
defer syscall.Close(fd)
// 写入数据
syscall.Write(fd, []byte("Hello"))
// 获取文件状态
var stat syscall.Stat_t
syscall.Fstat(fd, &stat)
fmt.Printf("文件大小:%d\n", stat.Size)
// 截断文件
syscall.Ftruncate(fd, 0)
}
示例 2:进程管理
package main
import (
"fmt"
"syscall"
)
func main() {
// 获取进程信息
fmt.Println("PID:", syscall.Getpid())
fmt.Println("PPID:", syscall.Getppid())
fmt.Println("UID:", syscall.Getuid())
fmt.Println("GID:", syscall.Getgid())
// 获取资源使用
var rusage syscall.Rusage
syscall.Getrusage(syscall.RUSAGE_SELF, &rusage)
fmt.Printf("最大内存:%d KB\n", rusage.Maxrss)
}
示例 3:环境变量
package main
import (
"fmt"
"syscall"
)
func main() {
// 获取
if val, found := syscall.Getenv("PATH"); found {
fmt.Println("PATH:", val)
}
// 设置
syscall.Setenv("MY_VAR", "value")
// 再次获取
fmt.Println(syscall.Getenv("MY_VAR"))
// 删除
syscall.Unsetenv("MY_VAR")
// 获取所有环境变量
for _, env := range syscall.Environ() {
fmt.Println(env)
}
}
示例 4:管道通信
package main
import (
"fmt"
"syscall"
)
func main() {
var p [2]int
syscall.Pipe(p[:])
// 写数据
syscall.Write(p[1], []byte("Hello"))
// 读数据
buf := make([]byte, 100)
n, _ := syscall.Read(p[0], buf)
fmt.Println(string(buf[:n])) // Hello
// 关闭
syscall.Close(p[0])
syscall.Close(p[1])
}
示例 5:信号处理
package main
import (
"fmt"
"syscall"
)
func main() {
// 获取自身 PID
pid := syscall.Getpid()
fmt.Println("当前 PID:", pid)
// 可以发送信号给自己
// syscall.Kill(pid, syscall.SIGTERM)
}
示例 6:资源限制
package main
import (
"fmt"
"syscall"
)
func main() {
var rlim syscall.Rlimit
// 获取当前限制
syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim)
fmt.Printf("文件描述符限制:Cur=%d, Max=%d\n", rlim.Cur, rlim.Max)
// 设置新限制
rlim.Cur = 1024
rlim.Max = 4096
syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlim)
}
示例 7:内存映射
package main
import (
"fmt"
"syscall"
)
func main() {
// 打开文件
fd, _ := syscall.Open("/tmp/test.bin", syscall.O_RDWR|syscall.O_CREAT, 0644)
defer syscall.Close(fd)
// 设置文件大小
syscall.Ftruncate(fd, 4096)
// 内存映射
data, err := syscall.Mmap(fd, 0, 4096, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED)
if err != nil {
fmt.Println("错误:", err)
return
}
// 使用映射的内存
data[0] = 'H'
data[1] = 'i'
// 取消映射
syscall.Munmap(data)
}
示例 8:目录操作
package main
import (
"fmt"
"syscall"
)
func main() {
// 获取当前目录
wd, _ := syscall.Getwd()
fmt.Println("当前目录:", wd)
// 改变目录
syscall.Chdir("/tmp")
// 创建目录
syscall.Mkdir("/tmp/testdir", 0755)
// 删除目录
syscall.Rmdir("/tmp/testdir")
// 恢复目录
syscall.Chdir(wd)
}
最佳实践
1. 优先使用高级包
// ✅ 推荐:使用 os 包
file, _ := os.Open("/tmp/test.txt")
defer file.Close()
// ⚠️ 不推荐:直接使用 syscall
fd, _ := syscall.Open("/tmp/test.txt", syscall.O_RDONLY, 0)
defer syscall.Close(fd)
2. 正确关闭文件描述符
// ✅ 推荐
fd, err := syscall.Open(path, mode, perm)
if err != nil {
return err
}
defer syscall.Close(fd)
// ⚠️ 不推荐:忘记关闭
fd, _ := syscall.Open(path, mode, perm)
// 使用 fd...
// 忘记关闭会导致资源泄漏
3. 检查所有错误
// ✅ 推荐
if err := syscall.Chmod(path, mode); err != nil {
// 处理错误
}
// ⚠️ 不推荐:忽略错误
syscall.Chmod(path, mode) // 可能失败
4. 使用 golang.org/x/sys
// ✅ 推荐:使用 x/sys
import "golang.org/x/sys/unix"
unix.Open(...)
// ⚠️ 不推荐:syscall 已不推荐
import "syscall"
syscall.Open(...)
与其他包配合
与 os 包配合
package main
import (
"fmt"
"os"
"syscall"
)
func main() {
// os.File 获取 syscall 文件描述符
file, _ := os.Open("/tmp/test.txt")
defer file.Close()
fd := int(file.Fd())
// 使用 syscall 操作
var stat syscall.Stat_t
syscall.Fstat(fd, &stat)
fmt.Println("文件大小:", stat.Size)
}
与 unsafe 包配合
package main
import (
"syscall"
"unsafe"
)
func main() {
// C 风格字符串
ptr, _ := syscall.BytePtrFromString("hello")
// 使用 unsafe 转换
_ = uintptr(unsafe.Pointer(ptr))
}
注意事项
限制
-
平台相关:
- 不同操作系统有不同的系统调用号
- 某些函数只在特定平台可用
-
不推荐使用:
- 大多数 syscall 函数已被更高级的包替代
- 新代码应使用 golang.org/x/sys
-
错误处理:
- 错误类型为 Errno
- 需要手动检查所有错误
-
可移植性:
- 直接使用 syscall 会降低代码可移植性
- 优先使用 os、net 等标准库
使用建议
-
何时使用 syscall:
- 需要访问底层系统功能
- 标准库不提供相应功能
- 性能关键代码
-
何时避免:
- 有标准库替代(os、net、time)
- 需要跨平台支持
- 一般应用代码
快速参考
文件操作
| 函数 | 功能 |
|---|---|
Open | 打开文件 |
Close | 关闭文件 |
Read | 读取文件 |
Write | 写入文件 |
Stat | 获取文件状态 |
Chmod | 改变权限 |
Chown | 改变所有者 |
Link | 创建硬链接 |
Symlink | 创建符号链接 |
Unlink | 删除文件 |
进程管理
| 函数 | 功能 |
|---|---|
Getpid | 获取进程 ID |
Getppid | 获取父进程 ID |
Getuid | 获取用户 ID |
Getgid | 获取组 ID |
ForkExec | fork 并 exec |
Exec | 执行新程序 |
Exit | 退出进程 |
Wait4 | 等待子进程 |
Kill | 发送信号 |
环境变量
| 函数 | 功能 |
|---|---|
Getenv | 获取环境变量 |
Setenv | 设置环境变量 |
Unsetenv | 删除环境变量 |
Environ | 获取所有环境变量 |
Clearenv | 清空环境变量 |
网络
| 函数 | 功能 |
|---|---|
Socket | 创建 socket |
Bind | 绑定地址 |
Listen | 监听 |
Accept | 接受连接 |
Connect | 连接 |
Sendto | 发送数据 |
Recvfrom | 接收数据 |
Shutdown | 关闭连接 |
常见错误
| 错误 | 含义 |
|---|---|
ENOENT | 文件或目录不存在 |
EACCES | 权限不足 |
EEXIST | 文件已存在 |
EINVAL | 参数无效 |
ENOMEM | 内存不足 |
EBUSY | 资源忙 |
EINTR | 系统调用被中断 |
总结
syscall 包提供了对底层操作系统原语的接口。
核心优势:
- ✅ 直接访问系统调用
- ✅ 完整的系统功能支持
- ✅ 高性能(无额外抽象)
重要限制:
- ⚠️ 平台相关,可移植性差
- ⚠️ 不推荐使用,优先使用 golang.org/x/sys
- ⚠️ 需要手动管理资源
- ⚠️ 错误处理复杂
主要用途:
- 文件操作(Open、Read、Write、Stat)
- 进程管理(ForkExec、Exec、Wait4)
- 网络编程(Socket、Bind、Listen)
- 系统信息(Getpid、Getuid、Getrusage)
- 资源管理(Getrlimit、Setrlimit)
使用建议:
- 优先使用 os、net、time 等高级包
- 新代码使用 golang.org/x/sys
- 始终检查错误
- 正确关闭文件描述符
- 注意平台差异
现代替代方案:
- golang.org/x/sys/unix(Unix 系统)
- golang.org/x/sys/windows(Windows 系统)
- os、net、time 等标准库包