• 締切済み

forkの失敗???

C++(UNIX)です。 以下のようなprogramをくみました。 comは自作のCシェルです。 ------------------- : pid_t ch_pid = fork(); cout << "ch_pid = " << ch_pid<< endl; int shell_ret = 0; int execl_ret = 0; int status = 0; if( ch_pid == 0) { cout << "execl(shell)" << endl; execl_ret = execl(com, com, NULL); cout << "execl ret = " << execl_ret << endl; } else if(ch_pid < 0) { cout << "fail to fork" << endl; cout << "errno = " << errno << endl; return 0; } waitpid(ch_pid, &shell_ret, 0); : ------------------ 実行したところ、 成功する[シェルが実行される]場合と、失敗する[シェルが実行されない]場合があります。 シェルが失敗するときはそれ以上先に進まず、固まってしまいます。(waitpidのせいだと思いますが。) 成功する場合のログ --------------- ch_pid = 12885 ch_pid = 0 execl(shell) : --------------- 失敗する場合のログ --------------- ch_pid = 12885 : --------------- forkに失敗していたら、"fail to fork"と表示されると思うので forkには失敗していないと思うのですが・・・。 なぜ、execlは実行されないのでしょうか。

noname#1080
noname#1080

みんなの回答

  • terra5
  • ベストアンサー率34% (574/1662)
回答No.3

