Slide 1

Slide 1 text

nginxの初期化 @karky7 2015/11/28

Slide 2

Slide 2 text

自己紹介 氏名:デニーロ・田畑 三島にある、Handsという会社で、後輩のパシリをやってます

Slide 3

Slide 3 text

自己紹介 twitter: @karky7 contribute gentoo-haskellコミッタ 日本OpenSolarisユーザーグループ会 パッケージメンテナ gentoo好き 静岡ベシャベシャ協会 伊東支部(会計) ハッシュタグ #ベシャベシャ

Slide 4

Slide 4 text

初期化フェーズについて調べてみた

Slide 5

Slide 5 text

初めに注意事項

Slide 6

Slide 6 text

ちなみにそんなに知ってるわけじゃないので

Slide 7

Slide 7 text

間違ってたら、許してね

Slide 8

Slide 8 text

細かい、ツッコミなしでお願いします

Slide 9

Slide 9 text

細かい、ツッコミしたら...

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

原液

Slide 12

Slide 12 text

イッキさせます、キリッ!

Slide 13

Slide 13 text

nginxの特徴 apacheとの違いとかは、世の素晴らしい先生の方々のドキュメントを 参照お願いします、はしょります

Slide 14

Slide 14 text

私はコードを追っかけてみました

Slide 15

Slide 15 text

main関数その1 1. ngx_strerror_init() 2. ngx_get_options() 3. ngx_time_init() 4. ngx_regex_init() 5. ngx_log_init()

Slide 16

Slide 16 text

main関数その2 6. ngx_ssl_init() 7. ngx_save_argv() 8. ngx_process_options() 9. ngx_os_init() 10. ngx_crc32_table_init() 11. ngx_add_inherited_sockets()

Slide 17

Slide 17 text

main関数その3 12. モジュール数のカウント 13. ngx_init_cycle() ・・・これでかい 14. ngx_os_status() 15. ngx_init_signals() 16. ngx_daemon() ・・・ デーモン化 ※ページを稼いでいる分けではありませ

Slide 18

Slide 18 text

main関数その4 17. ngx_master_process_cycle() 18. ngx_start_worker_processes() 19. ngx_spawn_process() ・・・ worker_processes分さらにfork() 19. ngx_worker_process_cycle() ・・・ event loopへ突入

Slide 19

Slide 19 text

みるの、やだ、なえるwww

Slide 20

Slide 20 text

ngx_strerror_init() 135個あるエラーコードをエラー文字列へ変換しngx_sys_errlist配列 へする 変換はstrerror()を利用してerrnoを文字列化

Slide 21

Slide 21 text

ngx_get_options() コマンドラインのオプション解析

Slide 22

Slide 22 text

ngx_time_init() 時間関連の初期化、ログの出力フォーマットを作成

Slide 23

Slide 23 text

ngx_regex_init() PCRE系の初期化、pcre用のメモリ確保関数、メモリ解放関数へのポイ ンタを初期化 PCRE Perl Compatible Regular Expressions perl互換正規表現互換ライブラリ

Slide 24

Slide 24 text

ngx_log_init() error_logをログレベルNGX_LOG_NOTICEでオープン --error-log-path=で指定した場合、NGX_ERROR_LOG_PATHがdefine される それ以外はprefixからの相対パスでnginx.confで指定可能

Slide 25

Slide 25 text

ngx_ssl_init() SSLライブラリ関連の初期化処理

Slide 26

Slide 26 text

ngx_save_argv() コマンドライン引数の情報を一時cycle変数へコピー、環境変数のポイ ンタ(environ)を取得 environ ・・・ ローダのldに設定されているプロセスの環境変数 ... 00007ffff7ffd000 4K rw--- ld-2.20.so ...

Slide 27

Slide 27 text

ngx_process_options() init_cycleのprefix情報、ログ関連の情報を初期化

Slide 28

Slide 28 text

