返回顶部
首页 > 资讯 > 后端开发 > GO >Golang标准库syscall详解(什么是系统调用)
  • 396
分享到

Golang标准库syscall详解(什么是系统调用)

2024-04-02 19:04:59 396人浏览 泡泡鱼
摘要

目录一、什么是系统调用二、golang标准库-syscall1. syscall无处不在2. syscall demo举例:Go版本的strace三、参考一、什么是系统调用 In c

一、什么是系统调用

In computing, a system call is the programmatic way in which a computer program requests a service from the kernel of the operating system it is executed on. This may include hardware-related services (for example, accessing a hard disk drive), creation and execution of new processes, and communication with integral kernel services such as process scheduling. System calls provide an essential interface between a process and the operating system.

系统调用是程序向操作系统内核请求服务的过程,通常包含硬件相关的服务(例如访问硬盘),创建新进程等。系统调用提供了一个进程和操作系统之间的接口。

二、Golang标准库-syscall

syscall包包含一个指向底层操作系统原语的接口。

注意:该软件包已被定。标准以外的代码应该被迁移到golang.org/x/sys存储库中使用相应的软件包。这也是应用新系统或版本所需更新的地方。 Signal , Errno 和 SysProcAttr 在 golang.org/x/sys 中尚不可用,并且仍然必须从 syscall 程序包中引用。有关更多信息,请参见 https://golang.org/s/go1.4-syscall。

Https://pkg.go.dev/golang.org/x/sys
该存储库包含用于与操作系统进行低级交互的补充Go软件包。

1. syscall无处不在

举个最常用的例子, fmt.Println(“hello world”), 这里就用到了系统调用 write, 我们翻一下源码


func Println(a ...interface{}) (n int, err error) {
	return Fprintln(os.Stdout, a...)
}

Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
 
func (f *File) write(b []byte) (n int, err error) {
    if len(b) == 0 {
        return 0, nil
    }
    // 实际的write方法,就是调用syscall.Write()
    return fixCount(syscall.Write(f.fd, b))
}

2. syscall demo举例:

 go版本的strace Strace

strace 是用于查看进程系统调用的工具, 一般使用方法如下:

strace -c 用于统计各个系统调用的次数


[root@localhost ~]# strace -c echo hello
hello
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           0         1           read
  0.00    0.000000           0         1           write
  0.00    0.000000           0         3           open
  0.00    0.000000           0         5           close
  0.00    0.000000           0         4           fstat
  0.00    0.000000           0         9           mmap
  0.00    0.000000           0         4           mprotect
  0.00    0.000000           0         2           munmap
  0.00    0.000000           0         4           brk
  0.00    0.000000           0         1         1 access
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         1           arch_prctl
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000                    36         1 total
[root@localhost ~]#

stace 的实现原理是系统调用 ptrace, 我们来看下 ptrace 是什么。

man page 描述如下:

The ptrace() system call provides a means by which one process (the “tracer”) may observe and control the execution of another process (the “tracee”), and examine and change the tracee's memory and reGISters. It is primarily used to implement breakpoint debuggingand system call tracing.

简单来说有三大能力:

追踪系统调用
读写内存和寄存器
向被追踪程序传递信号

ptrace接口:


int ptrace(int request, pid_t pid, caddr_t addr, int data);
 
request包含:
PTRACE_ATTACH
PTRACE_SYSCALL
PTRACE_PEEKTEXT, PTRACE_PEEKDATA
等

tracer 使用 PTRACE_ATTACH 命令,指定需要追踪的PID。紧接着调用 PTRACE_SYSCALL。
tracee 会一直运行,直到遇到系统调用,内核会停止执行。 此时,tracer 会收到 SIGTRAP 信号,tracer 就可以打印内存和寄存器中的信息了。

接着,tracer 继续调用 PTRACE_SYSCALL, tracee 继续执行,直到 tracee退出当前的系统调用。
需要注意的是,这里在进入syscall和退出syscall时,tracer都会察觉。

go版本的strace

了解以上内容后,presenter 现场实现了一个go版本的strace, 需要在 linux amd64 环境编译。
https://GitHub.com/silentred/gosys

// strace.go


package main
 
import (
    "fmt"
    "os"
    "os/exec"
    "syscall"
)
 
