1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[メモ] UNIXの子プロセスの標準入力にパイプでデータを渡したい

Posted at

####やりたいこと
UNIXで子プロセスを起動して任意のコマンドをexecで実行したい。
そのコマンドの標準入力に対してパイプでデータを渡したい。

####プログラム例
子プロセスを起動してcatを引数なしで呼ぶ。catは引数なしなので標準入力を待つ。
親プロセスからは"Hello, World."をパイプで流す。

つまり、shellで
$ echo "Hello, World" | cat
を実行したのと同じ。

コード

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(void)
{
	int     fd[2];

	// pipe を作成する。fd[0]は受信用、fd[1]は送信用
	pipe(fd);

	// プロセス生成
	switch(fork()) {
	case -1:
		perror("fork");
		return 1;
	case 0: // 子プロセス
		{
			close(fd[1]); // 送信用fdを閉じる

			// 受信用fdをstdinのfdに上書きする
			if (dup2(fd[0], STDIN_FILENO)==-1) {
				perror("cannot redirect stdin"); 
				exit(1); 
			}
			close(fd[0]); // 受信用fdは複数いらないので閉じる

			// cat を実行する
			execlp("cat", "cat", NULL) ;

			perror("execlp: failed."); // ここに来たということはexeclpに失敗した
		}
	default:
		{ // 親プロセス
			const char send_str[] = "Hello, World.\n";

			close(fd[0]); // 受信側fdを閉じる
			write(fd[1], send_str, strlen(send_str)+1);
			close(fd[1]); // 送信後は必ず閉じる ★①

			int status;
			wait(&status);
		}
	}

	return (0);
}

####はまったこと
"Hello, World"は出力されるが、子プロセスが終了しない。

####原因
親プロセスがwrite()後にfd[1]に対してcloseをしていなかった。(上記ソースの★①)
子プロセス側は標準入力をずっと待っている状態だった。

###参考になったもの
http://stackoverflow.com/questions/22245237/execlp-redirect-stdin-in-c

以上。

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?