fork() を使うプログラムを pthread を使って書き換える

並列分散ソフトウェア

                                       電子・情報工学系
                                       新城 靖
                                       <yas@is.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.hlla.is.tsukuba.ac.jp/~yas/sie/pdsoft-2000/2001-01-18 fork-pthread.html
あるいは、次のページから手繰っていくこともできます。
http://www.hlla.is.tsukuba.ac.jp/~yas/sie/
http://www.is.tsukuba.ac.jp/~yas/index-j.html
http://www.hlla.is.tsukuba.ac.jp/~yas/index-j.html

■fork() を使うプログラムを pthread を使って書き換える

◆echo-server-fork(forkを使ったプログラム)

TCP/IP のポート番号 7 (echo) では、受け取ったデータをそのまま返すサー ビスを提供している。以下は、これと同じような機能を提供するサーバである。 複数の接続先(クライアント)の要求を同時に処理するために、クライアント ごとに fork() システム・コールで専用の子プロセスを作っている。


----------------------------------------------------------------------
 1: 
 2: /*
 3:         echo-server-fork.c -- 受け取った文字列をそのまま返すサーバ(fork版)
 4:         http://www.hlla.is.tsukuba.ac.jp/~yas/sie/pdsoft-2000/examples/echo-server-fork.c
 5:         $Header: /home/hlla/yas/cvs/sie-pdsoft-2000-examples/echo-server-fork.c,v 1.1 2001/01/06 22:05:53 yas Exp $
 6:         Start: 1997/06/09 19:46:40
 7: */
 8: #include <stdio.h>
 9: #include <sys/types.h>  /* socket(), time() */
10: #include <sys/socket.h> /* socket() */
11: #include <netinet/in.h> /* struct sockaddr_in */
12: 
...
20: main( int argc, char *argv[] )
21: {
22:     int portno ;
23:         if( argc >= 3 )
24:         {
25:             fprintf( stdout,"Usage: %s host port\n",argv[0] );
26:             exit( -1 );
27:         }
28:         if( argc == 2 )
29:             portno = atoi( argv[1] );
30:         else
31:             portno = getuid();
32:         echo_server( portno );
33: }
34: 
35: void echo_server( int portno )
36: {
37:     int acc,com ;
38:     pid_t child_pid ;
39:         acc = tcp_acc_port( portno );
40:         if( acc<0 )
41:             exit( -1 );
42:         print_host_port( portno );
43:         while( 1 )
44:         {
45:             if( (com = accept( acc,0,0 )) < 0 )
46:             {
47:                 perror("accept");
48:                 exit( -1 );
49:             }
50:             tcp_peeraddr_print( com );
51:             if( (child_pid=fork()) > 0 ) /* parent */
52:             {
53:                 close( com );
54:             }
55:             else if( child_pid == 0 )
56:             {
57:                 close( acc );
58:                 echo_reply( com );
59:                 printf("[%d,%d] connection closed.\n",getpid(),com );
60:                 close( com );
61:                 exit( 0 );
62:             }
63:         }
64: }
65: 
66: void echo_reply( int com )
67: {
68:     char buf[BUFSIZ] ;
69:     int rcount ;
70:     int wcount ;
71: 
72:         while( (rcount=read(com,buf,BUFSIZ)) > 0 )
73:         {
74:             if( (wcount=writen(com,buf,rcount))!= rcount )
75:             {
76:                  perror("write");
77:                  exit( 1 );
78:             }
79:             printf("[%d,%d] ",getpid(),com );
80:             fflush( stdout );
81:             write( 1, buf, rcount );
82:         }
83: }
...
----------------------------------------------------------------------

実行例。

サーバ側。サーバは、終了しないので、最後に、^CDel を押して、割り込みを掛けて終了させる。


----------------------------------------------------------------------
% ./echo-server-fork  [←]
run telnet adonis1 1231 
[4535,4] connection from 130.158.86.1:2368
[4539,4] 012
[4535,4] connection from 130.158.86.9:15629
[4542,4] abc
[4542,4] def
[4542,4] connection closed.
[4539,4] 345
[4539,4] connection closed.
^C
% []
----------------------------------------------------------------------
クライアント側(その1)。
----------------------------------------------------------------------
% telnet adonis1 1231 [←]
Trying 130.158.86.1...
Connected to adonis1.
Escape character is '^]'.
012[←]
012
345[←]
345
^]
telnet> quit[←]
Connection closed.
% []
----------------------------------------------------------------------
クライアント側(その2)。
----------------------------------------------------------------------
% % telnet adonis1 1231 [←]
Trying 130.158.86.1...
Connected to adonis1.
Escape character is '^]'.
abc[←]
abc
def[←]
def
^]
telnet> quit[←]
Connection closed.
% []
----------------------------------------------------------------------

