ネットワーク・プログラミング マルチタスク.

Slides:



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

ネットワーク・プログラミ ング カーネルの役割とプロセス生成. 1.1 OS の役割 仮想マシン OS はハードウェアの多様性 をカプセル化し、利用者を 複雑な処理から開放する。 プロセス管理 時間多重化により各プロセ スに CPU を割当てる。 メモリ管理 メモリ空間の多重化により、 各プロセスにメモリを割当.
プロセスの生成とコマンドの実行 プロセスの生成とコマンドの実行 プロセス生成のシステムコール プロセス生成のシステムコール プロセス生成のプログラム例 プロセス生成のプログラム例 プログラム実行のシステムコール プログラム実行のシステムコール 子プロセスの終了を待つシステムコール 子プロセスの終了を待つシステムコール.
システムプログラミング 第10回 情報工学科 篠埜 功. 今回の内容 プロセス(続き) – execve システムコール 現在のプロセスを、引数に与えられたファイル(実行 形式ファイルあるいはシェルスクリプト等の実行可能 なファイル)を受け取り、現在のプログラムをそれで 置き換える(変身)。 fork.
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
データ構造とアルゴリズム 第10回 mallocとfree
システムプログラミング 第13回 情報工学科 篠埜 功.
ネットワークプログラミング 第9回「応用ネットワークプログラミング(1)」
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
OSとコマンド OS:コンピュータを使うための基本プログラム コマンド:OS上で使用できる命令 OS本体であるカーネルの内部コマンド
第8回ネットワークプログラミング 中村 修.
第8回 プログラミングⅡ 第8回
担当:青木義満 情報工学科 3年生対象 専門科目 システムプログラミング システムプログラミング プロセス間通信(パイプ) 担当:青木義満
構造体.
TCPソケットプログラミング ソケットプログラミング TCP-echoのデータ通信手順
アルゴリズムとデータ構造 補足資料6-3 「サンプルプログラムcat3.c」
担当:青木義満、篠埜 功 情報工学科 3年生対象 専門科目 システムプログラミング 第8回、第9回 シグナル処理 担当:青木義満、篠埜 功
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
担当:青木義満 情報工学科 3年生対象 専門科目 システムプログラミング 第11回 プロセス間通信4 仮想FTPの実現 担当:青木義満
オペレーティングシステム2004 プロセス (1) 2004年10月8日 海谷 治彦.
システムプログラミング 第13回 プロセス間通信(続き) 情報工学科 篠埜 功.
UDPエコーサーバ UDP-echoサーバのプログラムモデル(Cプログラム) サーバで利用するソケット関数(Cプログラム)
システムプログラミング 第13回 情報工学科 篠埜 功.
システムプログラミング 第9回 、10回 ハードリンク、シンボリックリンク プロセスの生成
システムプログラミング 第12回 プロセス間通信 情報工学科 篠埜 功.
岡村耕二 トランスポート層 岡村耕二 情報ネットワーク.
マルチスレッド処理 マルチプロセス処理について
岡村耕二 トランスポート層 ソケットプログラミング 岡村耕二 情報ネットワーク.
プログラミング 4 記憶の割り付け.
ソケットプログラム(TCP,UDP) EasyChat開発2
2005年度 データ構造とアルゴリズム 第3回 「C言語の復習:再帰的データ構造」
プログラミング入門2 第11回 情報工学科 篠埜 功.
演習1の解答例の解説 2004年10月21日 海谷 治彦.
第7回 プログラミングⅡ 第7回
第11回 プログラミングⅡ 第11回
Webプロキシ HTTP1.0 ヒント CS-B3 ネットワークプログラミング  &情報科学科実験I.
演習1の解答例の解説 2006年11月8日 海谷 治彦.
データ構造と アルゴリズム 第五回 知能情報学部 新田直也.
担当:青木義満 情報工学科 3年生対象 専門科目 システムプログラミング 第6回 システムプログラミング概要 プロセスの生成 担当:青木義満
関数の再帰呼び出しとは ハノイの塔 リダイレクト レポート課題
岡村耕二 トランスポート層 岡村耕二 情報ネットワーク.
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
ネットワーク・プログラミング ソケットオプションとスレッド.
岡村耕二 トランスポート層 岡村耕二 情報ネットワーク.
2005年度 データ構造とアルゴリズム 第6回 「ハッシュ法を用いた探索」
配列変数とポインタ 静的確保と動的確保 ポインタ配列 2次元配列 時間計測 第1回レポートの課題
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
B演習(言語処理系演習)第2回 田浦.
岡村耕二 TCP通信プログラム 課題と回答例 岡村耕二 情報ネットワーク.
システムプログラミング 第12回 プロセス間通信 情報工学科 篠埜 功.
情報基礎演習B 後半第2回 担当 岩村 TA 谷本君.
システムプログラミング 第12回 プロセス間通信 情報工学科 篠埜 功.
ネットワーク・プログラミング デバイスドライバと環境変数.
ネットワーク・プログラミング Cプログラミングの基礎.
システムプログラミング 第10回 プロセス間通信3 簡易Web server(準備) Chat プログラム 担当:青木義満、篠埜 功
岡村耕二 TCP通信プログラム 岡村耕二 情報ネットワーク.
ネットワーク・プログラミング 非同期I/Oとスレッド同期制御.
システムプログラミング 第9回 、10回 ハードリンク、シンボリックリンク プロセスの生成
ネットワーク・プログラミング TCPサーバ.
ネットワーク・プログラミング メッセージの作成とセマフォ.
ネットワーク・プログラミング ソケットプログラミングと共有メモリ.
ネットワーク・プログラミング 1対多のプロセス間通信.
ネットワーク・プログラミング パイプライン通信とシグナル.
岡村耕二 UDP通信プログラム 課題と回答例 岡村耕二 情報ネットワーク.
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
プログラミング演習II 2004年11月 16日(第5回) 理学部数学科・木村巌.
ネットワーク・プログラミング プロセスとファイルシステム管理.
岡村耕二 TCP通信プログラム 岡村耕二 情報ネットワーク.
Presentation transcript:

