関連記事
Goメモ-447 (mkfifoメモ)(1)(create) - いろいろ備忘録日記
Goメモ-448 (mkfifoメモ)(2)(read) - いろいろ備忘録日記
GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ
概要
以下、自分用のメモです。忘れないうちにメモメモ。。。
Go側から名前付きパイプ(mkfifo)を扱うことがあったので、忘れない内にメモしておこうと思いました。
今回は名前付きパイプファイルからの書き込みについて。
なお、標準ライブラリにある syscall
パッケージの Mkfifo()
でも行えるのですが
サンプルでは sys/unix の方を使っています。
サンプル
//go:build linux package main import ( "bufio" "flag" "log" "os" "time" ) var ( fname string ) func init() { log.SetFlags(log.Lmicroseconds) flag.StringVar(&fname, "fname", "", "FIFO file name") flag.Parse() } func main() { if err := run(); err != nil { log.Fatal(err) } } func run() error { // // 名前付きパイプを開く // os.OpenFile() にて、モード指定で os.ModeNamedPipe を指定する // os.O_WRONLYで開くと書込み専用となるが、この場合読み込みが発生するまで // ブロックされる。これはUNIXの名前付きパイプの挙動に従った動作である。 // var ( f *os.File err error ) log.Println("[Before] os.OpenFile(os.O_WRONLY)") // 対象となる名前付きパイプに読み込みが発生していない場合、ここでブロックされる。 f, err = os.OpenFile(fname, os.O_WRONLY, os.ModeNamedPipe) if err != nil { return err } defer f.Close() log.Println("[After ] os.OpenFile(os.O_WRONLY)") // // データを書込み // type ( data struct { numWrites int err error } ) var ( writer = bufio.NewWriter(f) results = make(chan data) timeout = time.Second ) go func() { n, err := writer.WriteString("helloworld\n") if err == nil { err = writer.Flush() } results <- data{n, err} }() select { case r := <-results: if r.err != nil { return r.err } log.Printf("Write %d byte(s)", r.numWrites) case <-time.After(timeout): // 上記で記載した通り、os.O_WRONLYのみで開いている場合 // ブロッキングモードとなっているため、os.OpenFile()の呼び出しの // 時点でブロックされることとなる。つまり、実際にデータを書き出す // タイミングでは待たされることが無いため、このタイムアウトは通らない。 log.Println("timeout") } return nil }
実行すると以下のようになります。
$ task task: [build] go build -o app . task: [create-fifo] rm -f ./tmp-fifo task: [create-fifo] mkfifo ./tmp-fifo -m0666 task: [run] ./app -fname ./tmp-fifo & task: [run] (sleep 2; cat ./tmp-fifo) 05:20:10.335269 [Before] os.OpenFile(os.O_WRONLY) 05:20:12.337542 [After ] os.OpenFile(os.O_WRONLY) 05:20:12.337643 Write 11 byte(s) helloworld
わざと読み込みを2秒ずらしてから行うようにしているので、os.OpenFile()
の戻りが2秒後になっていますね。
参考情報
6.3 Named Pipes (FIFOs - First In First Out)
Ubuntu Manpage: mkfifo, mkfifoat - FIFOスペシャルファイル(名前付きパイプ)を作成する
Master the Linux ‘mkfifo’ Command: A Comprehensive Guide | by Peter Hou | Medium
Goのおすすめ書籍
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。