◆echo-server-pthread(pthreadを使ったプログラム)

fork() の代わりに、Pthread を使う。

----------------------------------------------------------------------
   1: 
   2: /*
   3:         echo-server-fork.c -- 受け取った文字列をそのまま返すサーバ(pthread版)
   4:         http://www.hlla.is.tsukuba.ac.jp/~yas/sie/pdsoft-2000/examples/echo-server-pthread.c
   5:         $Header: /home/hlla/yas/cvs/sie-pdsoft-2000-examples/echo-server-pthread.c,v 1.1 2001/01/06 22:05:53 yas Exp $
   6:         <-- ~yas/syspro1-1998/ipc/RCS/echo-server-fork.c,v 1.5 1997/06/09 21:28:27 yas Exp $
   7:         Start: 1997/06/09 19:46:40
   8: */
   9: #include <stdio.h>
  10: #include <sys/types.h>  /* socket(), time() */
  11: #include <sys/socket.h> /* socket() */
  12: #include <netinet/in.h> /* struct sockaddr_in */
  13: #include <pthread.h>
...
  22: main( int argc, char *argv[] )
  23: {
  24:     int portno ;
  25:         if( argc >= 3 )
  26:         {
  27:             fprintf( stdout,"Usage: %s host port\n",argv[0] );
  28:             exit( -1 );
  29:         }
  30:         if( argc == 2 )
  31:             portno = atoi( argv[1] );
  32:         else
  33:             portno = getuid();
  34:         echo_server( portno );
  35: }
  36: 
  37: void echo_server( int portno )
  38: {
  39:     int acc,com ;
  40:     pthread_t worker ;
  41:         acc = tcp_acc_port( portno );
  42:         if( acc<0 )
  43:             exit( -1 );
  44:         print_host_port( portno );
  45:         while( 1 )
  46:         {
  47:             if( (com = accept( acc,0,0 )) < 0 )
  48:             {
  49:                 perror("accept");
  50:                 exit( -1 );
  51:             }
  52:             tcp_peeraddr_print( com );
  53:             if( pthread_create( &worker, NULL, (void *)echo_reply, (void *)com)
  54:                 != 0 )
  55:             {
  56:                 perror("pthread_create()");
  57:                 exit( -1 );
  58:             }
  59:             pthread_detach( worker );
  60:         }
  61: }
  62: 
  63: void echo_reply( int com )
  64: {
  65:     char buf[BUFSIZ] ;
  66:     int rcount ;
  67:     int wcount ;
  68: 
  69:         while( (rcount=read(com,buf,BUFSIZ)) > 0 )
  70:         {
  71:             if( (wcount=writen(com,buf,rcount))!= rcount )
  72:             {
  73:                  perror("write");
  74:                  exit( 1 );
  75:             }
  76:             printf("[%d,%d,%d] ",getpid(),pthread_self(),com );
  77:             fflush( stdout );
  78:             write( 1, buf, rcount );
  79:         }
  80:         printf("[%d,%d,%d] connection closed.\n",getpid(),pthread_self(),com );
  81:         close( com );
  82: }
<以下省略>
----------------------------------------------------------------------

実行例。

サーバ側。サーバは、終了しないので、最後に、^CDel を押して、割り込みを掛けて終了させる。


----------------------------------------------------------------------
% ./echo-server-pthread [←]
run telnet adonis1 1231 
[4509,65536,4] connection from 130.158.86.1:2367
[4509,65537,4] 012
[4509,65536,5] connection from 130.158.86.9:15628
[4509,65538,5] abc
[4509,65538,5] def
[4509,65538,5] connection closed.
[4509,65537,4] 345
[4509,65537,4] connection closed.
^C
% []
----------------------------------------------------------------------
クライアント側(その1)。
----------------------------------------------------------------------
% telnet adonis1 1231 [←]
Trying 130.158.86.1...
Connected to adonis1.
Escape character is '^]'.
012[←]
012
345[←]
345
^]
telnet> quit[←]
Connection closed.
% []
----------------------------------------------------------------------
クライアント側(その2)。
----------------------------------------------------------------------
% % telnet adonis1 1231 [←]
Trying 130.158.86.1...
Connected to adonis1.
Escape character is '^]'.
abc[←]
abc
def[←]
def
^]
telnet> quit[←]
Connection closed.
% []
----------------------------------------------------------------------

↑[もどる] [1月18日] [1月25日] [2月1日]
Last updated: 2001/01/18 13:08:29
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>