ngx_os_init() CPU、pagesizeに関する情報収集 利用可能なCPU数の取得(cpuinfo) pagesizeの取得 CPUのキャッシュラインのサイズを取得 open可能なファイルディスクリプタの数を取得

Slide 29

Slide 29 text

利用可能なCPU数の取得 ngx_ncpu = sysconf(_SC_NPROCESSORS_ONLN);

Slide 30

Slide 30 text

pagesizeの取得 ngx_pagesize = getpagesize(); / * s y s c o n f ( _ S C _ P A G E S I Z E ) * /

Slide 31

Slide 31 text

CPU Cache Line とりあえず暫定的に決め打ちしておいて、後でcpuinfoでしっかり設定 ngx_cacheline_size = NGX_CPU_CACHE_LINE; ... void ngx_cpuinfo(void) { ... ... case 6: ngx_cacheline_size = 32; model = ((cpu[0] & 0xf0000) >> 8) | (cpu[0] & 0xf0); if (model >= 0xd0) { / * I n t e l C o r e , C o r e 2 , A t o m * / ngx_cacheline_size = 64; } break; ...

Slide 32

Slide 32 text

CPU Cache Line Pentium /Pro/II/III ... 32 Intel Core, Core 2, Atom ... 64 AMD ... 64 その他 ... 128 となっております

Slide 33

Slide 33 text

open可能fd数 プロセスがオープンできる最大のfd数 getrlimit(RLIMIT_NOFILE, &rlmt) ngx_max_sockets = (ngx_int_t) rlmt.rlim_cur; karky7 ~ # ulimit -a ... open files (-n) 1024 ここで設定されるのは初期値で、のちにnginx.confファイルの worker_rlimit_nofileで指定可能

Slide 34

Slide 34 text

ngx_crc32_table_init() 巡回冗長検査のテーブル設定 16の要素がキャッシュラインに収まるかどうかの検査(だと思うのですが) if (((uintptr_t) ngx_crc32_table_short & ~((uintptr_t) ngx_cacheline_size - 1)) == (uintptr_t) ngx_crc32_table_short) { return NGX_OK; } p = ngx_alloc(16 * sizeof(uint32_t) + ngx_cacheline_size, ngx_cycle->log);

Slide 35

Slide 35 text

ngx_add_inherited_sockets() NGINX_VARに設定された環境変数のソケット番号について追加オプシ ョンを設定 ※ 例えばSO_SNDBUFな

Slide 36

Slide 36 text

moduleへのindexを設定 moduleの管理構造体へ(*ngx_modules[])indexを設定

Slide 37

Slide 37 text

ngx_module_t *ngx_modules[]とは モジュールを管理するオブジェクトをまとめた構造体、モジュールを追 っかけるにはこの構造体からみるといいね! objs/ngx_modiles.c ngx_module_t *ngx_modules[] = { &ngx_core_module, &ngx_errlog_module, ... ... &ngx_http_copy_filter_module, &ngx_http_range_body_filter_module, &ngx_http_not_modified_filter_module, NULL }; objsディレクトリはconfigure時に生成されます

Slide 38

Slide 38 text

ngx_init_cycle() 主要なデータオブジェクトcycleの初期化、ページ単位で色々なデータ 構造を詰めながら初期化を実行していく 4KB単位で領域をアロケートしていく 4KBのなかに色々な型の情報を詰めて確保していく Listenソケットの作成 モジュールのcontext設定関数の呼び出し

Slide 39

Slide 39 text

ngx_create_pool() 4KBを確保し、その領域の先頭に領域のメタ情報を格納したインスタン スを返してくる

Slide 40

Slide 40 text

allocate関数 posix_memalign() Linux版 memalign() Solaris版 ⁽˙³˙⁾◟( ˘•ω•˘ )◞⁽˙³˙⁾ Mac, Win ???

Slide 41

Slide 41 text

メモリ管理 sysconf(_SC_PAGESIZE)でアライメントされた領域のアドレスを返し てくる nginxが確保したメモリ領域は、OSのページング機構に最適化されて いる 領域中に確保される変数オブジェクトはページを跨いで確保される事 はない(と思うよ)

Slide 42

Slide 42 text

初期状態でこうなってます

Slide 43

Slide 43 text

ngx_pcalloc() cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t)); 4KBの領域にsizeof(ngx_cycle_t)分の領域を確保しそのポインタを返し てくる

