Let's start Scheme

2015-07-02

プロセス間通信とセマフォ

書こうと決めてから1週間近くたってしまった。時間とは取れないものである。

Sagittariusにプロセス間通信用の共有メモリとその排他制御用のセマフォを入れた話。

プロセス間通信なんてソケットでもファイルでも何でもいいんだけど、もう少し軽量なものがあるといいかと思い共有メモリを入れた。っで、一つの資源に対して二つ以上の場所からアクセスがあると排他制御がいるということで、プロセス間で使えるセマフォを入れた。とりあえずこんな感じで使える。
;; process A
(import (rnrs)
        (sagittarius process)
        (sagittarius threads))

;; create a semaphore with initial counter 0
(define sem (make-semaphore "/waiter" 0))

;; opens shared memory. if this is the first process then it'll be created
;; with the size 256.
(define shm (open-shared-memory "/shared-memory" 256 (file-options no-fail)))

;; wait for the other process
(semaphore-wait! sem)

;; something was delivered
(let ((bv (shared-memory->bytevector shm)))
  (print (utf8->string bv 0 5)))

;; close and release
(close-shared-memory shm)
(semaphore-close! sem)
(semaphore-destroy! sem)

;; process B
(import (rnrs)
        (sagittarius process)
        (sagittarius threads))

;; open the semaphore created by the other process
(define sem (open-semaphore "/waiter"))

;; this must specify no-truncate option otherwise it may fail
(define shm (open-shared-memory "/shared-memory" 256 (file-options no-truncate)))

(let ((bv (shared-memory->bytevector shm)))
  ;; put some value
  (bytevector-copy! (string->utf8 "hello") 0 bv 0 5))

;; notify the other process
(semaphore-post! sem)
プロセスAは入力待ちプロセス。プロセスBは共有メモリ/shared-memoryに何か書き込んでセマフォのカウンタを一つ増やす。

正直共有メモリだとシェルから使いにくいのであんまり嬉しくないのが悲しいところ。本当は名前付きパイプも入れたいのだが、POSIXとWindowsでモデルが大分違うので上手いAPIを思いつかないでいる。(作成を考えなければどちらのモデルでも名前付きパイプは単なるファイルと変わらないので扱えなくはないのだが、せっかくなので何かほしいという話。)

なんでこんなのが入ったかといえば、最近仕事で使うツールを自前サーバに載せているのだが、サーバの再起動をリモートREPLからできると楽かなぁと思ったからというのがある。正直どちらもあまり上手く使われていないので今のところそこまでの恩恵がないという話もある・・・

No comments:

Post a Comment