ykominami
3/5/2015 - 12:07 AM

mrubyのForkをCから使ってプロセス制御

mrubyのForkをCから使ってプロセス制御

pid = Process.fork() {
p "hoge"
sleep 1
}
p "parent"
Process.waitpid pid
#p "bye for now."

def mymethod
  p "Hello, this is mymethod."
  yield
end

mymethod {puts "hogehgo"}
// gcc forktest.c `mruby/bin/mruby-config --cflags --ldflags --libs --ldflags-before-libs`

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "mruby.h"
#include "mruby/proc.h"

static mrb_value myfunc(mrb_state *mrb, mrb_value obj) {

  system("touch /home/ubuntu/workspace/work/hoge2.txt");
  return mrb_nil_value();
}


int main() {
  FILE *f;
  struct RProc *blk;
  mrb_state *mrb;
  mrb_value val,proc;

  mrb = mrb_open();
  f = fopen("fork.rb", "r");
  mrb_load_file(mrb, f);
  fclose(f);
  blk = mrb_proc_new_cfunc(mrb, myfunc);
  proc = mrb_obj_value(blk);
  val = mrb_funcall_with_block(mrb, mrb_top_self(mrb), mrb_intern_cstr(mrb, "mymethod"), 0, NULL, proc);

  val = mrb_funcall_with_block(mrb, mrb_obj_value(mrb_module_get(mrb, "Process")), mrb_intern_cstr(mrb, "fork"), 0, NULL, proc);
  mrb_funcall(mrb,mrb_obj_value(mrb_module_get(mrb, "Process")),"waitpid",1,val);

  system("echo '123'>bar.txt");
  return 0;
}

大前提

conf.gem :github => 'iij/mruby-process'

やりたいことをRubyで書くと

pid = Process.fork() { hogo.run }
Process.waitpid pid

C言語からProcess.forkを呼ぶにあたり必要な事

ブロックを扱う必要がある

以下の方法がある。

  • ブロックをC言語で用意する。
  • ブロックを受け取るメソッドを用意して、これを経由して行う

C言語側でブロックを用意するには

ブロックをC言語では関数として用意する必要がある。

mrb_state*,mrb_valueを受け、mrb_valueを返す型にする。

static mrb_value myfunc(mrb_state *mrb, mrb_value obj) {
  return mrb_nil_value();
}

struct RProc *blk;
mrb_value proc;

blk = mrb_proc_new_cfunc(mrb, myfunc);
proc = mrb_obj_value(blk);

Process.fork() {hoge}

mrb_value val;
val = mrb_funcall_with_block(mrb, mrb_obj_value(mrb_class_get(mrb, "Process")), mrb_intern_cstr(mrb, "fork"), 0, NULL, proc);