第8回ネットワークプログラミング 中村 修.

Slides:



Advertisements
Similar presentations
システムプログラミング 第11回 シグナル 情報工学科 篠埜 功. 今回の内容 前回の補足( exit システムコールについ て) プロセス間通信 – シグナルの送信 --- 今回の内容 – パイプによる通信 – ソケットによる通信.
Advertisements

ネットワーク・プログラミ ング カーネルの役割とプロセス生成. 1.1 OS の役割 仮想マシン OS はハードウェアの多様性 をカプセル化し、利用者を 複雑な処理から開放する。 プロセス管理 時間多重化により各プロセ スに CPU を割当てる。 メモリ管理 メモリ空間の多重化により、 各プロセスにメモリを割当.
プロセスの生成とコマンドの実行 プロセスの生成とコマンドの実行 プロセス生成のシステムコール プロセス生成のシステムコール プロセス生成のプログラム例 プロセス生成のプログラム例 プログラム実行のシステムコール プログラム実行のシステムコール 子プロセスの終了を待つシステムコール 子プロセスの終了を待つシステムコール.
システムプログラミング 第10回 情報工学科 篠埜 功. 今回の内容 プロセス(続き) – execve システムコール 現在のプロセスを、引数に与えられたファイル(実行 形式ファイルあるいはシェルスクリプト等の実行可能 なファイル)を受け取り、現在のプログラムをそれで 置き換える(変身)。 fork.
アルゴリズムとデータ構造 第2回 線形リスト(復習).
プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
ネットワークプログラミング 第9回「応用ネットワークプログラミング(1)」
プログラミング言語論 第6回 型 情報工学科 篠埜 功.
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
OSとコマンド OS:コンピュータを使うための基本プログラム コマンド:OS上で使用できる命令 OS本体であるカーネルの内部コマンド
担当:青木義満 情報工学科 3年生対象 専門科目 システムプログラミング システムプログラミング プロセス間通信(パイプ) 担当:青木義満
プログラミング演習II 2004年12月 21日(第8回) 理学部数学科・木村巌.
第4回放送授業.
担当:青木義満、篠埜 功 情報工学科 3年生対象 専門科目 システムプログラミング 第8回、第9回 シグナル処理 担当:青木義満、篠埜 功
Linuxカーネルについて 2014/01.
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
シグナル通信 普通の割込みとソフトウェア割込み ソフトウェア割込みとシグナル キーボードからのシグナル 例外 (exception)
関数 関数とスタック.
(B2) 親: minami, kazuki 多様な認証機器に対応する 認証システム (B2) 親: minami, kazuki.
Linux リテラシ2006 第6回 デーモン CIS RAT.
オペレーティングシステム2004 プロセス (1) 2004年10月8日 海谷 治彦.
アスペクト指向プログラミングを用いたIDSオフロード
情報工学科 3年生対象 専門科目 システムプログラミング 第5回、第6回 ヒアドキュメント レポート課題 情報工学科 篠埜 功.
ネットワークプログラミング 中村 修.
プログラミング2 関数
第11回ネットワークプログラミング 中村 修.
第7回ネットワークプログラミング 中村 修.
ソケットプログラム(TCP,UDP) EasyChat開発
システムプログラミング 第9回 、10回 ハードリンク、シンボリックリンク プロセスの生成
システムプログラミング 第12回 プロセス間通信 情報工学科 篠埜 功.
マルチスレッド処理 マルチプロセス処理について
プログラミング 4 記憶の割り付け.
インターネットにおける真に プライベートなネットワークの構築
演習1の解答例の解説 2004年10月21日 海谷 治彦.
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
Webプロキシ HTTP1.0 ヒント CS-B3 ネットワークプログラミング  &情報科学科実験I.
演習1の解答例の解説 2006年11月8日 海谷 治彦.
Talkプログラムのヒント 1 CS-B3 ネットワークプログラミング  &情報科学科実験I.
担当:青木義満 情報工学科 3年生対象 専門科目 システムプログラミング 第6回 システムプログラミング概要 プロセスの生成 担当:青木義満
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
ネットワーク・プログラミング ソケットオプションとスレッド.
フロントエンドとバックエンドのインターフェース
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
B演習(言語処理系演習)第2回 田浦.
データ構造とアルゴリズム 第11回 リスト構造(1)
アルゴリズムとプログラミング (Algorithms and Programming)
システムプログラミング 第12回 プロセス間通信 情報工学科 篠埜 功.
システムプログラミング 第12回 プロセス間通信 情報工学科 篠埜 功.
ネットワーク・プログラミング デバイスドライバと環境変数.
第5回 プログラミングⅡ 第5回
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
ネットワーク・プログラミング 非同期I/Oとスレッド同期制御.
システムプログラミング 第9回 、10回 ハードリンク、シンボリックリンク プロセスの生成
ネットワーク・プログラミング TCPサーバ.
ネットワーク・プログラミング パイプライン通信とシグナル.
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
ネットワーク・プログラミング マルチタスク.
情報処理Ⅱ 2005年11月25日(金).
プログラミング演習II 2004年11月 16日(第5回) 理学部数学科・木村巌.
ネットワーク・プログラミング プロセスとファイルシステム管理.
プログラミング演習II 2003年12月10日(第7回) 木村巌.
プログラミング演習II 2004年11月 2日(第3回) 理学部数学科・木村巌.
情報処理Ⅱ 小テスト 2005年2月1日(火).
プログラミング 2 静的変数.
Presentation transcript:

第8回ネットワークプログラミング 中村 修

今日のお題 講義 ---------休憩-------------------------------- 実習: 並列echoサーバを作ろう 今後の授業予定 ミニプロなどの説明 fork サーバの挙動 プロセス 練習1: forkに慣れよう ---------休憩-------------------------------- 実習: 並列echoサーバを作ろう

今後の授業予定 12/01(月) ミニプロ説明,fork 12/08(月) select 12/15(月) ミニプロプロポーザル提出&チェック   12/22(月) IPv6プログラミング 01/08(木) ミニプロレポート提出&チェック 01/19(月) ミニプロチェック(再提出)、優秀作品発表 *ミニプロについては次ページに詳細あり

ミニプロのルール 個人でプログラムを作る OSは問わない ネットワークを使うプログラム レポートには以下の項目を含めること 一応、公式サポート環境はCNS 他の環境でもTA/SAは(できるだけ)頑張ります ネットワークを使うプログラム レポートには以下の項目を含めること 使用方法 面白さ 実行環境 提出ソースコードにはコメントを付加すること 日本語 or 英語

今日のテーマ forkします

よくあるサーバー 複数のクライアントから 同時にアクセスを受ける サーバー 集中! クライアント クライアント クライアント クライアント

サンプルの問題点 一つのクライアントに対応している間は、他のクライアントに対応できない! どこがネックか? 複数のクライアントが一度にアクセスした場合を考慮しなければいけない どこがネックか? accept()を多重化して実行できると良い? 実際の処理を多重化して実行できると良い?

サーバの気持ちになってみよう たくさんのソケットを扱ったり,めんどくさいことはしたくない 沢山のクライアントが接続してきたら,大変 いちいちソケットを検査するのが面倒 どれにどれだけ時間がかけられるんだ? 沢山のクライアントが接続してきたら,大変

自分の分身を作ればいいんだ! 仕事は全部,分身にまかせよう 親の仕事は,コネクションがきたときに分身を作ることだけ 親プロセス 子プロセス二号 子プロセス一号 t

分身のための関数 forkシステムコール int fork(); 自分とまったく同じ複製プロセスを作るシステムコール 自分がコピーかどうかわからなくならない? 0が帰ってきたら自分は子プロセス 正の整数が帰ってきたら自分はfork()を呼び出した親プロセス -1は失敗

プロセスってなぁに 仕事=アプリケーション=コマンド=プログラム アプリケーションの実行 食べ物をのせるお皿 プログラムをプロセスとして実行 お皿:プロセス アプリケーション

プロセスを見る Solaris BSD系 % ps –efj % ps auxj USER PID PPID PGID …………… COMMAND nobody 123 89 89 …………… httpd