ネットワーク・プログラミング マルチタスク

全体の位置づけ オペレーションシステム(Linux) ソケットプログラミング プロセス カーネルとシステムコール プロセス間通信 スレッド クライアントーサーバ 非同期I/Oとマルチタスク

クライアントからの要求が多い場合必要となる 1.1 マルチタスク(並行サーバ) 今まで説明したサーバの処理方法 クライアントからの要求が多い場合必要となる 反復サーバ(TCPEchoServer.c) 一度に一つのクライアントのみ処理する。 並行サーバ(TCPEchoServer-Fork.c) プロセスやスレッドを利用して、1つのクライアントの処理を並列処理するために複数のサーバを作成する。 並行サーバプロセスの作成 クライアントからの要求が到着する毎に新しいプロセスを1つ生成する。 生成された子プロセスは要求してきたクライアントの処理のみを実行する。 子プロセスは処理終了後ゾンビ状態へ。 親プロセスがwaitpid()を実行し子プロセスは完全に消滅する。 TCPEchoServer-Fork.c クライアントから接続要求がある度に子プロセスを作る以外はTCPEchoServer.cと同じ。 サーバはfork()システムコール実行後、 直にclnSockをクローズする。 子プロセスは直にservSockをクローズする。 クライアント 並行サーバ sock servSock クライアント サーバ connect(sock,…) accept(servSock,…) sock clntSock クライアント サーバ fork() sock clntSock サーバ クライアント 子 サーバ:close(clntSock) 子: close(servSock) sock サーバ クライアント clntSock サーバ

