• ベストアンサー

パイプのプログラム

ここまでプログラムはできているのですが、親プロセスと子プロセスのところが分かりません。どなたかお願いします! XXX%a.out a|b のように入力して、コマンドaとコマンドbを、並列処理するプログラムを作っています。 なお、コマンドの実行は execl("/bin/コマンド名",コマンド名,NULL) というシステムコールを利用します。 パイプの生成およびファイル記述子の複製は、 pipe(pipefd)、 dup(pipefd[0])またはdup(pipefd[1]) のシステムコールを用います。 プログラム #include<stdio.h> #include<string.h> main(int argc,char *argv[]) { int pipefd[2],pid; char cmd_a[20]="/bin/"; if(pipe(pipefd)==-1) { perror("pipe error"); exit(1); } if((pid=fork())==-1){ perror("fork error"); exit(1); } if(pid!=0){ /*親プロセス*/ strcat(cmd_a,argv[1]); /*子プロセス*/

質問者が選んだベストアンサー

  • ベストアンサー
  • kei_
  • ベストアンサー率29% (5/17)
回答No.3

まず、pipe() や execv(), fork() などの関数について、 勉強したらどうでしょう?(あとは、close や dup も) 処理としては、#1 さんの書いているように、 親プロセスで、パイプのつなぎかえをしたあと(dup, close)、 コマンド a の呼び出しを行い(exec)、 子プロセスでもパイプをつなぎかえた後、 コマンド b の呼び出しをしたらいいのでは? pipe については Google などの検索サイトで探せばたくさん出てきます。

参考URL:
http://www.google.co.jp/search?num=20&hl=ja&inlang=ja&ie=Shift_JIS&q=pipe+close&btnG=Google+%8C%9F%8D%F5&lr=lang_ja

その他の回答 (2)

回答No.2

> 今日までの課題なのですが、できたらプログラムの中身もお願いできませんか? この課題は、周りの人も分からなくて困っています。 宿題を見ず知らずの誰かにやってもらうおつもりですか?

回答No.1

> 親プロセスと子プロセスのところが分かりません。 って、そこがこのプログラムの肝じゃないですか。 ここまでできていますっていうのも、学校で出た課題そのままという気がします。 親プロセスがaを担当するんだとすると、 標準出力を閉じて、パイプの一方を閉じて、他方をdupして、aを実行 という手順です。子プロセスは、 標準入力を閉じて、親とは反対側のパイプを閉じて、他方をdupして、bを実行 ですね。パイプを閉じるのは念のためなのでしなくてもOKです。

raul-man
質問者

お礼

ありがとうございます。 今日までの課題なのですが、できたらプログラムの中身もお願いできませんか? この課題は、周りの人も分からなくて困っています。

