欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang標(biāo)準(zhǔn)庫(kù)syscall詳解(什么是系統(tǒng)調(diào)用)

 更新時(shí)間:2021年05月25日 10:48:04   作者:西京刀客  
最近在研究go語(yǔ)言,發(fā)現(xiàn)go語(yǔ)言系統(tǒng)調(diào)用源碼只有調(diào)用函數(shù)的定義,今天通過(guò)本文給大家分享Golang標(biāo)準(zhǔn)庫(kù)syscall詳解及什么是系統(tǒng)調(diào)用,感興趣的朋友一起看看吧

一、什么是系統(tǒng)調(diào)用

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.

系統(tǒng)調(diào)用是程序向操作系統(tǒng)內(nèi)核請(qǐng)求服務(wù)的過(guò)程,通常包含硬件相關(guān)的服務(wù)(例如訪問(wèn)硬盤(pán)),創(chuàng)建新進(jìn)程等。系統(tǒng)調(diào)用提供了一個(gè)進(jìn)程和操作系統(tǒng)之間的接口。

二、Golang標(biāo)準(zhǔn)庫(kù)-syscall

syscall包包含一個(gè)指向底層操作系統(tǒng)原語(yǔ)的接口。

注意:該軟件包已被鎖定。標(biāo)準(zhǔn)以外的代碼應(yīng)該被遷移到golang.org/x/sys存儲(chǔ)庫(kù)中使用相應(yīng)的軟件包。這也是應(yīng)用新系統(tǒng)或版本所需更新的地方。 Signal , Errno 和 SysProcAttr 在 golang.org/x/sys 中尚不可用,并且仍然必須從 syscall 程序包中引用。有關(guān)更多信息,請(qǐng)參見(jiàn) https://golang.org/s/go1.4-syscall。

https://pkg.go.dev/golang.org/x/sys
該存儲(chǔ)庫(kù)包含用于與操作系統(tǒng)進(jìn)行低級(jí)交互的補(bǔ)充Go軟件包。

1. syscall無(wú)處不在

舉個(gè)最常用的例子, fmt.Println(“hello world”), 這里就用到了系統(tǒng)調(diào)用 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
    }
    // 實(shí)際的write方法,就是調(diào)用syscall.Write()
    return fixCount(syscall.Write(f.fd, b))
}

2. syscall demo舉例:

 go版本的strace Strace

strace 是用于查看進(jìn)程系統(tǒng)調(diào)用的工具, 一般使用方法如下:

strace -c 用于統(tǒng)計(jì)各個(gè)系統(tǒng)調(diào)用的次數(shù)

[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 的實(shí)現(xiàn)原理是系統(tǒng)調(diào)用 ptrace, 我們來(lái)看下 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.

簡(jiǎn)單來(lái)說(shuō)有三大能力:

追蹤系統(tǒng)調(diào)用
讀寫(xiě)內(nèi)存和寄存器
向被追蹤程序傳遞信號(hào)

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。緊接著調(diào)用 PTRACE_SYSCALL。
tracee 會(huì)一直運(yùn)行,直到遇到系統(tǒng)調(diào)用,內(nèi)核會(huì)停止執(zhí)行。 此時(shí),tracer 會(huì)收到 SIGTRAP 信號(hào),tracer 就可以打印內(nèi)存和寄存器中的信息了。

接著,tracer 繼續(xù)調(diào)用 PTRACE_SYSCALL, tracee 繼續(xù)執(zhí)行,直到 tracee退出當(dāng)前的系統(tǒng)調(diào)用。
需要注意的是,這里在進(jìn)入syscall和退出syscall時(shí),tracer都會(huì)察覺(jué)。

go版本的strace

了解以上內(nèi)容后,presenter 現(xiàn)場(chǎng)實(shí)現(xiàn)了一個(gè)go版本的strace, 需要在 linux amd64 環(huán)境編譯。
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 會(huì)在進(jìn)入和退出syscall時(shí)使 tracee 暫停,所以這里用一個(gè)變量控制,RAX的內(nèi)容只打印一遍
        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有提到的一個(gè)request命令
        err = syscall.PtraceSyscall(pid, 0)
        if err != nil {
            panic(err)
        }
        // 猜測(cè)是等待進(jìn)程進(jìn)入下一個(gè)stop,這里如果不等待,那么會(huì)打印大量重復(fù)的調(diào)用函數(shù)名
        _, err = syscall.Wait4(pid, nil, 0, nil)
        if err != nil {
            panic(err)
        }
 
        exit = !exit
    }
 
    ss.print()
}

