0

クライアントがTCPソケットを使用してサーバーに接続できるようにし、ユーザーがクライアント側からサーバー側にシステムコールを発行して応答を返すことができるようにする単純なクライアント/サーバープログラムを作成しようとしています。例えば:

クライアントの問題: ls

サーバーは /usr/bin または w/e で ls を見つけ、execve() を使用して実行します。

また、クライアント側でシステム コールを発行する lls や lmkdir などのようなものも用意します。

問題は、「ls」またはその他のコマンドが実際に呼び出されていないため、私の execve() が正しく実行されていないように見えることです。私はこれと同じ種類のプログラムを以前にローカル側のみ(サーバーなどなし)で実行したことがあり、execve()は正常に機能しました。ここにいくつかのコードがあります:

       pid = fork();

       if(pid){ // Child
        printf("child wait");
          pid = wait(&status);
          printf("Child dead\n");
       }else{ // Parent

          if(execPath){            

          execve(execPath, arglist, env);
          printf("Command Complete\n");

        }

       }

何らかの理由で、PID ステートメントの子セクションの printfs がまったく実行されていません。システムが実際にプロセスをフォークしているとは思いません。クライアント/サーバータイプのプログラムであるため、これを機能させるために何か特別なことをしなければなりませんか、それともまったく同じように機能する必要がありますか?

ありがとう

4

3 に答える 3

2

正確にexecveは、フォークしません。現在の画像を引数として指定された画像に置き換え、最初から開始します(つまりmain())。元のプログラムに戻ることはありません。

system()おそらくユースケースで使用したいと思うでしょう。

于 2013-02-25T19:01:32.967 に答える
1

コードにはいくつかの問題があります。

  • fork()親の場合は pid を返し、子の場合は 0 を返します。したがって、親は if の true ブランチを実行します。そして子はelseブランチを実行します。それらのコメントを交換します。
  • stdout はライン バッファリングされます。待機の前に新しい行(\n)を追加します。printfそうしないと、待機が完了して 2 番目printfが呼び出される前に印刷が表示されません。
  • エラーの場合でも子が終了することを確認してください。そうしないと、子が親のコードを実行し、親がまだ子の終了を待っています。
  • execve成功した場合は戻りません。失敗しても返ってきます。

したがって、修正されたコードは次のようになります。

   pid = fork();

   if(pid){  // Parent
      printf("child wait\n");
      pid = waitpid(pid, &status, 0);
      printf("Child dead\n");
   }else{ // Child
      if(execPath){            
          execve(execPath, arglist, env);
          printf("execve failed!\n");
      }
      _exit(1);
   }

または、 を使用できますsystem(3)

于 2013-02-25T20:52:35.527 に答える
1

子プロセスはそれ自体の子プロセスを生成していないため、wait()呼び出しが他の外部イベント (呼び出しを中断するシグナルなど) なしで戻ることはほとんどありません。代わりに、親に子プロセスを待機させる必要があります。

失敗する可能性があることに注意してください。そのfork()ことを考慮する必要があります。execveまた、成功した場合は返されないことに注意してください。したがって、何かを印刷する場合、その後の print ステートメントは失敗を示す必要があります。

system()コマンドの出力を、接続されたクライアントに関連付けられたソケットに送信する必要がある可能性が高いため、を使用してもフォークを節約できない可能性があります。ただし、コードには、出力がクライアントに流れるようにする手順がありません。

switch ((pid = fork())) {
case -1:  /* todo: handle error */
          break;
case 0:   /* child */
          dup2(socket, 0); /* todo: check return value */
          dup2(socket, 1); /* todo: check return value */
          dup2(socket, 2); /* todo: check return value */
          close(socket);   /* todo: check return value */
          execve(...);
          /* todo: handle failure */
          exit(EXIT_FAILURE);
default:  /* parent */
          if (pid != waitpid(pid, 0, 0)) {
              /* todo: handle error */
          }
}
于 2013-02-25T19:49:06.547 に答える