Goならわかるシステムプログラミング:第5章 システムコール

01 Mar 2022, 23:39 By mosuke5

こんにちは、もーすけです。
「Goならわかるシステムプログラミング」を読み進めています。とてもいい本です。 読み進めながら実験していることを書いていきます。同じ本を読んでいる人の参考(寄り道?)になればと思います。 今回は「システムコール」です。


Goならわかるシステムプログラミングの学習シリーズ

問題への挑戦

本章は、問題に挑戦した結果だけまとめます。

Q5.1 システムコールの確認

システムコールの確認は、すでに第2章 io.Writer でもネットワーク通信関連で行っているので確認してみてください。

せっかくなので他のネタでシステムコールを確認してみます。
Q2.2で実践したcsvデータのファイルへの書き込みでシステムコールをトレースしてみます。

package main

import (
	"encoding/csv"
	"os"
)

func main() {
	file, err := os.Create("tmp.txt")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	w := csv.NewWriter(file)
	w.Write([]string{"foo", "bar", "hoge"})
	w.Write([]string{"kuu", "kaa", "joe"})
	w.Flush()
}

環境は、RHEL8.5です。

$ uname -a
Linux mosuke5-station 4.18.0-348.7.1.el8_5.x86_64 #1 SMP Wed Dec 8 21:51:17 EST 2021 x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/redhat-release
Red Hat Enterprise Linux release 8.5 (Ootpa)

Goのプログラムのビルドはトレースする必要がないので事前にビルドしておきます。 straceには -y, -f, -e openat,read,write,clone,close, -o output のオプションを付けていますが、それぞれ簡単に説明しておきます。

  • -y は、ファイルディスクリプタに関連のあるパスを表示します。どのファイルに対しての操作かわかりやすくなります。
  • -f は、フォークされたプロセスもトレースします。
  • -e は、表示するシステムコールを絞り込みます。これは、全システムコールだと表示がながくなりわかりづらくなるので、説明用に絞っているだけです。
  • -o は、ファイルに結果をアウトプットしています。
$ go build main.go
$ ls -l main
-rwxrwxr-x. 1 mosuke5 mosuke5 1789722  4月 14 20:17 main

$ strace -y -f -e openat,read,write,clone,close -o output ./main
$ cat output
1127332 openat(AT_FDCWD, "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size", O_RDONLY) = 3</sys/kernel/mm/transparent_hugepage/hpage_pmd_size>
1127332 read(3</sys/kernel/mm/transparent_hugepage/hpage_pmd_size>, "2097152\n", 20) = 8
1127332 close(3</sys/kernel/mm/transparent_hugepage/hpage_pmd_size>) = 0
1127332 clone(child_stack=0xc000096000, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS, tls=0xc00007c090) = 1127333
1127332 clone(child_stack=0xc000098000, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS, tls=0xc00007c490) = 1127334
1127332 clone(child_stack=0xc000092000, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS, tls=0xc00007c890) = 1127335
1127334 clone(child_stack=0xc000112000, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS, tls=0xc000100090) = 1127336
1127332 openat(AT_FDCWD, "tmp.txt", O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 3</home/mosuke5/work/tmp/tmp.txt>
1127332 write(3</home/mosuke5/work/tmp/tmp.txt>, "foo,bar,hoge\nkuu,kaa,joe\n", 25) = 25
1127332 close(3</home/mosuke5/work/tmp/tmp.txt>) = 0
1127332 exit_group(0)                   = ?
1127336 +++ exited with 0 +++
1127335 +++ exited with 0 +++
1127334 +++ exited with 0 +++
1127333 +++ exited with 0 +++
1127332 +++ exited with 0 +++

いくつかの気になったポイントを紹介します。

  • straceの結果で一番左に記載の番号は、実行したプロセスのPIDになります。
  • clone で、スレッドを作っています。今回はあまり活躍の場はなさそうですが、いくつかスレッドを起動して処理してます
  • openat で、書き込み用のtmp.txtをオープンしています
  • write で、書き込みを行っています。コード上では、2回に分けてCSVレコードを記述していますが、どうやらLinux上では一度に書き込みを行うようですね。
  • close で、対象のファイルをしっかりクローズしています。
  • 最後に exit_group で、すべてのスレッドを終了しています。

システムコールについては、こちらの本「Linuxシステムコール基本リファレンス」をよく参考にしていますので、一緒に学ぶとよいです。

記事の内容に関連した相談、仕事依頼したい New

記事の内容やクラウドネイティブ技術に関する相談、仕事依頼を開始しました。
仕事依頼、相談をしてみる

記事へのフィードバック

本記事に対して、フィードバックあればこちらのフォームからご記入ください。
記事の内容にフィードバックしてみる

このエントリーをはてなブックマークに追加