LINUXカーネルモジュールを作ってみる。

カーネルモジュールを作ってみる。

Makefile作る

$ echo "obj-m := mymod.o" >Makefile

モジュール作る

$ vi mymod.c

内容

#include
#include
#includestatic int sec=5;
module_param(sec, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(sec,"Set the interval.");

static void mymod_timer(unsigned long data);

static DEFINE_TIMER(timer,mymod_timer,0,0);

static void mymod_timer(unsigned long data)
{
    printk(KERN_INFO "mymod: timer\n");
	mod_timer(&timer,jiffies + sec * HZ);
}

static int mymod_init(void)
{
	printk(KERN_INFO "mymod: init\n");
	if (sec

makeする

$ make -C /lib/modules/`uname -r`/build M=`pwd`

モジュール情報を参照する

$ modinfo mymod.ko
filename:       mymod.ko
description:    My module
license:        GPL
author:         testauther
srcversion:     50B6B0B23BAEBE637023B86
depends:        
vermagic:       3.0.0-24-generic-pae SMP mod_unload modversions 686 
parm:           sec:Set the interval. (int)

モジュールを組み込む

$ sudo insmod mymod.ko

dmesgにモジュールの実行結果が出力されている!

$ dmesg | tail
[ 7154.226058] mymod: init

/sysにディレクトリできてる

$ ls /sys/module/mymod 
holders  initstate  notes  parameters  refcnt  sections  srcversion

パラメータ情報を取得

$ cat /sys/module/mymod/parameters/sec 
5

node.jsでバイナリデータを実行するアドオン作った。

node.jsって、Google V8 JavaScript Engine使ってるから、
中身では、javascriptコードをJITで実行しているんだよね。

でも、node.jsでJITして実行したい!
って、要望が(僕の中で)高まってきたので、作りました。

nodeで、バイナリデータを模したArrayを引数にして、
モジュールを呼び出すとC++のアドオンでバイナリが実行され、

バイナリ実行結果の戻り値がリターンされます。
ただそれだけですが。。。

にわかなC++コードをあげときました。
https://github.com/yutaka-m/node-cfunc

実行イメージ

$ node
> var a = require('./build/Release/cfunc');
undefined
> a.cfunc(new Array(0xb8,0x05,0x00,0x00,0x00,0xc3));
5

Arrayに以下のバイナリ列が入ってます。
戻り値が5で返るものです。

0xb8,0x05,0x00,0x00,0x00 // mov $0x5,%eax
0xc3 // retq

コンパイラ実装会用のネタとして、
関数定義の動的な変更(引数と戻り値)
外部ライブラリの読み込み(バイナリからのputchar呼び出し)
Brainf*ckの実装
をできればいいなぁ。

V8 JavaScript Engineを使ってみる。

node.jsでアレコレしようと思うと、C++でアドオンを作る必要が出てきて、
V8 JavaScript Engineをシンプルに動かして試したくなった。
今回は、サンプルを動かすまでの備忘録。
いろんなブログを漁ると、V8は、2年前に流行ってたんですね。。。

環境

OS:Ubuntu 12.04
CPU:64bit

depot_toolsを入手する。

$ mkdir $HOME/tools
$ cd tools
$ git clone https://git.chromium.org/chromium/tools/depot_tools.git
$ vi ~/.bashrc
export PATH=$PATH:$HOME/tools/depot_tools

V8をビルドする。

$ mkdir v8
$ cd v8
$ git clone git://github.com/v8/v8.git v8 && cd v8
$ make dependencies
$ make x64.release -j8
(64bitでコア8個)
$ make x64.release.check
$ cd ..

サンプルコード

$ vi hello_world.cpp

 #include <v8.h>
 using namespace v8;
 int main(int argc,char* argv[]) {
   HandleScope handle_scope;
   Persistent<Context> context = Context::New();
   Context::Scope context_scope(context);
   Handle<String> source = String::New("'hello' + ' world'");
   Handle<Script> script = Script::Compile(source);
   Handle<Value> result = script->Run();
   context.Dispose();
   String::AsciiValue ascii(result);
   printf("%s\n", *ascii);
   return 0;
 }

サンプルコードのビルド

なんか、どこにもドキュメントがないけど、 ./v8/out/x64.release/obj.target/tools/gyp/以下に 静的ライブラリができてたので、それを使う。

$ g++ -I./v8/include hello_world.cpp -o hello_world ./v8/out/x64.release/obj.target/tools/gyp/libv8* -lpthread

サンプルの実行

$hello_world
hello world (出力)

やったぁ!動いた!これで、わざわざnode-gypとか使わずにコードを試せます。

Webアプリにリアルタイムなバックエンドを提供するFirebaseを使ってみた。

スケーラブルでリアルタイムなバックエンドを実現するものらしい。つまり、PaaS的な何か。
具体的には、FirebaseがWebsocketとデータストアを提供してくれます。
(フロントエンドのHTMLとかの置き場を提供してくれるのかは、よく読めてない。。。)

とりあえず試したい人は、まず以下のURLを開いて、
「BUILD A SAMPLE APP IN 5 MINUTES」ボタンを押すところから
はじめるとわかりやすいです。
http://www.firebase.com/

サンプルを動かした感じ

サンプルで作ったアプリをブラウザを2つ開いてテストすると、
リアルタイムにデータが連携していることがわかります。
HTMLをそのままコピー&ペーストし、自分のサーバで公開しても動作してました。
(いつまで使えるかわかりませんが)

f:id:alumican:20120415220852p:plain

使い方とか動作

どうやってリアルタイムなバックエンドを実現しているのかというと、
 1.firebase.jsを組み込む。
 2.データストアの参照を取得
 3.データストアの変更に対して、コールバックを記述する。
 4.データストアを操作する。
という内容になっており、ブラウザのjavascriptだけでデータ駆動するようになっています。

1.Firebaseを組み込む

<script type='text/javascript' src='http://static.firebase.com/demo/firebase.js'></script>

サーバとWebsocket等で通信する部分は、ここに記述されている。

2.データストアの参照を取得

var myDataRef = new Firebase('http://demo.firebase.com/{ここに特定データストアの文字列}');

自分のアプリ用のデータストアを指定しています。

3.データストアの変更に対して、コールバックを記述する。

myDataRef.on('child_added', function(snapshot) {
  //処理を書く
});

child_addedは、データストアのリストにストアされたときに呼び出されるイベント。
そのほか、value・child_changed・child_removed・child_moved等の
イベントをコールバックとして記述できる。

4.データストアを操作する。

myDataRef.set('User ' + name + ' says ' + text);
myDataRef.push({name: name, text: text});

こんなかんじで操作する。

思ったこと

データストアが、第三者でも操作できるんじゃないか?って、素朴な疑問を感じます。
インターネットはオープンでいこうよ!だから、データもオープンだよな!的な原理主義だったら
面白いんだけど、どうすんだろ。

最近、白石さんが紹介していたMeteorなるオールJavascriptフレームワークが出てくる等、
フレームワーク界隈が乱立してる感じですね。
http://d.hatena.ne.jp/Syunpei/20120413/1334276712

 

cowbuilderを使ってみる。

検証はなんでも仮想化環境で頑張っちゃうとか無駄だから、もっと軽量にパッケージを試したい。
手軽にsandboxできるcowbuilderをためしてみた。
その備忘録。

環境は、ubuntu oneiricです。

構築

インストールしてsandboxを構築する。

sudo aptitude install cowbuilder
sudo cowbuilder --create --distribution oneiric --components "main universe" --architecture i386 --basepath /var/cache/pbuilder/base-oneiric-i386.cow

ログイン

変更を適用しない。

sudo cowbuilder --login --basepath /var/cache/pbuilder/base-oneiric-i386.cow 

変更を適用する。(--save)

sudo cowbuilder --login --save --basepath /var/cache/pbuilder/base-oneiric-i386.cow 

/tmpをホストと共有(--bindmount /tmp)

sudo cowbuilder --login --bindmount /tmp --basepath /var/cache/pbuilder/base-oneiric-i386.cow

コマンドの実行(--execute ファイル名)

sudo cowbuilder --execute ./ls.sh --basepath /var/cache/pbuilder/base-oneiric-i386.cow

ログインしたらapt-getして簡単に検証。
chrootとpbuilderとか似たようなものらしい。
いろいろインストールされたカオス環境ともおさらばできそう。

Node.jsのSocket.IO+WebRTCでP2Pの動画チャットを作ってみた。

WebRTCでP2Pを実現しようとすると、ブラウザ1とサーバとブラウザ2の間でリアルタイムな通信を必要とするので、node.jsのWebSocket(Socket.IO)で実装してみた。
最初のページを静的なHTMLで作ったのとDBを使ってないので、
たぶん公式に載ってるデモより混乱しないと思う。

ローカルで2つのブラウザを立ち上げて試すと、うまく動作します。
だけど、リモートで試すとストリームがみつからないみたいでうまく動かない。
blobをやりとりしている部分をもう少し追う必要がありそう。

ソースコード(github)

今回は、少し大きくなったので、githubに公開しました。(と言っても、実質2ファイルです)
https://github.com/yutaka-m/node-webrtc-chat

以下の手順で起動すれば、うまく動作すると思います。

node.jsをインストール
# aptitude install g++
# aptitude install libssl-dev
# mkdir src
# cd src/
# wget http://nodejs.org/dist/v0.6.14/node-v0.6.14.tar.gz
# tar zxvf node-v0.6.14.tar.gz 
# cd node-v0.6.14/
# configure
# make
# make install

npmをインストール
# curl http://npmjs.org/install.sh | sh

アプリをインストール
# git clone git://github.com/yutaka-m/node-webrtc-chat.git
# cd node-webrtc-chat
# npm install
# node app.js

http://localhost:3001/ にアクセスする。

デモ

面倒くさい人用にデモサイトも作りました。

ChromeのDev ChannelとBataで動作確認しています。

http://alumican.jp:3001/

使い方

1.ブラウザを2つ立ち上げる
 (以下、ブラウザAとブラウザBと呼称)
2.ブラウザAの「Generate Room key」ボタンを押し、Room keyを生成する。(手入力でも可)
3.ブラウザAの「Connect」ボタンを押す。
4.ブラウザAの「Room key」をブラウザBの「Room key」にコピー&ペーストする。
5.ブラウザBの「Connect」ボタンを押す。
6.ブラウザAとブラウザBのステータスがEstablished.になったら完了。

余談

node.jsのアプリケーションは、ポートを占有するしちゃうんだけど、
複数アプリケーションを動作させる時はみんなどうしてるんだろう。
apacheプロクシにするとwebsocketで性能が劣化しそうだし悩ましい。

webRTCでP2Pの動画チャットを頑張れば試せるデモ作ってみた。

WebRTCって、P2Pで動画チャットできるって聞いたからためしみた。ら、案の定、動作が安定していないのと、
知らないプロトコルとか出てきて泣いた。

www.webrtc.orgに紹介されている http://apprtc.appspot.com/ のデモコードだと
大きすぎて何しているのかわけわからない。
だから、シンプルにするために
 ・最低限のコードにする
 ・サーバをつかわない(本来、P2Pする前にクライアント間でメディア形式を決めるのに使います)
を目標にデモを書いてみた。
なので、手動でコピペを頑張ってもらう部分がありますw

デモを作る前提知識と参考にしたもの

サーバからのPUSHが必要

http://apprtc.appspot.com/ のデモを参考にしています。
デモコードを見るかぎり、サーバからのPUSHが必要です。
このコードは、Google App EngineのChannel APIで実現していますが、
大体は、WebSocketが前提になるんじゃないかと思います。(ハードル高いw)
今回のデモは、この通信を手動で・・・

STUNサーバ

ブラウザ同士がP2Pするには、大体NATを越える必要があるので、STUNサーバが必要です。
グローバル側から見たブラウザのIPなどの情報を教えてくれるものです。
しかし、構築するのにIPが2つ必要らしいので自前で作るのは難しいため
公開STUNサーバを利用することにしました。
http://www.voip-info.org/wiki/view/STUN
(jpはないのですか?)

コード(sample03.html)

<html>
<head>
<title>sample03</title>
</head>
<body>
<script type="text/javascript">

var local;
var remote;
var pc;
var localstream;

var init = function() {
  local = document.getElementById("local");
  remote = document.getElementById("remote");
  navigator.webkitGetUserMedia("video", gotStream, noStream);
}

var sendSignalingChannel = function(message) {
  console.log("sendSignalingChannel:" + message);
  document.form_test.sdp_out.value = message;
}

var gotStream = function(stream) {
  local.src = webkitURL.createObjectURL(stream);
  localstream = stream;
}

var createPC = function() {
  pc = new webkitPeerConnection('STUN stun.ekiga.net', sendSignalingChannel);
  pc.addStream(localstream);
  pc.onaddstream = function (event) {
    remote.src = webkitURL.createObjectURL(event.stream);
  };
}

var noStream = function(error) {
  alert("noStream");
}

var setSDP = function() {
  var text = document.form_test.sdp_in.value;
  text = text.replace(/^\n/g,"");
  pc.processSignalingMessage(text);
}

setTimeout(init,1);

</script>
<video id="local" width="320" height="240" autoplay></video>
<video id="remote" width="320" height="240" autoplay></video><br>
<form name="form_test">
<button onclick="createPC(); return false;">1 createPeerConnection</button><br>
<button onclick="createPC(); setSDP(); return false;">2 input Offer</button><br>
<button onclick="setSDP(); return false;">3 input Answer</button><br>
<button onclick="setSDP(); return false;">4 input OK</button><br>
SDP input<br>
<textarea name="sdp_in" cols="50" rows="5"></textarea><br>
SDP output<br>
<textarea name="sdp_out" cols="50" rows="10"></textarea><br>
</form>
</body>
</html>


デモ

以下にデモページを用意しています。
3月28日現在、WebRTCは、Google Chromeの開発版(DEV Channel)等でしか動作しないので、
Chromeの開発版でMediaStreamを有効にして試してください。
(味見部で試してもらった結果、Chrome Canaryだと動作しないようです)
あと、Webカメラが必要です。

ただし!手順どおり実行しないと動きませんー!
http://alumican.ddo.jp/webrtc/sample03.html
※動作確認は、Google Chrome Version 19.0.1068.1 devでしました。
※動画データなどは、サーバに送信されません。

操作手順

1.http://alumican.ddo.jp/webrtc/sample03.htmlを2つのウィンドウで開く。
 (以下、ブラウザAとブラウザBと呼称)
2.おもむろにブラウザAの「1 createPeerConnection」ボタンを押す。
3.ブラウザAの「SDP output」に表示されたテキストをコピー
4.ブラウザBの「SDP input」にペースト
5.ブラウザBの「2 input Offer」ボタンを押す。
6.ブラウザBの「SDP output」に表示されたテキストをコピー
7.ブラウザAの「SDP input」にペースト
8.ブラウザAの「3 input Answer」ボタンを押す。
9.ブラウザAの「SDP output」に表示されたテキストをコピー
10.ブラウザBの「SDP input」にペースト(※前に入ってたデータは消す)
11.ブラウザBの「4 input OK」ボタンを押す。

この手順を素早く!(時間制限があるみたいだから)
うまくいけば、これでブラウザAもBもカメラの動画がローカルとリモートの2つ表示されます。

f:id:alumican:20120327183354p:plain


基本的に、手順操作に失敗したら、状態依存があるらしく2度と同じ結果が得られないことが多いので
開発版のChromeを再起動するのがいいかなと思います。
他でコーディング試している人はどうしてるんだろう。教えて偉い人m(_ _)m

最期までやってくれた方、お疲れさまでした。
次は、ちゃんとサーバ立ててWebSocket込みのデモを作ろうとおもいます。

 ローカルでしか試していないので不具合とかあったらコメントください。