socketpair
次のように、両方のプロセスを作成する場合にのみ使用できます。
- call
socketpair
- これで、2 つのソケット ファイル記述子 (1 つのパイプの両端) ができました。
- 一方のエンドを親エンドに指定し、もう一方を子エンドに指定します。どちらでもかまいません。選択して、後でそれに固執するだけです
- 呼び出し
fork
- これで 2 つのプロセスができました
fork
ゼロが返された場合、あなたは子供です。親ファイル記述子を閉じ、子記述子を保持し、それをこのプロセスのパイプの終わりとして使用します
fork
ゼロ以外が返された場合、あなたは親です。子ファイル記述子を閉じ、親ファイル記述子を保持し、それをパイプの終わりとして使用します
- 2 つのプロセスがあり、それぞれが同じパイプの異なる端を表す 1 つのファイル記述子を持っています。両方のプロセスが同じプログラムを実行していることに注意してください
fork
。親がそのwrite
ソケットで呼び出すと、子はソケットからそのデータを読み取ることができ、その逆も同様です。
コードへの直訳は次のとおりです。
void child(int socket) {
const char hello[] = "hello parent, I am child";
write(socket, hello, sizeof(hello)); /* NB. this includes nul */
/* go forth and do childish things with this end of the pipe */
}
void parent(int socket) {
/* do parental things with this end, like reading the child's message */
char buf[1024];
int n = read(socket, buf, sizeof(buf));
printf("parent received '%.*s'\n", n, buf);
}
void socketfork() {
int fd[2];
static const int parentsocket = 0;
static const int childsocket = 1;
pid_t pid;
/* 1. call socketpair ... */
socketpair(PF_LOCAL, SOCK_STREAM, 0, fd);
/* 2. call fork ... */
pid = fork();
if (pid == 0) { /* 2.1 if fork returned zero, you are the child */
close(fd[parentsocket]); /* Close the parent file descriptor */
child(fd[childsocket]);
} else { /* 2.2 ... you are the parent */
close(fd[childsocket]); /* Close the child file descriptor */
parent(fd[parentsocket]);
}
exit(0); /* do everything in the parent and child functions */
}
これは単なるサンプル コードであることに注意してください。エラー チェックと実用的なストリーム プロトコルはすべて省略しています。
2 つの別個のプログラムが通信する必要がある場合 (たとえば、clientと呼ばれる実行可能ファイルとserverと呼ばれる実行可能ファイルがある場合)、このメカニズムを使用することはできません。代わりに、次のことができます。
- UNIX ソケットを使用します (1 つのホスト上の IPC パイプはファイル名で識別されます。これは、クライアントとサーバーが同じマシンで実行されている場合にのみ機能します)。
- またはTCP / IPソケットを使用します(IPアドレスとポートがパイプを識別し、クライアントとサーバーが異なるマシン上にある場合があります)
特にソケットが必要なく、クライアントとサーバーを同じマシンで実行する必要がある場合は、共有メモリまたはメッセージ キューを使用することもできます。