Apache Module 作成 ~~HelloWorld~~
概要
社内のいろんな人がapacheやnginxのモジュールを作成してアウトプットされているので自分もこの流れにのっかって(だいぶ遅い)とりあえずApacheのモジュールを作成してみようお思ったのでブログ書いてみた。
いろいろ
- VM:Vagrant + virtualBox
- OS:CentoOS7
httpd -v Server version: Apache/2.2.15 (Unix) Server built: Feb 9 2016 17:28:49
雛形作成
apxインストール
apxという便利なコマンドを使えばモジュールの雛形が作成できるみたい。apxをインストール。
yum install httpd-devel
雛形出力
apxs -g -n hello
- -g : 雛形生成指定
- -n : モジュールの名前指定(ハイフンをつけたらコンパイルエラーになってはまった。)
結果
$ ls
Makefile mod_hello.c modules.mk
mod_hello.c
#include "httpd.h" #include "http_config.h" #include "http_protocol.h" #include "ap_config.h" /* The sample content handler */ static int hello_handler(request_rec *r) { if (strcmp(r->handler, "hello")) { return DECLINED; } r->content_type = "text/html"; if (!r->header_only) ap_rputs("The sample page from mod_hello.c\n", r); return OK; } static void hello_register_hooks(apr_pool_t *p) { ap_hook_handler(hello_handler, NULL, NULL, APR_HOOK_MIDDLE); } /* Dispatch list for API hooks */ module AP_MODULE_DECLARE_DATA hello_module = { STANDARD20_MODULE_STUFF, NULL, /* create per-dir config structures */ NULL, /* merge per-dir config structures */ NULL, /* create per-server config structures */ NULL, /* merge per-server config structures */ NULL, /* table of config file commands */ hello_register_hooks /* register hooks */ };
コンパイル&インストール
apxs -i -a -c mod_hello_world.c
インストールオプション
-c This indicates the compilation operation. It first compiles the C source files (.c) of files into corresponding object files (.o) and then builds a dynamically shared object in dsofile by linking these object files plus the remaining object files (.o and .a) of files. If no -o option is speci‐ fied the output file is guessed from the first filename in files and thus usually defaults to mod_name.so. -i This indicates the installation operation and installs one or more dynami‐ cally shared objects into the server's modules directory. -a This activates the module by automatically adding a corresponding LoadMod‐ ule line to Apache's httpd.conf configuration file, or by enabling it if it already exists.
結果(色々できてる)
ls
Makefile mod_hello.c mod_hello.la mod_hello.lo mod_hello.o mod_hello.slo modules.mk
httpd.conf
/hello/ で始まる URI のリクエストを処理するハンドラーを指定。
<Location "/hello/"> SetHandler hello </Location>
モジュールのダイナミックリンク指定
自動で追加される↓
LoadModule hello_module /usr/lib64/httpd/modules/mod_hello.so
結果
apache再起動でhtt://localhost/hello/で以下が表示される
The sample page from mod_hello.c
デバッグ準備めもめも
やりたいこと
initプロセスまでの流れや、カーネルのデバッグをしたいのでいろいろと準備の自分メモ。 qemu上でデバッグできるようになりたいなぁ。
今日やったこと
qumu-img、qemu-kvmコマンドを使って仮想マシンの作成。それを元に仮想マシンルートファイルシステムを/mnt以下にマウント。
losetup
- ループバッグデバイスの一覧が表示される。
vgsscan
- 何も設定していないCentOS7だと何も表示されない
- ボリュームグループの一覧が表示される。
lvscan
kpartx -av xxx.img
- マッパーデバイスにマッピングする(/dev/mapper/loop1p1が仮想ディスク)
- 仮想ディスクのVGとLVをホスト側で見えるようになる(非アクティブ)
- add map loop1p1
kpartあとの変化
- ループバッグデバイスに割り付ける(例えばloop1p1)、その中の(仮想ディスク)VG、LGがホストでみえる。
- loop1p1の中のVGとかLVとかがみえる?
- さらにloop1p1の中のVGとLVが/dev/mapper/VG-LVとしてマップされる。
- なので上のvgscan、lvscanの出力が変わる
vgchangeでLVを有効にする。そのままでは無効。
qemuとkvm
仮想化
仮想化のことを勉強してみた。centos7上で実際にvirt-manager、virt-install、quem-img、quem-kvmコマンドを実際に試してみた。
はまったこと
- biosも仮想化機能に対応していないといけない。デフォではOFFられてたのでONにしないといけない。
- /dev/kvm がroot:rootなのでroot:kvmにしてユーザをkvmグループにaddしたが一度ログアウトしないと有効にならない?なのでパーミッションDynedされた。
学んだこと
- 各種仮想マシンを操作するコマンド郡。それを実際に試せたこと。
- 仮想マシンのVCPUはqemuの一つのスレッドと対応していること。なので仮想マシンのCPUは普通にLINUXのスケジューリングでどのVCPUがどれくらいCPUを使うかを決めていること。ホストのOSからみたらただのプロセス。Cgroupなんてのも合わせて勉強すると面白そう。
興味あること
どのようにして仮想マシンの仮想CPU命令を変換しているのか。どこかの記事でqemuをソースコードリーディングしているのがあったので読んでみたいなと思った。
やってみること
systemtapを使いたい
カーネルデバッグ
ネットをみているとsystemtapというものを使ってカーネルデバッグができるようだったので、systemtapを使ってみようと思った。 自分の環境はcentos6.7 カーネル2.6系
必要なもの
- systemtap
- kernel-debuginfo
- kernel-devel
- kernel-debuginfo-common
develは最初っからはいっていた。ほかはyumでいけるのかなーと思ったらsystemtap以外はだめだった。。 やりかたがおかしいのかなぁ。 なんでネットでdebuginfo、debuginfo-commonのrpmをダウンロードしてインストール。 しかし、これでstapコマンドを使ってみるも、debuginfoがないと怒られた。/lib/modules/カーネルバージョン/buildはあるように見えたが、怒られた。 ということでよくわからずkernel-debuginfoコマンドがあるということなので、カーネルバージョンを指定してinstallしたらうまくいった。
やったこと
とりあえず__switch_toを追跡しようと思ったが、なんかそんなものありませんみたいなかんじだった。なぜだ!新しくなったのかなぁ? ということでとりあえずsimiliarででてたswitch_mmを指定。うまく実行できた。
これから
systemtapの他にもっと便利なやつあるのかなー? とりあえずこれを使ってinitプロセスが立ち上がるまでを追跡できたらいいなと思っとります。
共有ライブラリ
共有ライブラリ
コンパイラ、OS、ハッキング本などなど色んな本を読んでいると必ず出てくるキーワード、それが共有ライブラリ。避けては通れない共有ライブラリ。なぜならコンパイラ(gcc)は必ずプログラム共有ライブラリを使用しているからだ。C言語でmain関数の中を空にしてもスタートアッププログラムがリンクされる。
標準C libc
Linuxでは/libか/usr/libにインストールされるみたい。 とある環境のプロセスのメモリ情報
cat maps ldd a.out linux-gate.so.1 => (0xb776e000) libc.so.6 => /lib/libc.so.6 (0x49cbd000) /lib/ld-linux.so.2 (0x49c95000)
soフアイルが共有ファイル。やはり必ず使用されているみたい。 ちなみに標準CにはCで実装するには面倒なものをCで実装しているものと、アセンブラで書かれているものがある(システムコールラッパー)。
共有ファイルの仕組み
動的リンク
共有ライブラリはプログラム実行時に動的にリンクされる。ちなみに.interpセクションで指定されたダイナミックリンカ(通称ld.so)がexecveの際にメモリにロードされld.soが共有ライブラリを再帰的にリンクする。
共有ライブラリのシンボル解決
共有ライブラリは各プロセスで共有されて、各プロセスの仮想メモリにはそれぞれ別のアドレスに割り当てられる。さらに共有ライブラリは実行時にリンクされるので実行時までアドレスが決定されない。よってプログラムの実行時には共有ライブラリの参照箇所はシンボル解決が行われていな。なので、実行時にはわかっていない共有ライブラリのアドレスを調べてシンボル解決する仕組みが必要になる。それがGOTとPLT。
GOT
直接共有ライブラリへ参照はせず、GOT領域を使用する。GOTはデータ領域に配置されるので各プロセスが独自に持てる領域。なので各プロセスはここで各々プロセスによって異なる共有ライブラリへの参照を保持する。初期値はその共有ライブラリへのシンボル解決するアドレスへの値が入っていてシンボル解決するとこの各共有ライブラリの関数などに対応するGOT領域にアクセスすれば共有ライブラリに参照ができる。
PLT
PLTは対象の共有ライブラリへ参照するためにGOTに飛ぶ。PLT→GOT→共有ライブラリ。なんで二段階になっているかというと、はじめはシンボル解決するための処理が入るので(コレハ図をみないとわかりにくい)。 アセンブラではしたみたいな感じでかかれてる。
print@PLT
初ブログ
@福岡でwebエンジニアやってます!よろしくお願いします!))
詳しくありませんが、低レイヤーのことに興味もっています。詳しいことは書けません!!備忘録として日々ブログできればと思ってます!