最近はnode.jsに興味を持ち出しています。
そうなると、やっぱり内部のアーキテクチャが気になってしまって、jsを弄るのと並行してlibuvを使ってCでコード書いたりしています。例えば、Apache2.4系のmpmはLoadableなので、libuvでmpm書いちゃったらApacheも高速だろうなーとかも考えてます。
しかし、Windowsはいっぱいあるんだけど、意外とLinuxにlibuvをインストールする記事やドキュメントが無くて、微妙にハマったのでlibuvをLinuxにインストールする方法をまとめておきます。Makefileやconfig-unix.mkをチラチラ見ながらなんとかしました。
Linuxにlibuvをインストール
OSはCentOS5系でわけあって32bitのPAEカーネルの環境にインストールしました。
Linux example.com 2.6.18-308.11.1.el5PAE #1 SMP Tue Jul 10 09:29:33 EDT 2012 i686 i686 i386 GNU/Linux
まずは、libuvをGitHubからとってきます。
そして、libuvディレクトリに移動しmakeします。
すると、上記の32bit環境では下記のようなエラーがでました。64bit環境ではふつうに通ります。
In file included from src/unix/internal.h:40,
from src/unix/async.c:22:
src/unix/linux/syscalls.h:74: error: expected specifier-qualifier-list before ‘__u64’
make: *** [src/unix/async.o] Error 1
おや、__u64がなんか怪しいんでは?と言われている様子。ということで、/usr/include/linux/types.hをみてみると、以下のようになっていました。
96 typedef __u64 uint64_t;
97 typedef __u64 u_int64_t;
98 typedef __s64 int64_t;
99 #endif
ここで安直に、-U__STRIC_ANSI__したらいいんじゃないの?と思い、MakefileのCPPFLAGSに追加するも、以下のようにうまくいきませんでした。
src/unix/signal.c: In function ‘uv__signal_handler’:
src/unix/signal.c:144: warning: implicit declaration of function ‘uv__signal_first_handle’
src/unix/signal.c:144: warning: assignment makes pointer from integer without a cast
src/unix/signal.c: In function ‘uv_signal_start’:
src/unix/signal.c:310: warning: comparison between pointer and integer
src/unix/signal.c: In function ‘uv__signal_stop’:
src/unix/signal.c:446: warning: comparison between pointer and integer
make: *** [src/unix/signal.o] Error 1
うーん、これはなんかいつもの良くない方向にハマっていってるなぁと思ったので、とりあえず__u64をunsigned long longに変える以下のようなpatchを作って当てました。これだとansi、c89の環境なのでもちろんWarningが発生しますが一応コンパイルは通ります。もっと良い案があれば教えて欲しいです。というか__u64と書かれていたのは一か所だけでした。
+++ src/unix/linux/syscalls.h 2012-11-10 00:44:41.000000000 +0900
@@ -71,7 +71,7 @@
struct uv__epoll_event {
__u32 events;
- __u64 data;
+ unsigned long long data;
} __attribute__((packed));
struct uv__inotify_event {
そして、再度makeするとうまく通って、libuv.aがカレントディレクトリに生成されました。そして、ヘッダファイルとライブラリを以下のようにコピーしました。
sudo cp livuv.a /usr/lib/.
そこで、以下のようなlibuvのサンプルコードを書いて、
#include <uv.h>
int main() {
uv_loop_t *loop = uv_loop_new();
printf("Now quitting.¥n");
uv_run(loop);
return 0;
}
以下のようにコンパイルしました。
そして、バイナリa.outを実行すると、
Now quitting.
と、無事libuvを使ったコードを実行する事ができました。
めでたしめでたし。
というわけで、今後はlibuvを使って非同期通信を色々やってみたいと思います。
0 Comments.