LifeTimeStudent

技術的なことの備忘録として

Apache Module 作成 ~~HelloWorld~~

概要

社内のいろんな人がapacheやnginxのモジュールを作成してアウトプットされているので自分もこの流れにのっかって(だいぶ遅い)とりあえずApacheのモジュールを作成してみようお思ったのでブログ書いてみた。

いろいろ

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

    • 論理ボリュームの一覧が表示される。
    • 何も設定していないCentOS7だと下の表示
      • /dev/centos(VG名)/swap(LV名)
      • /dev/centos(VG名)/root(LV名)
  • 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を有効にする。そのままでは無効。

  • 仮想マシンに紐付かせた/dev/VG名(仮想マシン中)/LV名(仮想マシン中)を/mntにマウントする

qemu-kvmコマンドでのインストール

qemu-kvmコマンドでのインストールメモメモ

virt-managerなどを使わずにqemu-kvmコマンドを使って仮想マシンをインストールした時のメモ

やったこと

  1. qemu-imgを使ってイメージファイルを作成
  2. qemu-kvmを使ってゲストOSのインストール

メモメモ

qemu-kvmvncサーバ上でインストールする。なのでqemu-kvmに-vnc 0.0.0.0:1を指定して実行。指定するのはなんでもよい?? インストールを開始するにはvncclientコマンドで上のIPを使ってアクセスする必要がある。

qemuとkvm

仮想化

仮想化のことを勉強してみた。centos7上で実際にvirt-managervirt-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ソースコードリーディングしているのがあったので読んでみたいなと思った。

やってみること

  • 前からエミュレータに興味があったけど、今回qemuを実際に触れてさらにエミュレータに興味を持った。やっぱり仮想化おもしろい。 色々調べて見ると8086などの仮想CPUを自作して、その上で昔のwindowsを動かしたりしているものがあった!色々調べながら自分もこのエミュレータを自作してみたいなーって思った。やっぱり手を動かしてなんぼ。昔の自分に教えてやりたい (´ω`)。。
  • コンテナ技術のDockerを勉強してみたい。

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エンジニアやってます!よろしくお願いします!))

詳しくありませんが、低レイヤーのことに興味もっています。詳しいことは書けません!!備忘録として日々ブログできればと思ってます!