1.2 TCPEchoServer-Fork.c プログラマが作成したファイル TCPEchoServer-Fork.c その1 TCPEchoServer-Fork.c その2 #include “TCPEchoServer.h” /* 新しく作ったインクルード */ #include <sys/wait.h> /* waitpid()で利用する */ int main(int argc, char *argv[]) { int servSock; /* サーバのソケット識別子 */ int clntSock; /* クライアントのソケット識別子 */ unsigned short echoServPort; /* サーバのポート番号 */ pid_t processID; /* fork()からのプロセスID */ unsigned int childProcCount = 0; /* 子プロセスの数 */ if (argc != 2) /* 引数の数が正しいかチェック */ fprintf(stderr, "Usage: %s <Server Port>\n", argv[0]); exit(1); } echoServPort = atoi(argv[1]); /* 第1引数はローカルポート番号 */ servSock = CreateTCPServerSocket(echoServPort); for (;;) /* 永遠に繰返す */ { clntSock = AcceptTCPConnection(servSock); /* 子プロセスの作成とエラー報告 */ if ((processID = fork()) < 0) DieWithError("fork() failed"); else if (processID == 0) /* 子プロセスの場合 */ close(servSock); /* 子は親プロセスのソケットをクローズ */ HandleTCPClient(clntSock); exit(0); /* 子プロセスの終了 */ } printf("with child process: %d\n", (int) processID); close(clntSock); /* 親は子のソケットをクローズ */ childProcCount++; /* 未回収の子プロセス数を1増やす */ while (childProcCount) /* 全ゾンビをクリーンアップ */ {       processID = waitpid((pid_t) -1, NULL, WNOHANG); if (processID < 0) /* waitpid()のエラーを確認 */ DieWithError("waitpid() failed"); else if (processID == 0) /* ゾンビが存在しない */ break; else childProcCount--; /* 子プロセスを1つ回収 */ /* この部分には到達しない */ その3で説明 接続要求毎に 子プロセス作成 親が使用中のためソケットの リソース自体は開放されない HandleTCPClient() については第9回参照 ワイルド カード 成功すると終了した子プロセスのプロセスID サーバソケットを作成し、接続要求待ち(listen())までを行う関数 ノンブロッキング(ゾンビがいなければリターンが直に戻る)

1.3 AcceptTCPConnection.c #include <stdio.h> /* printf()用 */ #include <sys/socket.h> /* accept()用 */ #include <arpa/inet.h> /* sockaddr_inとinet_ntoa()用 */ void DieWithError(char *errorMessage); /* エラー処理関数 */ int AcceptTCPConnection(int servSock) { int clntSock; /* クライアントソケット識別子 */ struct sockaddr_in echoClntAddr; /* クライアントアドレス */ unsigned int clntLen; /* クライアントのアドレス構造体の長さ */ /* 入出力パラメータのサイズを設定 */ clntLen = sizeof(echoClntAddr); /* クライアントからの接続待ち */ if ((clntSock = accept(servSock, (struct sockaddr *) &echoClntAddr, &clntLen)) < 0) DieWithError("accept() failed"); /* clntSockはクライアントに接続 */ printf("Handling client %s\n", inet_ntoa(echoClntAddr.sin_addr)); return clntSock; } cast

1.4 クライアント毎にスレッド作成 スレッドの利点 スレッドの欠点 TCPEchoServer-Thread.c 1.4 クライアント毎にスレッド作成 スレッドの利点 同一プロセスの中で複数のタスクを実行できるため、(プロセスの)コピー時間が不要である。 コンピュータ・リソース(メモリ、スタック、ファイル/ソケット識別子)の消費を少なく出来る。 スレッド間の情報交換が容易である。 スレッドの欠点 子プロセスの制御(kill等)はコマンドラインから可能であるが、スレッドの制御は出来ない。 TCPEchoServer-Thread.c プログラムの大部分はTCPEchoServer-Fork.cと同じ。 クライアント サーバ クライアント サーバ (接続要求) sock servSock connect(sock,…) accept(servSock,…) クライアント サーバ (接続) servSock clntSock sock pthread_create() クライアント サーバ (接続) servSock スレッド clntSock sock socketは複製されないのでclose()が不要