Slide 44

Slide 44 text

領域内に確保されるインスタンスの開始アドレスは16の倍数にアライメントされています

Slide 45

Slide 45 text

module context呼び出し 設定領域の確保、基本的にはこんな感じで利用されているが、設定領域 へのポインタ配列として利用しているケースもあるよ

Slide 46

Slide 46 text

module context ngx_module_t経由でngx_core_module_create_confが呼ばれます static ngx_core_module_t ngx_core_module_ctx = { ngx_string("core"), ngx_core_module_create_conf, / * v o i d * ( * c r e a t e _ c o n f ) ( n g x _ c y c l e _ t * c y c l e ) ; * / ngx_core_module_init_conf / * c h a r * ( * i n i t _ c o n f ) ( n g x _ c y c l e _ t * c y c l e , v o i d * c o n f ) ; * / }; ngx_module_t ngx_core_module = { NGX_MODULE_V1, &ngx_core_module_ctx, / * m o d u l e c o n t e x t * / ngx_core_commands, / * m o d u l e d i r e c t i v e s * / NGX_CORE_MODULE, / * m o d u l e t y p e * / NULL, / * i n i t m a s t e r * / NULL, / * i n i t m o d u l e * / NULL, / * i n i t p r o c e s s * / NULL, / * i n i t t h r e a d * / NULL, / * e x i t t h r e a d * / NULL, / * e x i t p r o c e s s * / NULL, / * e x i t m a s t e r * / NGX_MODULE_V1_PADDING };

Slide 47

Slide 47 text

nginx.confの読込と初期化

Slide 48

Slide 48 text

ngx_conf_parse() 実際のnginx.confのparseを実行 #define NGX_CONF_BUFFER 4096 .. for ( ;; ) { rc = ngx_conf_read_token(cf); ... defaultでnginx.confファイルのサイズは4096バイトに制限される でかいファイルを読みたい場合は、NGX_CONF_BUFFERをでかくし てコンパイル confファイルにluaコードとか書きすぎると叱られる

Slide 49

Slide 49 text

ngx_read_file() threadが利用可能な処理系の場合pread()で読込 pread()とはファイルオフセットを変化させないread() 複数スレッドで同じfd(nginx.conf)へアクセスできる したがってファイルオフセットはスレッド固有に管理

Slide 50

Slide 50 text

parseされた値 ngx_str_t型の10個の領域を使って値を変換していく、10も使わないけど

Slide 51

Slide 51 text

