Skip to content

Add example/syscall/syscall6 #925

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/syscall/syscall6/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
app
16 changes: 16 additions & 0 deletions examples/syscall/syscall6/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# これは何?

[unix](https://pkg.go.dev/golang.org/x/sys/unix) パッケージの

- Syscall6()

を使っているサンプルです。

```sh
$ task
task: [default] rm -f ./app
task: [default] go build -o app .
task: [default] ./app
# Kubernetes-managed hosts file.
127.0.0.1 localho
```
10 changes: 10 additions & 0 deletions examples/syscall/syscall6/Taskfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# https://taskfile.dev

version: '3'

tasks:
default:
cmds:
- rm -f ./app
- go build -o app .
- ./app
96 changes: 96 additions & 0 deletions examples/syscall/syscall6/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package main

import (
"log"
"unsafe"

"golang.org/x/sys/unix"
)

func main() {
log.SetFlags(0)

if err := run(); err != nil {
log.Fatal(err)
}
}

func run() error {
//
// unix.Syscall6()を使って mmap(2) を呼び出し
//

// ファイルディスクリプタを取得
var (
fileName = "/etc/hosts"
fd int
err error
)
fd, err = unix.Open(fileName, unix.O_RDONLY, 0)
if err != nil {
return err
}
defer unix.Close(fd)

// ファイルサイズを取得
var (
stat unix.Stat_t
fsize int64
)
err = unix.Fstat(fd, &stat)
if err != nil {
return err
}

fsize = stat.Size

// mmap(2)を利用してメモリにマッピング
// 引数については man 2 mmap で調べられる
//
// そもそも、unixパッケージには
// - unix.Mmap()
// - unix.Munmap()
// が存在するので、それを利用するのが普通です。
//
// 本サンプルは、unix.Syscall6()を試す為の実装です。
var (
trap = uintptr(unix.SYS_MMAP)
addr = uintptr(0) // アドレスヒント(0は自動割当)
length = uintptr(fsize) // ファイルサイズ
prot = uintptr(unix.PROT_READ) // 読み取り専用
flags = uintptr(unix.MAP_SHARED) // マッピングフラグ(共有)
fdptr = uintptr(fd) // ファイルディスクリプタ
offset = uintptr(0) // オフセット
errno unix.Errno

unmap = func(addr uintptr) {
unix.Syscall(unix.SYS_MUNMAP, addr, length, uintptr(0))
}
)
addr, _, errno = unix.Syscall6(trap, addr, length, prot, flags, fdptr, offset)
if errno != 0 {
err = errno
return err
}
defer unmap(addr)

// 先頭 Nバイト 分を見る
const (
dispSize = 50
)
var (
// VSCodeなどで作業していると「possible misuse of unsafe.Pointer」という警告が出るが
// mmapの戻り値はメモリアドレスを表すuintptr値なので、以下のunsafe.Pointerへの変換は安全です。
ptr = (*byte)(unsafe.Pointer(addr))
data = unsafe.Slice(ptr, int(fsize))
)
if fsize >= dispSize {
log.Println(string(data[:dispSize]))
} else {
log.Println(string(data))
}



return nil
}
Loading