スレッド型並行サーバ スレッド型並行サーバ 並行サーバのセッションシーケンス 並行サーバ (TCPEchoServer-Thread.c) スレッド生成によるメモリ領域の状況 TCPEchoServer-Thread.c main() int CreateTCPServerSocket(unsigned short port) int AcceptTCPConnection(int servSock) void HandleTCPClient(int clntSocket) forkのシステムコールとスレッドのシステムコール pthread_create スレッドを生成する pthread_join スレッドが終了するのを待つ プログラム比較(例: forkの目覚まし時計) プログラム比較(例:スレッドの目覚まし時計) スレッド型並行サーバ 並行サーバのセッションシーケンス クライアント サーバ クライアント サーバ (接続要求) sock servSock connect(sock,…) クライアント accept(servSock,…) サーバ (接続) sock servSock clntSock pthread_create() クライアント サーバ (データ通信) sock servSock スレッド clntSock スレッド型並行サーバ 並行サーバ (TCPEchoServer-Thread.c) スレッドの利点 同一プロセスの中で複数のタスク(独立したスタック領 域)を実行できるため、(プロセスの)コピー時間が不要 コンピュータリソース(コード領域、変数領域、ファイル /ソケット識別子)を共有し、リソースの消費を少なく出 来る スレッドの欠点 子プロセスの制御(kill等)はコマンドラインから可能だ が、個別スレッドの制御は出来ない スレッド型並行サーバ(TCPEchoServer-Thread.c) プログラムの大部分は、 fork型並行サーバ (TCPEchoServer-Fork.c)と同じ スレッド型並行サーバ スレッド生成によるメモリ領域の状況 スタック領域 変数領域 プログラム コード領域 スレッドは、同一プロセス のプログラムコード領域と 変数領域の双方を共有、 スタックのみが独立 スレッド型並行サーバ TCPEchoServer-Thread.c main() #include “TCPEchoServer.h” #include <pthread.h> /* TCP エコーサーバ用 */ /* 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); スレッド型並行サーバ TCPEchoServer-Thread.c main() 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); } /* この部分には到達しない */ } 自身のスレッド IDを得る void *ThreadMain(void *threadArgs) { int clntSock; /* クライアントのソケット識別子 */ /* 戻り時、スレッドリソースの開放 */ pthread_detach(pthread_self()); /* ソケットのファイル記述子を引数から取り出す */ clntSock = ((struct ThreadArgs *) threadArgs) -> clntSock; free(threadArgs); /* 引数に割当てられたメモリ開放 */ HandleTCPClient(clntSock); return (NULL); malloc() ⇔ free() } スレッド型並行サーバ int CreateTCPServerSocket(unsigned short port) スレッド型並行サーバ int AcceptTCPConnection(int servSock) スレッド型並行サーバ void HandleTCPClient(int clntSocket) スレッド型並行サーバ forkのシステムコールとスレッドのシステムコール forkシステムコール 子プロセスが親プロセスの情報を殆ど複製するために、 処理が重い。 親プロセスや複製された他のプロセスとの情報交換に、 パイプやプロセス間通信を使わなければいけない スレッドのシステムコール 同一プロセスの中で、複数のスレッドが生成できる。 同一プロセスの中で、スレッド間の情報交換に変数を直 接利用できる。 スレッドを使えば、並行して行うプログラムが容易に書く ことが出来る。 スレッドを使う場合、main関数が終了すると全てのスレッ ドが終了する スレッド型並行サーバ pthread_create スレッドを生成する プロセスのfork()に対応 pthread_create スレッドを生成する インクルードファイル #include <pthread.h> 書式 int pthread_create(pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg); 戻値 成功時 0 (スレッド識別子が*threadに設定) 失敗時 0以外の値 *thread *attr *start_routine *arg スレッド識別子を格納する変数 スレッドの属性、 NULL: デフォルトの属性 スレッドが実行する関数 スレッドが実行する関数の引数 スレッド型並行サーバ pthread_join スレッドが終了するのを待つ プロセスのwait()に対応 pthread_join スレッドが終了するのを待つ インクルードファイル #include <pthread.h> 書式 int pthread_join(pthread_t th, void **thread_return); 戻値 成功時 0 (thをthread_returnに設定) 失敗時 0以外の値 th thread_return 終了待ちスレッド スレッドの戻り値 スレッド型並行サーバ プログラム比較(例: forkの目覚まし時計) #include <stdio.h> #include <stdlib.h> #include <unistd.h> Int main(int argc,char *argv[]) { int dep_time; dep_time=atoi(argv[1])*60-300; if (fork()==0) { //子プロセスの生成 sleep(dep_time); fprintf(stderr,”Leave in 5 min\n”); } return EXIT_SUCCESS; } $ gcc lv.c –o lv $./lv 30 $ $ Leave in 5 min スレッド型並行サーバ プログラム比較(例: スレッドの目覚まし時計) #include #include #include #include <pthread.h> <stdio.h> <stdlib.h> <unistd.h> int main(int argc, char *argv[]) { pthread_t thread; void *print_message(void *args); $ gcc lv2.c -o lv2 -lpthread $ ./lv2 30 You have to leave in 5 minutes $ pthreadライブラリ が必要 pthread_create(&thread, NULL, print_message, argv[1]); pthread_join(thread,NULL); return EXIT_SUCCESS; } void *print_message(void *args) { int dep_time; dep_time=atoi(args)*60-300; sleep(dep_time); fprintf(stderr, "You have to leave in 5 minutes\n"); return NULL; }
© Copyright 2024 ExpyDoc