このソースだとexecl()が失敗した場合, waitpid()を実行してしまい、ハングするでしょうね。 return errnoあたりが適切でしょうか。 あとは、情報不足なのでわかりません。 fork()やexecl()の失敗時のerrnoは必ずわかるようにしておきましょう。 -1がわかってもうれしくないです(^^; execl()が失敗する可能性も無いとは言えないかなぁ。

noname#1080
質問者

お礼

回答ありがとうございます。 execl()の失敗等のエラー処理も追加しました。

  • pikacchu
  • ベストアンサー率44% (11/25)
回答No.2

C++は少しかじったくらいなのではっきり言えませんが、なぜエラーになるのかの判断として、errnoを見てみるのはどうですか? 通常ですとerrno.hをインクルードして変数errnoを見ればエラーの種類がわかります。例えば、メモリが足りないとか・・・ただし、errnoはintの整数ですが、ヘッダの中を見ればエラーの種類はわかりますよ。

noname#1080
質問者

お礼

ありがとうございます。 errnoは使っていました。 が、manで調べていたので、エラーの種類がわからなかったんです。 ヘッダの中を見て、ようやく分かりました。ありがとうございました。

  • ranx
  • ベストアンサー率24% (357/1463)
回答No.1

このような質問をされる際の一般原則ですが、お使いの環境(OSの種類など)について 書いておいて頂いた方が、的確な回答を得やすいと思います。 プログラムを拝見しましたが、この範囲では、特に問題のありそうな個所は見当たらない ように思います。恐らく、fork()が失敗したわけでもexecl()が失敗したわけでもない ...となると、残るはcomの内部ですね。(ch_pid =0;execl(shell)が表示されないのは、 恐らくバッファリングされて、出力されていないためでしょう。) 試みに、ハングアップした状態で、psコマンドで状況を確認してみて下さい。 ・子プロセス(csh)が動いていなければ、上のプログラムに問題があります。 ・子プロセスが起動されながら動いていなければ、comが何かのリソース待ちです。 ・子プロセスが動きつづけていれば、恐らくcomが何かのバグで、無限ループに陥っています。

noname#1080
質問者

お礼

回答ありがとうございました。 ここでは記載していなかったのですが、 この関数がスレッドだったためfork()ではなく、fork1()を使うほうが良かったようです。 また、fork()とexecl()の間にログを吐くマクロ(自作)を入れていたのですが、それが大きな原因だったようです。

関連するQ&A

  • execl+forkで起動したシェルの結果

    execl+forkでシェルを起動したとき、 起動したシェルから返ってくる結果はどうやってとれるのでしょうか。 ============== pid_t pid_c; if(pid_c == 0) { int ret = execl(shell,shell, id, NULL); if(ret != 0) { exit(1); } } else if (pid_c < 0) { exit(1); }

  • char*の実体の数値をchar変数に格納する方法

    ある関数の戻り値がchar*でその関数の戻り値をchar変数に格納したいです。 char *ret_ch() { char *p="12"; return p; } int main(){ char res; //ここでret_ch()の戻り値の実体数値を代入 res=*ret_ch(); cout<<"RET=="<<ret<<endl; return 0; } char型は1バイトなので一文字しか入りません。 char型に数値として扱い、上記のポインターの 実体数値を格納するにはどのようにしたらいいのでしょうか? よろしくお願い致します。

  • forkについて

    fork文を使った問題について質問です。 #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { pid_t pid1,pid2; if((pid1 = fork()) == 0) printf("I am a first child with pid = %d,My parent pid is %d.\n",getpid(),getppid()); else if(( pid2 = fork()) == 0) printf("I am a second child with pid = %d,My parent pid is %d.\n",getpid(),getppid()); else printf("I am a parent with pid = %d.\nMy first and second children are %d and %d.\n",getpid(),pid1,pid2); exit(EXIT_SUCCESS); } このようなプログラムが与えられました。 問題は 1.このプログラムを改造して、1つの親プロセスから100の子プロセスを順に生成するプログラムをつくるというものと 2.1つの親から子プロセスを生成し、その子プロセスの孫プロセスを生成するプログラムをつくれというものです。 1はfor文を使えばできそうなのですが、forkの基礎が出来ていないのでどうループを回せばよいか分かりません。 2もfork内でforkを実行すればできそうだと思ったのですがうまく動かず・・・。 どうか正しく動くようなプログラムを教えてください!お願いします。

  • lsコマンドでforkできない

    Vine6.0の載ったマシン(node1とする)をlogin shellをzshにして使っています。 teratermなどを使って、node1にsshでログインし、lsコマンドを使用すると、 ls: fork failed: リソースが一時的に利用できません というメッセージが出て、lsが失敗します。zshをもう一度子シェルとして実行すると、 解決します。 他のコマンドは問題なく使えているので、lsが悪いのか、zshが悪いのかだと思うのですが、 理由はわかりますでしょうか? よろしくお願いします。

  • char型変数のアドレスを coutで表示するには

    #include <iostream> using namespace std; int main() { bool b; int i; short s; long l; float f; double d; char c; //上で宣言した変数のアドレスを表示 cout << "bool &b " << &b << endl; cout << "int &i " << &i << endl; cout << "short &s " << &s << endl; cout << "long &l " << &l << endl; cout << "float &f " << &f << endl; cout << "double &d " << &d << endl; cout << "char &c " << &c << endl; //「char &c 」とのみ表示される cout << '\n'; //char型のみ printf で再表示 printf("char &c %p\n", &c); //「char &c ********」と表示される return 0; } 上のプログラムを実行すると cout << "char &c " << &c << endl; のところだけ、アドレスが表示されません。 printfを使えば、char型の変数のアドレスも表示されるのですが…。 coutを使ってchar型のアドレスを表示させるにはどうすればいいのでしょうか。 よろしくお願いします。

  • アドレスの計算が合わない

    C++でポインタの勉強をしています。 その中でアドレスについての以下のような記述がありました。 <例1> struct { int a; int b; int c; } oshiete; cout << &oshiete.a << endl; cout << &oshiete.b << endl; cout << &oshiete.c << endl; このように、構造体の中で宣言された変数の領域は連続した場所を確保するというものでした。これの実行結果は以下の様になりました。 0013FF5C 0013FF60 0013FF64 int型のバイト数は4でしたので、それぞれの変数の先頭アドレスは4つ間隔になっています。しかし、これの2つ目の変数bをshort型に変えても同じ結果が返ってくるのです。short型のバイト数は2です。 <例2> struct { int a; short b; int c; } oshiete; cout << &oshiete.a << endl; cout << &oshiete.b << endl; cout << &oshiete.c << endl; 結果: 0013FF5C 0013FF60 0013FF64 そして変数aもshort型にすると、やっと納得のいく結果になりました。 <例3> struct { short a; short b; int c; } oshiete; cout << &oshiete.a << endl; cout << &oshiete.b << endl; cout << &oshiete.c << endl; 結果: 0013FF60 0013FF62 0013FF64 なぜ<例2>ではint, short, intの順で宣言したのにアドレスが全て4つ間隔なのでしょうか?例えば先頭アドレスが0013FF5Cであるなら、 0013FF5C 0013FF60 0013FF62 のように1つ目と2つ目のアドレス差は4、2つ目と3つ目のアドレス差は2になるはずだと思うのですが。

  • C++ の while ループ

    C++の基本学習者です。Windows 10 で Visual Studio Community 2015 を使っています。 教本に載っている、機械語のプログラムをC++でシミュレーションする、というものを作ろうと、途中まで下のようなコードを書き込み、そこまで間違いがないかを確かめるために、コンパイルして実行したら、添付の写真のようなエラーメッセージが出てきました。 // ConsoleApplication65.cpp : メイン プロジェクト ファイルです。 #include "stdafx.h" #include <iostream> #include <iomanip> #include <cstdlib> #include <ctime> #include <cmath> #include <cstring> using namespace System; using namespace std; int main() { // variables int program = 0; int accumulator = 0; int count = 0; int instructionRegister = 0; int operationCode = 0; int operand = 0; int location[100]; cout << "*** Welcome to Simpletron ***" << endl; cout << "*** Please enter your program ***" << endl; cout << "*** one instruction at a time,***" << endl; cout << "*** after the location number and and the prompt of '?' ***" << endl; cout << "*** To stop entering instructions, ***" << endl; cout << "*** enter -9999 . ***" << endl << endl; cout << setfill('0') << internal; cout << setw(3) << count << " ? "; cin >> program; while (program != -9999) { location[count] = program; count++; } return 0; } while ループに問題がありそうですが、コンパイルはちゃんとできたのに、何が悪いのでしょうか? 詳しい方、どうぞ教えてください。お願いします。

  • C言語 fork()について

    C言語 fork()について C言語でSystem Call fork()というものがあるそうで、まずは http://cai.int-univ.com/sugsi/Lecture/NetProg/chapter5/fork.html こちらのサイトの例をvisual studio 2008で実行させてみようと思ったのですが、以下のエラーが表示されてしまいました。 1>c:\users\user\documents\visual studio 2008\projects\project1\system call fork\system call fork\system call fork.cpp(3) : fatal error C1083: include ファイルを開けません。'unistd.h': No such file or directory ソースは以下のものです。 #include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(void) { int pid; char msg[256]; sprintf(msg, "hello world"); //sprinf()でmsgにhello worldを格納する pid = fork(); if(pid == 0) printf("%s, child process\n", msg); else printf("%s, parent process\n", msg); return 0; } #include <unistd.h>について注意されていますが、これは何なのでしょうか? #include<stdio.h>ならprintf()などの基本的な関数を使うのに必要なものと覚えたので、 #include <unistd.h>もfork()を使うときに必要なものだろう程度に思っているのですが、どうすれば、まずこのプログラムが実行できるんでしょうか? No such file or directoryと書かれているぐらいですから、下準備としてこのプロジェクトが保存されている場所でtxtファイルか何かを準備しておく必要があるということですかね...

  • ファイルをオープンしたままfork

    ファイルをオープンしたままforkした際の動作について質問です。 下のコードを書いてコンパイル、実行します。 #include <stdio.h> int main(int argc, char **argv){ FILE *fp; fp=fopen("file", "w"); fprintf(fp, "%d\n", getpid()); printf("%d\n", getpid()); fork(); } ====== $ gcc hoge.c -o hoge.out $ ./hoge.out XXX ←pid なぜかファイル内には同じpidが2つ書かれている。 $ cat file XXX XXX fork()によって生成されたプロセスが元のプロセスのファイルを参照することは予想できます。 しかしforkする前にfprintしているのになぜまたファイルに同じ内容が書き込まれるのでしょうか?

  • バックグラウンドでの処理

    C言語のカテゴリで質問しようか迷いましたが動きはシェル関連なので質問させてください. 例えば,以下のようなCソースがあったとします. 1 #include<iostream> 2 3 int main(int argc, char *argv[]) 4 { 5 6 for (int i = 0;; i++) { 7 8 std::cout << "0" << std::endl; 9 } 10 11 return 0; 12 } 実行ファイル名を0として ./0 & としましたが,0が連続的に出力されるだけでした. バックグラウンドで処理させているはずなのになぜ0が出力されるのでしょうか?

専門家に質問してみよう