プログラムの実行とプロセス 親プロセス 子プロセス プログラム コピー プロセス プロセス fork() 実行 生成 生成 OS プログラム main(int argc, char *argv) { struct sockaddr_in me, peer; ……. if(pid = fork()) == 0) { child process. } else if(pid > 0) { parenet process. else { error process. プログラム main(int argc, char *argv) { struct sockaddr_in me, peer; ……. if(pid = fork()) == 0) { child process. } else if(pid > 0) { parenet process. else { error process. プログラム main(int argc, char *argv) { struct sockaddr_in me, peer; ……. if(pid = fork()) == 0) { child process. } else if(pid > 0) { parenet process. else { error process. プログラム コピー プロセス プロセス fork() 実行 生成 生成 OS

親と子の区別 fork()の返り値 int parent; parent = fork(); 親側 子側 if(parent > 0){ 親の処理; } else if(parent == 0){ 子の処理 }

よくあるサーバでの処理の流れ 時間のかかるサービス(telnet,ssh,ftpなど)を提供するサーバでよくある処理 接続要求があったら,acceptして,とりあえずfork(); 子プロセスだったら、サービスの提供開始 親プロセスだったら、接続要求待ち 自分でたくさんのFDの面倒を見なくてよい 「後はまかせた」方式

fork()を用いたマルチクライアント サーバの仕組み ファイルディスクリプタ サーバ クライアント1 クライアント2 listen()してクライアントからの リクエストを待っている状態 クライアント3

fork()を用いたマルチクライアント サーバの仕組み ファイルディスクリプタ リクエスト サーバ クライアント1 クライアント2 クライアントからリクエストが 飛んで来た(accept()する直前) クライアント3

fork()を用いたマルチクライアント サーバの仕組み ファイルディスクリプタ accept() リクエスト サーバ fork() クライアント1 サーバ(子) クライアント2 サーバ側でaccept()し、 子プロセスを生成 クライアント3

fork()を用いたマルチクライアント サーバの仕組み ファイルディスクリプタ サーバ(親) クライアント1 サーバ(子) クライアント2 親プロセスはaccept()が作成した ファイルディスクリプタを閉じ、 子プロセスはlisten()しているファ イルディスクリプタを閉じる クライアント3

fork()を用いたマルチクライアント サーバの仕組み ファイルディスクリプタ サーバ(親) クライアント1 サーバ(子) クライアント2 子プロセスがクライアント1からの リクエストを処理 親プロセスは他のクライアントか らの接続要求を待ちつづける クライアント3

fork()を用いたマルチクライアント サーバの仕組み ファイルディスクリプタ accept() サーバ(親) クライアント1 fork() サーバ(子) クライアント2 サーバ(子) クライアント3 新たなクライアントからのリク エストを受け付けると、再び fork()し子プロセスを作成する

練習1: forkに触れてみよう 以下のソースを してみよう。 ソースコードをよーく読んでみよう。 コピー コンパイル 実行    してみよう。 ソースコードをよーく読んでみよう。 /home/kaizaki/osamuNP/8/fork_simple.c

練習1:重要な点① forkの基本構文 int pid; if( (pid = fork()) == 0){       /* child process */ } else if(pid > 0){       /* parent process */ } else { perror("fork()"); }

練習1:重要な点② 変数がコピーされる 別のメモリ領域が確保される Int numberの中身を考えてみよう original process id: 21146 original parent process id: 20587 this is parent process number: 25 fork() return value: 21147 parent process id: 21146 parent parent process id: 20587 press enter this is child process number: 15 fork() return value: 0 child process id: 21147 child parent process id: 21146 press enter

練習1:覚えた方がお得かも int getpid() プロセスidを取得 int getppid() 親プロセスidを取得

実習:echoサーバをforkしよう forkを用いて並列処理できるechoサーバを作成しよう。 ポイント 親プロセスと子プロセスでの役割分担をちゃんと考えよう 役目が終わった子プロセスはちゃんと殺してあるかな?

fork()を利用した並行サーバの注意点:親プロセスの義務 子プロセスが終了すると、「どのような死に様だったか」が親プロセスに伝えられる システムが親プロセスに通知 シグナルを利用 親プロセスは子プロセスの死に様を見届けなければならない 親プロセスが子プロセスの終了状態を受け取らなくては,子プロセスは成仏できずにゾンビプロセスに変わる 子プロセスが死んで,終了状態を受け取らずに親プロセスが死ぬと,ゾンビプロセスがいつまでも残る 子プロセスが終了する前に親プロセスが死ぬと? プロセスID1のinitが養子として引き取ってくれる

終了状態の受け渡し 親プロセス 子プロセス 子プロセス

終了状態の受け渡し 親プロセス 子プロセス 子プロセス 終了(正常/異常)

終了状態の受け渡し 親プロセス ゾンビ プロセス 子プロセス 終了(正常/異常)

終了状態の受け渡し 親プロセス 終了した子プロセスから 状態を取得する 終了(正常/異常) ゾンビ プロセス 子プロセス

終了状態の受け渡し 親プロセス 正確にはプロセスを管理 しているOSから通知される シグナル SIGCHLD ゾンビ プロセス 子プロセス

終了状態の受け渡し 親プロセス ゾンビ プロセス 子プロセス 消滅

シグナルとは? 非同期な事象をプログラムで扱うための方法 それらが起きた時に何らかの処理を実行させられる シグナルハンドラ 非同期(いつおきるか分からない事)な事を知らせてくれる 種類がある 割り込み・子プロセスの状態変化など kill(), raise(), alarm()で意図的に発生させることもできる 事前にOSに「これが起こったら教えてよ」と登録する 逆に「これが起きても無視して」とも言える それらが起きた時に何らかの処理を実行させられる 例えば、割り込み(Ctrl-C)を受け取ったら「ばかやろー」と画面に表示できる あるシグナルを受け取った時に実行する処理を一つの関数にしてそれを登録する シグナルハンドラ シグナルを受け取った時に呼び出される関数 プログラマが定義する 注意: シグナルはキューイングできない 複数の子プロセスが死んでも、親には「1回だけ」通知される

時間的な処理の流れ シグナルハンドラ 何かの処理 シグナル発生 自動的に呼ばれる 処理終了 中断した所から実行を再開

知っておきたいシグナル SIGINT SIGTERM SIGTSTP SIGCHLD SIGALRM Ctrl-Cにバインドされていて、プロセスを終了するためによく使われる SIGTERM これもプロセスを終了するためによく使われる。killコマンドがdefaultで送るシグナル SIGTSTP Ctrl-Zにバインドされていて、プロセスをサスペンドするためによく使われる。 SIGCHLD fork()で作成した子プロセスがexit()したことを通知するシグナル。これを受けて wait() などの後処理を走らせる SIGALRM alarm()によって指定された秒数後に送られるシグナル。タイマーの実装でよく使う

シグナルハンドラの指定: signal() void (*signal(int signo, void (*func)(int)))(int); 指定したシグナル発生時に呼び出される関数(シグナルハンドラ)へのポインタを指定する 以前に設定されていたシグナルハンドラを指すポインタが戻り値 Signoは捕捉するシグナル funcはシグナルハンドラへのポインタ 第2引数のfuncは引数として整数をひとつとり、戻り値を返さない関数へのポインタ

親プロセスの義務(再び) つまり、子プロセスが終了したというシグナルを受け取ったら「南無阿弥陀仏」と唱えなければいけない 子プロセスの終了状態(ステータス)を受け取る 呪文: wait() システムコール 子プロセスの状態を受け取り、変数へ代入 子プロセスの終了状態から、適切な処理を進められる 注意: シグナルのキューイング 複数のシグナルを同時に受信しても「1つ」しか通知されない 複数の子プロセスが同時に死んだ場合の処理を工夫

waitシステムコール群 子プロセスの状態(ステータス)を取得するためのシステムコール pid_t wait(int *status); pid_t waitpid(pid_t wpid, int *status, int option); 子プロセスのpidが戻り値 失敗: -1

wait()とwaitpid()の違い waitは子プロセスが終了する(ほんとは状態が変わる)までブロックする waitpid 親プロセスは別の処理を行えない。 waitpid ブロックしないようにするオプションがある。 WNOHANG 戻り値0は、もう状態の変化したプロセスがないこと pidを指定できる -1 を指定すると最初に状態の変化した子プロセス 0を指定すると、同一プロセスグループidを持つ子プロセス

サンプルコード void sig_child(int signo) { int pid, status; while((pid = waitpid(-1, &status, WNOHANG)) > 0) { printf("PID: %d, terminated\n", pid); } int main(int argc, char *argv[]) …. signal(SIGCHLD, sig_child);