関連するQ&A

  • ls | sort を実行するプログラム

    以下のプログラムはls | sortを実行するプログラムなのですが、出力が2回ずつ出てしまい困っております。以下に実行結果も載せましたので参照ください。 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> main(int argc,char **argv){ int a[2],b[2]; int cint,status; char n; pid_t pid1,pid2; if(pipe(a)==-1){ perror("pipe"); exit(EXIT_FAILURE); } if(pipe(b)==-1){ perror("pipe"); exit(EXIT_FAILURE); } if((pid1 = fork())==-1){ perror("fork"); exit(EXIT_FAILURE); } if((pid2 = fork())==-1){ perror("fork"); exit(EXIT_FAILURE); } //子1 else if(pid1==0){ close(a[0]); close(b[0]); close(b[1]); dup2(a[1],1); close(a[1]); execlp(argv[1],argv[1],(char *)0); } //子2 else if(pid2==0){ close(a[1]); close(b[0]); dup2(a[0],0); dup2(b[1],1); close(a[0]); close(b[1]); execlp(argv[2],argv[2],(char *)0); } //親 else { close(a[0]); close(a[1]); close(b[1]); wait(&status); while((read(b[0],&n,1))==1){ putchar(n); } close(a[0]); } exit(EXIT_SUCCESS); } /*実行結果 $ ./pipesort ls sort 2^31-1.c~ 2^31-1.c~ a*b.c~ a*b.c~ a-z.c a-z.c a-z.c~ a-z.c~ a-z1.c a-z1.c a-z1.c~ a-z1.c~ a.c a.c a.c~ a.c~ a.out a.out a.sp~ a.sp~ a10 a10 */ というように同じファイル名が二度ずつ出力されるのです。これを出力は一度ずつにしたいのですがどのようにすればよいですか?

  • シェルでのパイプの処理の書き方で困ってます

    現段階でのプログラムを載せます (質問に必要な部分を抜粋) #include "自作のヘッダファイル(動作確認済)" void tokun ( char str[], char *chops[], int *flagment , int *pipeflagment, int *pipe, int *num){ char *buf; int i; *pipeflagment = 0; buf = str; for(i=0; i <= SIZE ; i++){ if((chops[i] = strtok(buf," \t")) == NULL) break; if( *chops[i] == '|' ){ *pipeflagment = 1; *pipe = i + 1; *num = i; } buf = NULL; } if( *chops[i-1] == '&' ){ *flagment = BACK; chops[i-1] = NULL; i--; printf("**Background Mode**\n"); }else{ *flagment = FORE; printf("**Foreground Mode**\n"); } if(i > SIZE){ fprintf(stderr,"Too many args\n"); exit(1); } } int main ( void ){ char prompt[ 64 ] = "> "; char command[ 256 ]; int st, id, j, pipenum, num; char *com[256]; enum proc_flag flag; int pipeflag ; int out; int pipe_fd[2]; int child, status; char *buf; pipeflag = 0; fprintf(stderr, "%s", prompt); while (gets(command) != NULL){ if( command == "quit" ){ kill(0, SIGKILL); } buf = command; tokun(command, com, &flag, &pipeflag, &pipenum, &num); //pipe部分の記述開始 if( pipeflag == 1){ com[num] = NULL; if(pipe(pipe_fd) < 0){ perror("pipe"); exit(1); } if((child = fork()) < 0){ perror("fork"); exit(1); } if(child) { /* parent process */ close(pipe_fd[1]); dup2(pipe_fd[0], STDIN); execvp (com[pipenum], com); close(pipe_fd[0]); if(wait(&status) < 0){ perror("wait"); exit(1); } }else { /* child process */ close(pipe_fd[0]); dup2(pipe_fd[1], STDOUT); execvp (com[0], com); // 通信の終了を子プロセスに通知 close(pipe_fd[1]); } } //pipe部分の記述終了 if((id = fork ()) == 0){ if( execvp(com[0], com) == (-1)){ exit(1); } }else { if( flag == BACK ){ waitpid(-1, NULL, WNOHANG); fprintf(stderr, "%s", prompt); }else { wait(&st); fprintf(stderr, "%s", prompt); } } } return 0; } パイプ部分が作れません・・・。 どうすればいいですか?

  • シェルのプログラム

    以下の項目を実現するプログラムを作っています。 コマンドプロンプトを表示し、キーボードからコマンドを文字列として入力する。入力した文字列を調べ、forkして子プロセスを作る子プロセスで、調べたコマンドをexecする、親プロセスは子プロセスの終了を待って、始めに戻るというプログラムです。自分なりにあれこれ作ったのが下のです。 #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> void read_command(char *command, char *p) { static char buf[100]; fgets(buf, 100, stdin); sscanf(buf, "%s %[\n]", command,p); } int main(void) { pid_t pid; int status; char command[100], p[100]; while (1) { printf("command>"); read_command(command, p); pid = fork(); if (pid < 0) { printf("forkできません\n"); continue; } if (pid != 0) { wait(&status); } else { execve(command, p, 0); } } return 0; } 子プロセスと親プロセスでのforkの仕方が分かりません。 実行したら下のような結果になるようにしたいのですが、できません。 どなたか、教えてください。 $./sh command> ls a.out ・・・・・・

  • 一部コマンドでエラー

    以下のプログラムにパス検索機能を追加しろ。 /bin/lsと入力していたものを、lsだけで実行できるようにする。 そのほかにもdata -Iやgcc -o test test.c、./testを実行可能にする。 と言う課題で、 if(execv(argv[0],argv[])==(-1)){をif(execvp(argv[0],argv)==(-1)){とする方法を聞いたのですが、 gcc -o test test.cを入力すると長文のエラーが出力されます。 どうしたら良いでしょうか? #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> main(int argc, char *argv[]){ int len, pid, st; char *p; int i, sp_flag; static char prompt[64]="> "; char command[256]; printf("%s",prompt); while (fgets(command, 256, stdin) != NULL){ if((len = strlen(command)) == 1)break; command[len-1] = '\0'; p=(char *)&command; sp_flag=0; for(i=0; *p!='\0';p++){ if(sp_flag == 0 && *p!=' '){ argv[i]=p; sp_flag=1; i++; }else if(*p==' '){ *p='\0'; sp_flag=0; } } argv[i]=(char *)0; for(i=0; argv[i]!=(char *)0; i++){ printf("%s\n",argv[i]); } if((pid = fork()) == 0){ if(execv(argv[0],argv)==(-1)){ printf("%s", "exec error.\n"); exit(1);} } else if(pid >= 1){ wait(&st); printf("%s", prompt); } else { perror("fork"); exit(1); } } exit(0); }

  • C言語のシェルプログラミングの課題が分かりません。

    C言語のシェルプログラミングを作れという課題で、以下のように作ったんですが、実行して何度かコマンドを入力した後、exitによって一発で終わらせることができません。どのように書き換えればいいか教えて下さい。 また、他にも書き換えた方がよいと思えるところがあったら是非教えて下さいm(_ _)m #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/wait.h> #include <sys/types.h> #include MAX_ARGS 10 #include MAX_LEN 100 extern char **environ; void child(int argc, char *argv[MAX_ARGS]); int main(void){ int argc, n = 0; int status; char input[MAX_LEN], *argv[MAX_ARGS], *cp; const char *delim = "\t\n"; while (1){ ++n; printf("$ "); fflush(stdout); if(fgets(input, sizeof(input), stdin) == NULL){ break; } cp = input; for(argc = 0; argc < MAX_ARGS; argc++){ if((argv[argc] = strtok(cp, delim)) == NULL) break; cp = NULL; } if(strcmp(argv[0], "exit") == 0){ exit(0); } pid_t pid = fork(); if(pid == -1){ perror("fork"); exit(1); }else if(pid == 0){ child(argc, argv); }else{ wait(&status); } } return 0; } void child(int argc, char *argv[MAX_ARGS]{ execvp(argv[0], argv); }

  • OS論

    #include <stdio.h> #include <unistd.h> main(int artc, char *argv[], char *env[]){ char *newargv[3], str[50]; int pid, pfds[2], rc; pipe(pfds); if((pid=fork()) == 0) { close(fileno(stdout)); dup2(pfds[1], fileno(stdout)); close(pfds[0]); close(pfds[1]); close(fileno(stdin)); newargv[0] = "banner"; newargv[1] = argv[2]; newargv[2] = (void *)NULL; rc = execve("/bin/banner",newargv,env); if(rc != 0){ printf("error\n"); } exit(0); } else { wait((void *)NULL); close(fileno(stdin)); dup2(pfds[0], fileno(stdin)); close(pfds[0]); close(pfds[1]); newargv[0] = "sed"; sprintf(str,"s/#/%s/g",argv[1]); newargv[1] = str; newargv[2] = (void *)NULL; printf("input pfds[0] = %d,output pfds[1] = %d\n", pfds[0], pfds[1]); rc= execve("/usr/ucb/sed",newargv,env); if(rc != 0){ printf("error\n"); } close(fileno(stdout)); exit(0); } } っていうプログラムがあります printf("input pfds[0] = %d,output pfds[1] = %d\n", pfds[0], pfds[1]); のpfds[0]とpfds[1]とはなんの値なんでしょう??

  • LINUXでC言語のプログラミングについて

    私は、現在情報工学科の学生です。現在学校でLINUXの科目を受講しています。私は今まで、学校から出された課題は自分でやってきましたが、この問題だけはどうしても解けず、このような場を借りて、問題のプログラミングについて皆様にご教授をお願いしています。自分でいろいろ調べ、考えてみましたがそれでも自分の知識が足りず、プログラムを作ることができませんでした。プログラムと解説のご教授をお願いします。 OS Linux プログラミング言語 C言語 コンパイル方式 [gcc] *****問題***** #include <manにより調べること> void main(argc, char *argv[]){ int n, fd[2]; char line[MAXLINE]; pid_t pid; if (pipe(fd)<0) exit(1); if ((pid=fork())>0) { /*parent process */ close (fd[0]); write(fd[1], "Hello\n", 6); } else{ /*child process */ close (fd[1]); n = read(fd[0], line, MAXLINE); write (1, line, n);/* write(fileno(stdout), line,n); } else exit(1); /* fork error */ exit (0); } (問題1)上記をもとに親プロセスがキーボードから入力した行をパイプで子プロセスに標準出力ファイルとして送り、子プロセスは標準入力から受けとってスクリーンにエコーバックするようなプログラムを作れ。ヒント:dup2(fd[1],fileno(stdout)), fgets(line, MAXLINE, stdin), fputs(....) (親) (子) キーボード-->| stdin stdout| ---> |stdin stdout|---->ディスプレイ

  • プログラミングの課題でシェルプログラミングが出たのですが・・・全くわけがわからないので助言を…

    先日学校でプログラミングの課題が出たのですが、いきなり説明もなく出されたためにまったく理解ができなくて非常に困っています。 内容はシェルプログラミングでプログラムを実行しろというモノですが、まだプログラミングを始めて幼いものでして、何が何やら理解できていないというのが現状です。 詳しい内容は #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <stdlib.h> #include <string.h> main(int argc, char *argv[]) { int len, pid, st; static char prompt[64]="> "; char command[256]; printf("%s",prompt); while (fgets(command, 256, stdin) != NULL){ if ((len = strlen(command)) == 1) break; command[len-1] = '\0'; if((pid = fork()) == 0) { if (execl(command,command,(char *)0)==(-1)){ printf("%s", "exec error.\n"); exit(1); } } else if(pid >= 1) { wait(&st); printf("%s", prompt); } else { perror("fork"); exit(1); } } exit(0); } というプログラム(自作なのであってるかは…)なのですが、これにはコマンドに引数があると、exec() でエラーになるという欠点があります。また、パス検索機能も指定されていないので、コマンドはフルパスで入力してあります。そこで問題なのですが、パス検索機能を追加するとともに、コマンドに引数があっても、exec() でプログラムが正常に実行できるように改良しろ。という内容の問題です。 上記のようにプログラムを作ることまではできたのですが、その先ができません。なんとかできるようにはできないでしょうか? ぜひ時間のある方回答お願いします。

  • execvpでのcdコマンドについて。

    簡単んなシェルプログラミングを組んでいます。 そこである問題にぶつかっています。 ******************************************** int main() { int argc, n = 0; pid_t pid; int status; char input[MAX_LEN], *argv[MAX_ARGS]; char path[30]; while (1) { /* プロンプトの表示 */ ++n; printf("command[%d] ", n); fgets(input, MAX_LEN, stdin); /* 改行を除去し、 空白,タブ区切りでコマンド列に分割、argvに単語毎に格納 (処理は略) */ sprintf(path,"%s",argv[0]);//PATH取得 pid = fork(); /*#### 子プロセス ####*/ if(pid == 0){ execvp(path,argv); exit(0); } /*#### 親プロセス処理 ####*/ } else { wait(&status); } }//while }//main としています。 ここで ls ps rm mkdir emacs などのコマンドは普通につかえるのですが、 cd .. や、 mkdir test cd test としてもそのディレクトリへ移動することができません。どうすればいいでしょうか?このプログラムをうごかしたままディレクトリを移動することは可能でしょうか?

  • プロセスに関するプログラム

    UNIX系OSでのプロセスの動きを確認するプログラムを勉強しています。 コマンドライン引数で与えられた整数の数だけプロセスを作成するというもので、わからないことがありますので教えて頂けると幸いです。 質問の要点は 1.プロセスの番号がなぜ順番どおりに並ばないことがあるのか 2.どのような点からこのプログラムのプロセスの最大生成数を判定す  るのか という2点です。 parentIDが1のときはinitが親を引き継いでいることはわかっています。 どなたかご教授おねがいします。 下記にソースコードを載せておきます。 *** process.c *** #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[]) { int np; int i; pid_t child_id; if(argc == 2) { fprintf(stderr, "<number of processes>\n"); exit(1); } np = atoi(argv[1]); for(i = 0; i < np; i++) if(child_id = fork()) break; printf("%d: process ID=%ld parent ID =%ld child ID=%ld\n", i , (long)getpid(), (long)getppid(), (long)child_id); return 0; }