引数を内部数値へ変換 static ngx_command_t ngx_core_commands[] = { { ngx_string("daemon"), NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, / * パラメータ化する関数 * / 0, offsetof(ngx_core_conf_t, daemon), NULL }, ... { ngx_string("worker_processes"), NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, ngx_set_worker_processes, / * パラメータ化する関数 * / 0, 0, NULL }, ... ...

Slide 52

Slide 52 text

関連はこんな感じ

Slide 53

Slide 53 text

要約すると ngx_conf_read_token() ファイルからトークンを抽出 ngx_conf_handler() トークンを引当しcmdの設定ハンドラを呼び出す

Slide 54

Slide 54 text

ログファイルなどのopen accecc_log、error_logのopen if (fcntl(file[i].fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", file[i].name.data); goto failed; } FD_CLOEXECでexecve()された場合でも適切にfdをcloseするように 設定

Slide 55

Slide 55 text

Listen socketを作成 IP情報はcycle->listeningの配列で管理 複数指定可能 server { listen 192.168.11.3:8000; server_name localhost; location / { ... } } server { listen 192.168.11.3:8989; ... }

Slide 56

Slide 56 text

Listen socketをnonblocking化 int nb = 1; retrun ioctl(s, FIONBIO, &nb); ソケットをnonblockingへ設定 fcntl ・・・ F_SETFL,O_NONBLOCK ioctl ・・・ FIONBIO Posix.1g ・・・ fcntlで設定を推奨ということらしい

Slide 57

Slide 57 text

Socketオプション TCP_DEFFER_ACCEPT データがソケットに到着したときに起きてくるオプション、 nonblocking socketと絡めた場合動作がちょっと不明... SO_ACCEPTFILTER FreeBSD、NetBSB 5.0以降で利用できるソケットオプションらし い、acceptする前に何やらfilterできるそうです

Slide 58

Slide 58 text

NGX_CORE_MODULEの初期化 static ngx_core_module_t ngx_core_module_ctx = { ngx_string("core"), ngx_core_module_create_conf, / * v o i d * ( * c r e a t e _ c o n f ) ( n g x _ c y c l e _ t * c y c l e ) ; * / ngx_core_module_init_conf / * こちらです * / }; 最終初期化処理の実行

Slide 59

Slide 59 text

ngx_configure_listening_sockets() ソケットの追加オプションの設定 soket option SO_RCVBUF, SO_SNDBUF, SO_KEEPALIVE, SO_SETFIB, SO_ACCEPTFILTER TCP option TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_FASTOPEN, TCP_DEFER_ACCEPT バックログの設定

Slide 60

Slide 60 text

module_init系の呼出 全てのモジュールのinit_module系を呼び出す(定義されていればです が) for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->init_module) { if (ngx_modules[i]->init_module(cycle) != NGX_OK) { / * f a t a l * / exit(1); } } } ngx_event_module_init ngx_regex_module_init ngx_http_spdy_module_init

Slide 61

Slide 61 text

ngx_init_signals() ... 1 シグナル情報をまとめたテーブルを利用してシグナルハンドラを登録 ngx_signal_t signals[] = { { ngx_signal_value(NGX_RECONFIGURE_SIGNAL),/ * S I G H U P * / "SIG" ngx_value(NGX_RECONFIGURE_SIGNAL), / * " S I G H U P " * / "reload", ngx_signal_handler }, / * h a n d l e r * /

Slide 62

Slide 62 text

ngx_init_signals() ... 2 シグナルハンドラをngx_signal_handler()へセット SIGHUP ... NGX_RECONFIGURE_SIGNAL SIGTERM ... NGX_TERMINATE_SIGNAL SIGQUIT ... NGX_SHUTDOWN_SIGNAL SIGWINCH ... NGX_NOACCEPT_SIGNAL SIGUSR1 ... NGX_REOPEN_SIGNAL SIGUSR2 ... NGX_CHANGEBIN_SIGNAL SIGALRM SIGINT SIGIO SIGCHLD SIGSYS SIGPIPE

Slide 63

Slide 63 text

ngx_signal_handler() ... 1 ngx_processの値が以下の場合 NGX_PROCESS_MASTER NGX_PROCESS_SINGLE NGX_SHUTDOWN_SIGNAL ... ngx_quit = 1(shutdown) NGX_TERMINATE_SIGNAL ... ngx_terminate = 1 (exiting) SIGINT ... ngx_terminate = 1 (exiting) NGX_NOACCEPT_SIGNAL ... ngx_noaccept = 1 (stop accepting connections) NGX_RECONFIGURE_SIGNAL ... ngx_reconfigure = 1 (reconfiguring) NGX_REOPEN_SIGNAL ... ngx_reopen = 1 (reopeninig log) NGX_CHANGEBIN_SIGNAL ... ignore = 1 (ignore) SIGALRM ... ngx_sigalrm = 1 SIGIO ... ngx_sigio = 1 SIGCHLD ... ngx_reap = 1

Slide 64

Slide 64 text

ngx_signal_handler() ... 2 ngx_processの値が以下の場合 NGX_PROCESS_WORKER NGX_PROCESS_HELPER NGX_NOACCEPT_SIGNAL ... ngx_debug_quit = 1(ngx_daemonized == 0) NGX_SHUTDOWN_SIGNAL ... ngx_quit = 1 (shutting down) NGX_TERMINATE_SIGNAL ... ngx_terminate = 1 (exiting) NGX_REOPEN_SIGNAL ... ngx_reopen = 1 (reopening logs) NGX_RECONFIGURE_SIGNAL ... (ignoring) NGX_CHANGEBIN_SIGNAL ... (ignoring) SIGIO ... (ignoring)

Slide 65

Slide 65 text

ngx_process_get_status() ... 1 SIGCHLDは子プロセスの終了ステータスを取得してクリーンアップ for ( ;; ) { pid = waitpid(-1, &status, WNOHANG); ... / * p i d から終了プロセスをe x i t e d へ設定 * / for (i = 0; i < ngx_last_process; i++) { if (ngx_processes[i].pid == pid) { ngx_processes[i].status = status; ngx_processes[i].exited = 1; process = ngx_processes[i].name; break; } } ...

Slide 66

Slide 66 text

ngx_process_get_status() ... 2 子プロセスの終了ステータスによってログを書込 WIFEXITED(status) 子プロセスが通常終了(exit())した場合にTrueを返す WEXITSTATUS(status) 子プロセスの終了ステータスを返す、WIFEXITEDがTrueの場合だ け呼ぶこと WTERMSIG(status) 子プロセスの終了の原因となったシグナル番号を返す、 WIFSIGNALEDがTrueの場合だけ呼ぶこと if (WEXITSTATUS(status) == 2 && ngx_processes[i].respawn) { ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "%s %P exited with fatal code %d " "and cannot be respawned", process, pid, WEXITSTATUS(status)); ngx_processes[i].respawn = 0; } ngx_unlock_mutexes(pid); ...

Slide 67

Slide 67 text

ngx_daemon() 「daemon = on」でdaemon化する、このプロセスが NGX_MASTER_PROCESSと設定される 親プロセス 速攻exit() 子プロセス ngx_pidへプロセスIDを格納 dup2()でSTDIN,STDOU,STDERRを/dev/nullへ複製 ngx_daemonized = 1 ngx_create_pidfile() NGX_MASTER_PROCESSのpid(ngx_pid)をnginx.pidファイルへ 書き出し

Slide 68

Slide 68 text

ngx_master_process_cycle() ... 1 「master_process on」でmaster_processを作成

Slide 69

Slide 69 text

ngx_master_process_cycle() ... 2 その後呼ぶforループ中でシグナルを受信したくないため、無視するシ グナルを設定する。 forループ中では子プロセスを調整するための処理 を実行中のためシグナルを受信してしまうと、まずい事になる。 sigemptyset(&set); sigaddset(&set, SIGCHLD); sigaddset(&set, SIGALRM); sigaddset(&set, SIGIO); sigaddset(&set, SIGINT); sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "sigprocmask() failed"); } ...