func main() {
    var err error
    var regs syscall.PtraceRegs
    var ss syscallCounter
    ss = ss.init()
 
    fmt.Println("Run: ", os.Args[1:])
 
    cmd := exec.Command(os.Args[1], os.Args[2:]...)
    cmd.Stderr = os.Stderr
    cmd.Stdout = os.Stdout
    cmd.Stdin = os.Stdin
    cmd.SysProcAttr = &syscall.SysProcAttr{
        Ptrace: true,
    }
 
    cmd.Start()
    err = cmd.Wait()
    if err != nil {
        fmt.Printf("Wait err %v \n", err)
    }
 
    pid := cmd.Process.Pid
    exit := true
 
    for {
        // 记得 PTRACE_SYSCALL 会在进入和退出syscall时使 tracee 暂停,所以这里用一个变量控制,RAX的内容只打印一遍
        if exit {
            err = syscall.PtraceGetRegs(pid, &regs)
            if err != nil {
                break
            }
            //fmt.Printf("%#v \n",regs)
            name := ss.getName(regs.Orig_rax)
            fmt.Printf("name: %s, id: %d \n", name, regs.Orig_rax)
            ss.inc(regs.Orig_rax)
        }
        // 上面Ptrace有提到的一个request命令
        err = syscall.PtraceSyscall(pid, 0)
        if err != nil {
            panic(err)
        }
        // 猜测是等待进程进入下一个stop,这里如果不等待,那么会打印大量重复的调用函数名
        _, err = syscall.Wait4(pid, nil, 0, nil)
        if err != nil {
            panic(err)
        }
 
        exit = !exit
    }
 
    ss.print()
}

// 用于统计信息的counter, syscallcounter.go


package main
 
import (
    "fmt"
    "os"
    "text/tabwriter"
 
    "github.com/seccomp/libseccomp-golang"
)
 
type syscallCounter []int
 
const maxSyscalls = 303
 
func (s syscallCounter) init() syscallCounter {
    s = make(syscallCounter, maxSyscalls)
    return s
}
 
func (s syscallCounter) inc(syscallID uint64) error {
    if syscallID > maxSyscalls {
        return fmt.Errorf("invalid syscall ID (%x)", syscallID)
    }
 
    s[syscallID]++
    return nil
}
 
func (s syscallCounter) print() {
    w := tabwriter.NewWriter(os.Stdout, 0, 0, 8, ' ', tabwriter.AlignRight|tabwriter.Debug)
    for k, v := range s {
        if v > 0 {
            name, _ := seccomp.ScmpSyscall(k).GetName()
            fmt.Fprintf(w, "%d\t%s\n", v, name)
        }
    }
    w.Flush()
}
 
func (s syscallCounter) getName(syscallID uint64) string {
    name, _ := seccomp.ScmpSyscall(syscallID).GetName()
    return name
}

最后结果:

Run:  [echo hello]
Wait err stop signal: trace/breakpoint trap
name: execve, id: 59
name: brk, id: 12
name: access, id: 21
name: mmap, id: 9
name: access, id: 21
name: open, id: 2
name: fstat, id: 5
name: mmap, id: 9
name: close, id: 3
name: access, id: 21
name: open, id: 2
name: read, id: 0
name: fstat, id: 5
name: mmap, id: 9
name: mprotect, id: 10
name: mmap, id: 9
name: mmap, id: 9
name: close, id: 3
name: mmap, id: 9
name: arch_prctl, id: 158
name: mprotect, id: 10
name: mprotect, id: 10
name: mprotect, id: 10
name: munmap, id: 11
name: brk, id: 12
name: brk, id: 12
name: open, id: 2
name: fstat, id: 5
name: mmap, id: 9
name: close, id: 3
name: fstat, id: 5
hello
name: write, id: 1
name: close, id: 3
name: close, id: 3
        1|read
        1|write
        3|open
        5|close
        4|fstat
        7|mmap
        4|mprotect
        1|munmap
        3|brk
        3|access
        1|execve
        1|arch_prctl

三、参考

Golang标准库——syscall
参考URL: https://www.jianshu.com/p/44109d5e045b
Golang 与系统调用
参考URL: https://blog.csdn.net/weixin_33744141/article/details/89033990

以上就是Golang标准库syscall详解(什么是系统调用)的详细内容,更多关于Golang标准库syscall的资料请关注编程网其它相关文章!

您可能感兴趣的文档:

--结束END--

本文标题: Golang标准库syscall详解(什么是系统调用)