// 用于統(tǒng)計(jì)信息的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
}

最后結(jié)果:

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標(biāo)準(zhǔn)庫(kù)——syscall
參考URL: https://www.jianshu.com/p/44109d5e045b
Golang 與系統(tǒng)調(diào)用
參考URL: https://blog.csdn.net/weixin_33744141/article/details/89033990

以上就是Golang標(biāo)準(zhǔn)庫(kù)syscall詳解(什么是系統(tǒng)調(diào)用)的詳細(xì)內(nèi)容,更多關(guān)于Golang標(biāo)準(zhǔn)庫(kù)syscall的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Golang合并yaml文件過(guò)程逐步講解

    Golang合并yaml文件過(guò)程逐步講解

    之前一直從事java開(kāi)發(fā),習(xí)慣了使用yaml文件的格式,尤其是清晰的層次結(jié)構(gòu)、注釋,下面這篇文章主要給大家介紹了關(guān)于Golang合并yaml文件的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • golang讀取各種配置文件(ini、json、yaml)

    golang讀取各種配置文件(ini、json、yaml)

    日常項(xiàng)目中,讀取各種配置文件是避免不了的,本文主要介紹了golang讀取各種配置文件(ini、json、yaml),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • 詳解go基于viper實(shí)現(xiàn)配置文件熱更新及其源碼分析

    詳解go基于viper實(shí)現(xiàn)配置文件熱更新及其源碼分析

    這篇文章主要介紹了詳解go基于viper實(shí)現(xiàn)配置文件熱更新及其源碼分析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • 利用golang的字符串解決leetcode翻轉(zhuǎn)字符串里的單詞

    利用golang的字符串解決leetcode翻轉(zhuǎn)字符串里的單詞

    這篇文章主要介紹了利用golang的字符串解決leetcode翻轉(zhuǎn)字符串里的單詞,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • Go語(yǔ)言Select chan用法小結(jié)

    Go語(yǔ)言Select chan用法小結(jié)

    select語(yǔ)句是Go語(yǔ)言中用于處理多個(gè)通道操作的關(guān)鍵字,它允許你在多個(gè)通道上進(jìn)行非阻塞的選擇操作,本文就詳細(xì)介紹一下如何使用,感興趣的可以了解一下
    2023-09-09
  • golang interface指針實(shí)現(xiàn)示例

    golang interface指針實(shí)現(xiàn)示例

    本文主要介紹了golang interface指針實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-08-08
  • golang中實(shí)現(xiàn)給gif、png、jpeg圖片添加文字水印

    golang中實(shí)現(xiàn)給gif、png、jpeg圖片添加文字水印

    這篇文章主要介紹了golang中實(shí)現(xiàn)給gif、png、jpeg圖片添加文字水印,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • go中控制goroutine數(shù)量的方法

    go中控制goroutine數(shù)量的方法

    這篇文章主要介紹了go中控制goroutine數(shù)量的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • go高并發(fā)時(shí)append方法偶現(xiàn)錯(cuò)誤解決分析

    go高并發(fā)時(shí)append方法偶現(xiàn)錯(cuò)誤解決分析

    這篇文章主要為大家介紹了go高并發(fā)時(shí)append方法偶現(xiàn)錯(cuò)誤解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • Go中Channel發(fā)送和接收操作指南

    Go中Channel發(fā)送和接收操作指南

    在golang中channel屬于較為核心的一個(gè)功能,尤其在go協(xié)程中,channel功能尤為重要,下面這篇文章主要給大家介紹了關(guān)于Go中Channel發(fā)送和接收操作的相關(guān)資料,需要的朋友可以參考下
    2021-08-08

最新評(píng)論