Slide 70

Slide 70 text

ngx_master_process_cycle() ... 3 ngx_start_worker_processes()呼出 子プロセスとしてworker_processが生成 for ( ;; ) { ... sigsuspend(&set); ... worker_processを生成した親はループに突入しsigsuspend()でsleep

Slide 71

Slide 71 text

sigsuspend() 無視したシグナルを一時的に退避して寝る 無視しているシグナルが受信可能状態になる シグナルハンドラを実行して起きてくる 起きた後は前回仕込んだシグナルマスクが有効になっている シグナルハンドラを実行した後は、グローバル変数などが更新されてい るので、そのフラグに応じて生成した子プロセスを処理する ... if (ngx_quit) { ngx_signal_worker_processes(cycle, /* killの発行 */ ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); ...

Slide 72

Slide 72 text

ngx_start_worker_processes() 「worker_processes」数のworker_processをさらにfork()する type = NGX_PROCESS_RESPAWNでngx_spawn_process()の呼出 / * n = w o r k e r _ p r o c e s s e s * / for (i = 0; i < n; i++) { ngx_spawn_process(cycle, ngx_worker_process_cycle, (void *) (intptr_t) i, "worker process", type); / * f o r k ( ) した子プロセスの情報を保存 * / ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; ngx_pass_open_channel(cycle, &ch); }

Slide 73

Slide 73 text

ngx_spawn_process() 子プロセス通信するためのStream UNIX Domain Socketを作成 if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1) { ... ngx_processes[s].channel[0,1]をnonblockingへ設定 ngx_processes[s].channel[0]をシグナル駆動IOへ設定 ngx_processes[s].channel[0]をF_SETOWN SIGIOを受け取るソケットのプロセスを ngx_pid(NGX_MASTER_PROCESS)に設定 ngx_processes[s].channel[0,1]をFD_CLOEXEC execされても自動closeするようsocketを設定

Slide 74

Slide 74 text

ngx_worker_process_cycle() ngx_worker_process_init() 初期化処理 「worker process」へプロセス名を設定 ngx_process_events() 実際のevent loopへ突入

Slide 75

Slide 75 text

ngx_worker_process_init() ngx_process = NGX_PROCESS_WORKERに設定 worker_rlimit_nofileの設定 プロセスの優先度を設定 moduleのinit_module呼出

Slide 76

Slide 76 text

ngx_process_events() event loopのepoolでクライアントのアクセスがまるまでsleep events = epoll_wait(ep, event_list, (int) nevents, timer); backtraceスはこんな感じ #0 ngx_epoll_process_events (cycle=0x7457f0, timer=18446744073709551615, flags=1) at src/event/ #1 0x00000000004326b3 in ngx_process_events_and_timers (cycle=0x7457f0) at src/event/ngx_event. #2 0x000000000044007d in ngx_worker_process_cycle (cycle=0x7457f0, data=0x0) at src/os/unix/ngx #3 0x000000000043c6db in ngx_spawn_process (cycle=0x7457f0, proc=0x43fe5c

Slide 77

Slide 77 text

こうなる

Slide 78

Slide 78 text

epollってなに I/O multiplexing(I/Oの多重化)のうちの1つ select() ... fdセットからの検索が必要 poll() ... 高速なselectのようなもの、移植性にかける模様 Linuxのみ(Solarisは/dev/pollデバイスで行なう) fdの管理をkernel内で管理 fdの数は無制限 fdの検索がO(1)になっているためユーザーランドの処理はselectより 高速

Slide 79

Slide 79 text

epollのサーバーサイドのそれ 1 1. epollオブジェクトの作成 epfd = epoll_create(MAX_EVENTS) 2. Listenソケットをイベントへ登録 struct epoll_event ev; / * L i s t e n s o k e t 設定用* / struct epoll_event events[MAX_EVENTS]; / * e v e n t 発生取得用 * / sock = socket(PF_INET, SOCK_STREAM, 0) bind(sock, (struct sockaddr *) &sin, sizeof sin); listen(sock, BACKLOG); ev.events = EPOLLIN; ev.data.fd = sock; epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev); 3. wait int nfd = epoll_wait(epfd, events, MAX_EVENTS, -1);

Slide 80

Slide 80 text

epollのサーバーサイドのそれ 2 4. イベントループ開始 for (i = 0; i < nfd; i++) { / * L i s t e n S o c k e t が起きた * / if (events[i].data.fd == sock) { / * s o c k はL i s t e n s o c k e t * / / * クライアントのs o k e t ファイルディスクリプタの取得 * / int client = accept(socket, (struct sockaddr *) &client_addr, &client_addr_len); / * クライアントのs o k e t をn o n b l o c k i n g へ * / int flag = fcntl(client, F_GETFL, 0); fcntl(client, F_SETFL, flag | O_NONBLOCK); / * k e r n e l へ読込可能、エッジトリガ形式で登録依頼 * / ev.events = EPOLLIN | EPOLLET; ev.data.fd = client; / * 登録 * / epoll_ctl(epfd, EPOLL_CTL_ADD, client, &ev); } else { / * 読込が可能なf d が既に入ってる * / int client = events[i].data.fd; int n = read(client, buffer, sizeof(buffer)); write(client, buffer, n); } } というような感じで動きます...コードはイメージです アハ

Slide 81

Slide 81 text

最後におまけ 「もうクドいよ」って吐き捨てないで..

Slide 82

Slide 82 text

nginxをデバックモードでトレースしてみる configure # ! / b i n / b a s h uname -r | grep gentoo GENTOO=$? if [ $GENTOO -eq 0 ] ; then echo '' echo 'Check system is `Gentoo`' echo '' ADDOPT="--with-cc-opt=-I/usr/include --with-ld-opt=-L/usr/lib64" else ADDOPT=" " fi CFLAGS="-g -O0" ./configure --prefix=$HOME/devbin/nginx \ --conf-path=$HOME/devbin/nginx/conf/nginx.conf \ --error-log-path=$HOME/devbin/nginx/var/log/error_log \ --pid-path=$HOME/devbin/nginx/var/run/nginx.pid \ --lock-path=$HOME/devbin/nginx/var/run/lock/nginx.lock \ --http-log-path=$HOME/devbin/nginx/var/log/nginx/access_log \ --http-client-body-temp-path=$HOME/devbin/nginx/var/lib/nginx/tmp/client \ --http-proxy-temp-path=$HOME/devbin/nginx/var/lib/nginx/tmp/proxy \ --http-fastcgi-temp-path=$HOME/devbin/nginx/var/lib/nginx/tmp/fastcgi \

Slide 83

Slide 83 text

ビルド build # ! / b i n / b a s h TMP=$HOME/devbin/nginx/var/lib/nginx/tmp/ LOG=$HOME/devbin/nginx/logs/ make -j6 make install if [ -d $TMP ]; then echo "[ $TMP ] found" else echo "Create directory [ $TMP ]" mkdir -p $TMP fi if [ -d $LOG ]; then echo "[ $LOG ] found" else echo "Create directory [ $LOG ]" mkdir -p $LOG fi

Slide 84

Slide 84 text

fork()に備えたgdbの設定 ~/.gdbinit set history save on set history size 10000 set history filename ~/.gdb_history set print pretty on set print static-members off set charset UTF-8 set follow-fork-mode child set detach-on-fork off dir /home/cuomo/Code/nginx/ngx-1.8.0/src dir /home/cuomo/Code/nginx/ngx-1.8.0/src/event dir /home/cuomo/Code/nginx/ngx-1.8.0/src/event/modules ... set follow-fork-mode child fork()したら子プロセスに自動attach set detach-on-fork off fork()後親、子プロセスともに捕まえる

Slide 85

Slide 85 text

ちょっとやってみる emacsから「M-x gdb」 emacs> gdb -i=mi ~/devbin/nginx/sbin/nginx Type "apropos word" to search for commands related to "word"... Reading symbols from /home/cuomo/devbin/nginx/sbin/nginx...done. (gdb) b main Breakpoint 1 at 0x40791f: file src/core/nginx.c, line 203. (gdb) r Starting program: /home/cuomo/devbin/nginx/sbin/nginx [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". Breakpoint 1, main (argc=1, argv=0x7fffffffd818) at src/core/nginx.c:203 203 { (gdb) できたか?!

Slide 86

Slide 86 text

今後は... 今後は、キャバクラに連れて逝ってもラッテから、イベント、モジュー ルの動きとか追っかけたいと思います

Slide 87

Slide 87 text

ご清聴有難うございました