本文链接: https://lsjlt.com/news/126763.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Golang标准库syscall详解(什么是系统调用)
    目录一、什么是系统调用二、Golang标准库-syscall1. syscall无处不在2. syscall demo举例:go版本的strace三、参考一、什么是系统调用 In c...
    99+
    2024-04-02
  • golang标准库template的代码生成方法是什么
    本篇内容主要讲解“golang标准库template的代码生成方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“golang标准库template的代码生成方法是什么”吧!curd-gen...
    99+
    2023-06-25
  • win7系统标准用户无法登录的解决办法是什么
    这篇文章将为大家详细讲解有关win7系统标准用户无法登录的解决办法是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。在win7系统中,普通的标准用户都是管理员用户衍生出来的账户。有的用户用...
    99+
    2023-06-28
  • 美国服务器系统标准特征与性能是什么
    美国服务器系统的标准特征和性能取决于具体的服务器类型和用途,但一般来说,美国服务器系统的特征和性能可能包括以下内容: 多核处理器...
    99+
    2024-04-09
    美国服务器 服务器
  • C++11标准库bind函数应用方法是什么
    这篇文章主要讲解了“C++11标准库bind函数应用方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++11标准库bind函数应用方法是什么”吧!bind 是什么?bind 顾名思...
    99+
    2023-06-22
  • linux中系统调用的概念是什么
    这篇文章主要讲解了“linux中系统调用的概念是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“linux中系统调用的概念是什么”吧!在linux中,系统调用是指操作系统提供给用户程序调用...
    99+
    2023-06-29
  • android 调用系统的照相机和图库实例详解
    android手机有自带的照相机和图库,我们做的项目中有时用到上传图片到服务器,今天做了一个项目用到这个功能,所以把我的代码记录下来和大家分享,第一次写博客希望各位大神多多批评...
    99+
    2022-06-06
    调用 系统 相机 Android
  • 详解Golang中什么是GOPATH?如何使用?
    在Golang开发中,GOPATH是非常重要的一个环境变量,它用于指定Golang编译器的工作区间。在编写代码时,我们的代码必须在GOPATH下才能被编译和运行。本文将详细介绍如何设置和配置GOPATH,以及如何在日常开发中充分利用GOPA...
    99+
    2023-05-14
    GOPATH Golang go语言
  • Go调度器学习之系统调用的方法是什么
    本篇内容主要讲解“Go调度器学习之系统调用的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Go调度器学习之系统调用的方法是什么”吧!1. 系统调用下面,我们将以一个简单的文件打开的系统...
    99+
    2023-07-05
  • 数据库应用系统指的是什么
    数据库应用系统指的是什么?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧!数据库应用系统有由数据库系统、应用程序系统、用户组成...
    99+
    2024-04-02
  • SqlServer系统数据库的作用是什么
    这篇文章将为大家详细讲解有关SqlServer系统数据库的作用是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。Master Master数据库保存有放在...
    99+
    2024-04-02
  • 常用的数据库管理系统是什么
    这篇文章主要介绍了常用的数据库管理系统是什么,具有一定借鉴价值,需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获。下面让小编带着大家一起了解一下。常见的数据库系统有IBM的DB2、甲骨文的Oracle...
    99+
    2024-04-02
  • 数据库审计系统的作用是什么
    数据库审计系统的作用是对数据库中的操作进行监控、记录和分析,以确保数据库的安全性和完整性。它可以追踪数据库中每个用户的操作,包括登录...
    99+
    2023-06-08
    数据库审计 数据库
  • linux调用系统内核函数的方法是什么
    在Linux中,调用系统内核函数的方法主要有以下几种:1. 使用系统调用(system call):系统调用是用户程序通过软中断(软...
    99+
    2023-10-18
    linux
  • 正在使用的系统是什么版本如何查看win7系统详情
    很多朋友的win7系统可能都是购买都不知道现在使用过的系统是什么版本,想要知道自家电脑win7系统的详细信息吗下面我们就来看看如何操作吧! 注:以下命令都需要在开启系统“运行窗口”后使用。 1、s...
    99+
    2023-06-05
    win7 版本 系统 详情
  • Windows7系统开机鼠标动不了是什么原因如何解决
      Win7开机鼠标突然不能动了,如果使用无线鼠标的还可能是电池没电了,但有用户用的是有线,且鼠标能在其他电脑使用,那么是什么原因导致的呢?下面小编从原因入手,给大家介绍下Win7系统鼠标不能动的解决方法。   原因分析...
    99+
    2023-06-17
    Win7 开机 鼠标动不了 Windows7 原因 系统 鼠标
  • golang pprof监控系列go trace统计原理与使用方法是什么
    这篇文章主要介绍“golang pprof监控系列go trace统计原理与使用方法是什么”,在日常操作中,相信很多人在golang pprof监控系列go trace统计原理与使用方法是什么问题上存...
    99+
    2023-07-05
  • 进销存系统对库存管理的主要作用是什么?
    库存过多,造成产品的积压,这似乎不是什么新鲜事,但是,年年积压,后面还是年年有人压,那么,库存的管理真的有那么难吗?其实,库存的管理没有那么难,而这不难,就全靠进销存系统的帮助,而这其中的关键点,我们一起来看一下。1、出入库管理货物的入库和...
    99+
    2023-06-05
  • 解析win10系统中的perfmon.exe是什么进程 是否能禁用
    很多人在使用电脑时可能没有注意到perfmon.exe进程的存在。那么perfmon.exe是什么进程呢,是否能禁用呢?下面小编就给大家介绍下perfmon.exe进程是什么以及是否能禁用。1、perfmon.exe进程其实就是window...
    99+
    2023-07-12
  • Linux系统进程占用端口的具体解决方案是什么
    Linux系统进程占用端口的具体解决方案是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Linux系统如何查看端口被哪个进程占用?\1. lsof -i:端...
    99+
    2023-06-28
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作