1.5 TCPEchoServer-Thread.c #include “TCPEchoServer.h”    /* TCP エコーサーバ用 */ #include <pthread.h>       /* POSIXスレッド用 */ void *ThreadMain(void *arg); /* クライアントスレッドに渡す引数構造体 */ struct ThreadArgs { int clntSock; /* クライアントソケット識別子 */ }; int main(int argc, char *argv[]) int servSock; /* サーバ用ソケット識別子 */ int clntSock; /* クライアント用ソケット識別子 */ unsigned short echoServPort; /* サーバポート番号 */ pthread_t threadID; /* pthread_create()からのスレッドID */ struct ThreadArgs *threadArgs; /* 引数構造体ポインタ */ if (argc != 2) /* 引数の数が正しいかチェック */ fprintf(stderr,"Usage: %s <SERVER PORT>\n", argv[0]); exit(1); }   /* 第一引数はローカルポート番号 */ echoServPort = atoi(argv[1]); servSock = CreateTCPServerSocket(echoServPort); for (;;) /* 永遠に繰返す */ { clntSock = AcceptTCPConnection(servSock); /* クライアント引数用にメモリを確保 */ if ((threadArgs = (struct ThreadArgs *) malloc(sizeof(struct ThreadArgs)))  == NULL) DieWithError("malloc() failed"); threadArgs -> clntSock = clntSock; /* クライアントスレッド作成 */ if (pthread_create(&threadID, NULL, ThreadMain, (void *) threadArgs) != 0) DieWithError("pthread_create() failed"); printf("with thread %ld\n", (long int) threadID); } /* この部分には到達しない */ void *ThreadMain(void *threadArgs) int clntSock; /* クライアントのソケット識別子 */ /* 戻り時、スレッドリソースの開放 */ pthread_detach(pthread_self()); /* ソケットのファイル記述子を引数から取り出す */ clntSock = ((struct ThreadArgs *) threadArgs) -> clntSock; free(threadArgs); /* 引数に割当てられたメモリ開放 */ HandleTCPClient(clntSock); return (NULL); 動的メモリ割当(予めサイズが予測出来ない場合、要求発生時にメモリ確保) 自身のスレッドIDを得る pthread_join()しなくても終了時リソース開放 malloc()で確保したメモリ領域を解放する サーバソケットを作成し接続要求待ち(listen())までを行う関数

1.6 制限付マルチタスク プロセス(スレッド)数の制限 制限付マルチタスクサーバ 1.6 制限付マルチタスク サーバへのアクセス急増やDoS攻撃に備える プロセス(スレッド)数の制限 プロセス(スレッド)数の増加によるOS負荷(プロセス間スケジューリングやコンテキストスイッチ)の増加を抑える。 制限付マルチタスクサーバ 接続待ちサーバプロセスを設定された数だけ予め作る。 処理中でないプロセスがaccept()を実行し接続を確立する。 各プロセスはクライアントからの要求を処理し続ける(プロセスの生成と削除は発生ない)。 サーバ 親 子1 子2 カーネル クライアント fork() fork() exit() connect() accept() connect() 全ての子プロセスが処理中の場合accept()しない。一つの子プロセスの処理が終了した時点でaccept()する。 accept() connect() close() close() accept()

1.7 TCPEchoServer-ForkN.c #include "TCPEchoServer.h" void ProcessMain(int servSock); /* 子のメインプログラム */ int main(int argc, char *argv[]) { int servSock; /* サーバ用ソケット記述子*/ unsigned short echoServPort; /* サーバのポート番号 */ pid_t processID; /* プロセスID */ unsigned int processLimit; /* 作成するプロセス数 */ unsigned int processCt; /* プロセスカウンタ */ echoServPort = atoi(argv[1]); /* 第1引数はローカルポート */ processLimit = atoi(argv[2]); /* 第2引数は子プロセス数*/ servSock = CreateTCPServerSocket(echoServPort); for (processCt=0; processCt < processLimit; processCt++) /* 子プロセスのforkとエラー報告 */ if ((processID = fork()) < 0) DieWithError("fork() failed"); else if (processID == 0) /* 子プロセスの場合 */ ProcessMain(servSock); exit(0); } void ProcessMain(int servSock) { int clntSock;/* クライアントコネクションのソケット記述子 */ for (;;) /* 永遠に繰返す */ clntSock = AcceptTCPConnection(servSock); printf("with child process: %d\n", (unsigned int) getpid()); HandleTCPClient(clntSock); } 次のconnect要求 を受け付ける エコー処理を実施する 処理中に到着するconnect要求は他のプロセスが処理するか待たせる 作成する子の数はprocessLimit 親は子を作成して終了する

宿題14 子1 子2 クライアント カーネル hw14.c :TCPEchoServer-ForkN.cの中のHandleTCPClient(clntSock);の直後にsleep(10);を加えたプログラム。 作成する子プロセス数を2個としてhw14を実行し、TCPEchoClientから連続3回エコー要求を出した場合、エコーの戻り時間がどのようになるか観察せよ。 psコマンドを使ってプロセス数を観測せよ。 表紙に氏名と学籍番号を書く 本文にプログラムを書く プログラムの実行結果を書く 実施した内容を説明する文章を書く レポートの締切は次の週の水曜日18:00 connect() accept() 受信データ=0 TCP close sleep(10) connect() accept() connect() 待ち行列に並んで待つ 10秒スリープ 待ち行列中の 接続要求を 子1が受付ける accept()