UNP学習ノート(第13章デーモンプロセスとinetdスーパーサーバ)
19560 ワード
デーモンプロセスについてapueのノートを表示できますhttp://www.cnblogs.com/runnyu/p/4645046.html
daemon_init関数
次はdaemonという名前でInit関数は、通常サーバプログラムから呼び出すことで、通常のプロセスをデーモンプロセスに変更できます.
View Code
デーモンとして実行される時間取得サーバプログラム
View Code
inetdデーモン
典型的なUNIXシステムには、FTP、Telnet、Rlogin、TFTPなどのクライアント要求の到着を待つだけの多くのサーバが存在する可能性がある.
以前は、これらのサービスはすべて1つのプロセスに関連付けられており、各プロセスはほぼ同じ起動タスクを実行していました.このモデルには、次の2つの問題があります.
1.これらのデーモンプロセスには、ほとんど同じ起動コードが含まれています.
2.各デーモン・プロセスは、プロセス・テーブル内でテーブル・アイテムを占有し、ほとんどの時間をスリープ状態にします.
4.3 BSDバージョンのTCPまたはUDPベースのサーバは、inetdデーモンプロセスを使用して上記の2つの問題を解決できます.
1.通常のデーモンプロセスのほとんどの起動詳細をinetdで処理することによって、デーモンプロセスの作成を簡略化する.
2.単一プロセス(inetd)は、各サービスのプロセスの代わりに、複数のサービスに対して外来の顧客要求を待つことができる.
inetdプロセスはdaemon_Init関数の説明のテクニックは自分を守護プロセスに変えます.
次に、自分のプロファイルを読み込み、処理します.通常は/etc/inetd.confのプロファイルは、このスーパーサーバがどのサービスを処理するか、および1つのサービス要求が到着したときにどのようにするかを決定します.このファイルの各行に含まれるフィールドは、次の図のようになります.
次はinetd.confファイルの例としてのいくつかの行:
次にinetdデーモンのワークフローを示します
1.起動時に/etc/inetdを読み込む.confファイルは、ファイルで指定したサービスごとに適切なタイプのソケットを作成します.新しく作成された各ソケットは、select呼び出しによって使用される記述子に追加されます.
2.ビット各ソケットはbindを呼び出し、対応するサーバをバンドルする周知のポートとプロビジョニングアドレスを指定する.ポート番号はgetservbynameで取得されます.
3.各TCPソケットについて、listenを呼び出して外部からの接続要求を受信する.UDPソケットについては、この手順は実行されません.
4.すべてのソケットを作成した後、selectを呼び出して、いずれかのソケットが読み取り可能になるのを待つ.
5.selectがソケットが読み取り可能であることを示すと、ソケットがTCPソケットであり、サーバのwait-flag値がnowaitである場合、acceptを呼び出してこの新しい接続を受け入れる.
6.inetdデーモンはfork派生プロセスを呼び出し、サブプロセスによってサービス要求を処理する.(サブプロセスはまず端末から離れ、execを呼び出して対応するserver-programフィールドで指定されたプログラムを実行して要求を具体的に処理する)
7.ステップ5でselectがバイトストリームソケットを返す場合、親プロセスは接続ソケットを閉じる必要があります(標準コンカレントサーバのように).親プロセスは、次の読み取り可能ソケットになるまでselectを再度呼び出します.
daemon_inetd関数
以下にdaemonという名前を示します.inetdの関数で、inetdによって起動された既知のサーバプログラムで使用できます.
View Code
とdaemon_Initに比べて、すべてのデーモン化ステップはinetdによって開始時に実行されました.この関数のタスクは、エラー処理関数にdaemon_を設定するだけです.procフラグ、openlogを呼び出します
次にinetdがデーモンとして起動する時間取得サーバプログラムを示す
View Code
すべてのソケット作成コードが消えていることがわかります.これらのステップはinetdによって実行されます.
この例のプログラムを実行するには、まず、/etc/servicesファイルに下りて追加するように、本サービスに名前とポートを付けます.
次に/etc/inetdに下りを加える.confファイル:
次にinetdにSIGHUP信号を送信し、プロファイルを再読み込みするように通知します.
次にnetstatコマンドを実行して、inetdがTCPポート9999にリスニングソケットを作成したことを検証します.
daemon_init関数
次はdaemonという名前でInit関数は、通常サーバプログラムから呼び出すことで、通常のプロセスをデーモンプロセスに変更できます.
1 #include "unp.h"
2 #include
3
4 #define MAXFD 64
5
6 extern int daemon_proc; /* defined in error.c */
7
8 int
9 daemon_init(const char *pname, int facility)
10 {
11 int i;
12 pid_t pid;
13
14 if ( (pid = Fork()) < 0)
15 return (-1);
16 else if (pid)
17 _exit(0); /* parent terminates */
18
19 /* child 1 continues... */
20
21 if (setsid() < 0) /* become session leader */
22 return (-1);
23
24 Signal(SIGHUP, SIG_IGN);
25 if ( (pid = Fork()) < 0)
26 return (-1);
27 else if (pid)
28 _exit(0); /* child 1 terminates */
29
30 /* child 2 continues... */
31
32 daemon_proc = 1; /* for err_XXX() functions */
33
34 chdir("/"); /* change working directory */
35
36 /* close off file descriptors */
37 for (i = 0; i < MAXFD; i++)
38 close(i);
39
40 /* redirect stdin, stdout, and stderr to /dev/null */
41 open("/dev/null", O_RDONLY);
42 open("/dev/null", O_RDWR);
43 open("/dev/null", O_RDWR);
44
45 openlog(pname, LOG_PID, facility);
46
47 return (0); /* success */
48 }
View Code
デーモンとして実行される時間取得サーバプログラム
1 #include "unp.h"
2 #include
3
4 int
5 main(int argc, char **argv)
6 {
7 int listenfd, connfd;
8 socklen_t addrlen, len;
9 struct sockaddr *cliaddr;
10 char buff[MAXLINE];
11 time_t ticks;
12
13 if (argc < 2 || argc > 3)
14 err_quit("usage: daytimetcpsrv2 [ ] ");
15
16 daemon_init(argv[0], 0);
17
18 if (argc == 2)
19 listenfd = Tcp_listen(NULL, argv[1], &addrlen);
20 else
21 listenfd = Tcp_listen(argv[1], argv[2], &addrlen);
22
23 cliaddr = Malloc(addrlen);
24
25 for ( ; ; ) {
26 len = addrlen;
27 connfd = Accept(listenfd, cliaddr, &len);
28 err_msg("connection from %s", Sock_ntop(cliaddr, len));
29
30 ticks = time(NULL);
31 snprintf(buff, sizeof(buff), "%.24s\r
", ctime(&ticks));
32 Write(connfd, buff, strlen(buff));
33
34 Close(connfd);
35 }
36 }
View Code
inetdデーモン
典型的なUNIXシステムには、FTP、Telnet、Rlogin、TFTPなどのクライアント要求の到着を待つだけの多くのサーバが存在する可能性がある.
以前は、これらのサービスはすべて1つのプロセスに関連付けられており、各プロセスはほぼ同じ起動タスクを実行していました.このモデルには、次の2つの問題があります.
1.これらのデーモンプロセスには、ほとんど同じ起動コードが含まれています.
2.各デーモン・プロセスは、プロセス・テーブル内でテーブル・アイテムを占有し、ほとんどの時間をスリープ状態にします.
4.3 BSDバージョンのTCPまたはUDPベースのサーバは、inetdデーモンプロセスを使用して上記の2つの問題を解決できます.
1.通常のデーモンプロセスのほとんどの起動詳細をinetdで処理することによって、デーモンプロセスの作成を簡略化する.
2.単一プロセス(inetd)は、各サービスのプロセスの代わりに、複数のサービスに対して外来の顧客要求を待つことができる.
inetdプロセスはdaemon_Init関数の説明のテクニックは自分を守護プロセスに変えます.
次に、自分のプロファイルを読み込み、処理します.通常は/etc/inetd.confのプロファイルは、このスーパーサーバがどのサービスを処理するか、および1つのサービス要求が到着したときにどのようにするかを決定します.このファイルの各行に含まれるフィールドは、次の図のようになります.
次はinetd.confファイルの例としてのいくつかの行:
次にinetdデーモンのワークフローを示します
1.起動時に/etc/inetdを読み込む.confファイルは、ファイルで指定したサービスごとに適切なタイプのソケットを作成します.新しく作成された各ソケットは、select呼び出しによって使用される記述子に追加されます.
2.ビット各ソケットはbindを呼び出し、対応するサーバをバンドルする周知のポートとプロビジョニングアドレスを指定する.ポート番号はgetservbynameで取得されます.
3.各TCPソケットについて、listenを呼び出して外部からの接続要求を受信する.UDPソケットについては、この手順は実行されません.
4.すべてのソケットを作成した後、selectを呼び出して、いずれかのソケットが読み取り可能になるのを待つ.
5.selectがソケットが読み取り可能であることを示すと、ソケットがTCPソケットであり、サーバのwait-flag値がnowaitである場合、acceptを呼び出してこの新しい接続を受け入れる.
6.inetdデーモンはfork派生プロセスを呼び出し、サブプロセスによってサービス要求を処理する.(サブプロセスはまず端末から離れ、execを呼び出して対応するserver-programフィールドで指定されたプログラムを実行して要求を具体的に処理する)
7.ステップ5でselectがバイトストリームソケットを返す場合、親プロセスは接続ソケットを閉じる必要があります(標準コンカレントサーバのように).親プロセスは、次の読み取り可能ソケットになるまでselectを再度呼び出します.
daemon_inetd関数
以下にdaemonという名前を示します.inetdの関数で、inetdによって起動された既知のサーバプログラムで使用できます.
1 #include "unp.h"
2 #include
3
4 extern int daemon_proc; /* defined in error.c */
5
6 void
7 daemon_inetd(const char *pname, int facility)
8 {
9 daemon_proc = 1; /* for our err_XXX() functions */
10 openlog(pname, LOG_PID, facility);
11 }
View Code
とdaemon_Initに比べて、すべてのデーモン化ステップはinetdによって開始時に実行されました.この関数のタスクは、エラー処理関数にdaemon_を設定するだけです.procフラグ、openlogを呼び出します
次にinetdがデーモンとして起動する時間取得サーバプログラムを示す
1 #include "unp.h"
2 #include
3
4 int
5 main(int argc, char **argv)
6 {
7 socklen_t len;
8 struct sockaddr *cliaddr;
9 char buff[MAXLINE];
10 time_t ticks;
11
12 daemon_inetd(argv[0], 0);
13
14 cliaddr = Malloc(sizeof(struct sockaddr_storage));
15 len = sizeof(struct sockaddr_storage);
16 Getpeername(0, cliaddr, &len);
17 err_msg("connection from %s", Sock_ntop(cliaddr, len));
18
19 ticks = time(NULL);
20 snprintf(buff, sizeof(buff), "%.24s\r
", ctime(&ticks));
21 Write(0, buff, strlen(buff));
22
23 Close(0); /* close TCP connection */
24 exit(0);
25 }
View Code
すべてのソケット作成コードが消えていることがわかります.これらのステップはinetdによって実行されます.
この例のプログラムを実行するには、まず、/etc/servicesファイルに下りて追加するように、本サービスに名前とポートを付けます.
mydaytime 9999/tcp
次に/etc/inetdに下りを加える.confファイル:
mydaytime stream tcp nowait andy /home/andy/daytimetcpsrv3 daytimetcpsrv3
次にinetdにSIGHUP信号を送信し、プロファイルを再読み込みするように通知します.
次にnetstatコマンドを実行して、inetdがTCPポート9999にリスニングソケットを作成したことを検証します.