1
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>

char *getdir()  /*find working directory*/
{
  char *buffer;/*buffer is going to be used in getcwd function to get the current directory*/
  char *path_buffer;//path_buffer is going to contain the directory//
  long maxsize = pathconf(".", _PC_PATH_MAX);/* we set maxsize as the maximum pathname length*/
  if((buffer=(char*) malloc((size_t)maxsize))!=NULL)
    {
      path_buffer=getcwd(buffer,maxsize); /*get the current directory*/
      printf("\nMy working directory = %s",path_buffer);
      return path_buffer;
    }
  else{
    exit(-1);
  }
}

char * getcmline() /*get command from stdin by the user*/
{
  int bytes_read;
  int nchars=200;/*max possible number for the input of the user*/
  int nbytes=(sizeof(char))*nchars; /*size of chars in bytes*/
  char *line=(char*) malloc(nbytes+1);
  bytes_read=getline(line,&nbytes,stdin);/*read line from stdin*/
  if(bytes_read == -1){
    printf("Read line error");
    exit(-1);
  } /*error handling for bytes_read*/
  else{
    if(line[strlen(line)-1]=='\n')
      {
        line[strlen(line)-1]='\0'; /*change new line character in the end of the line of stdin*/
      }
  }
  return line;
}

int main(void)
{
  pid_t pid,child_pid;
  int rv=0;
  char* exit_string="exit";
  char *path_buffer=NULL;
  int nchars=200;
  int nbytes=(sizeof(char))*nchars;
  char *line=malloc(nbytes+1);
  char *commands[2];
  while(1){
    switch(pid = fork())
      {
      case -1:
        perror("fork"); /* something went wrong */
        exit(1);
      case 0:
        printf(" CHILD: This is the child process!\n");
        child_pid=getpid();
        printf(" CHILD: My PID is %d\n", child_pid);
        path_buffer=getdir();/*get the directory path*/
        line=getcmline();/*get a command by the user*/
        if(strcmp(line,exit_string)==0)
          {
            rv=3;
            exit(rv);
          }
        commands[0]=line;
        commands[1]=NULL;
        execvp(commands[0],commands);
        perror("Execution error");
        exit(-1);



      default:
        waitpid(-1, &rv, 0);
        if(WIFEXITED(rv)){
          printf("Child exited normally and child's exit status is: %d\n", WEXITSTATUS(rv));
          if((WEXITSTATUS(rv))==3){
            exit(1);
          }
        }
      }
  }
  return 0;
}

で変更を行い、getlinerv適切な変数を作成しましたexecvp。しかし、今発生するエラーは、たとえば「ls」と入力した後のことです。それは言います:

実行エラー: そのようなファイルまたはディレクトリはありません。

助けてくれてありがとう、そして私の知識不足。

エラーは行変数にあるようですが、何が問題なのか理解できません!

C の Char 配列と getline

解決策はここに示されています。それは、line[(strlen)-1] ではなく、line[(strlen)-1] である必要があります。

4

3 に答える 3

4

親は子の pid を取得しないため、waitpid はそれを待機していません。waitpid(-1,...) は、続行する前に子プロセスが終了するのを待ちます。

また、ケースをインデントし、各ケース ステートメントを改行で終了することもお勧めします。

于 2012-09-17T19:39:58.523 に答える
1

したがって、警告については、これらの数字がどの行を参照しているかを知っているので、推測する必要があります。これを簡単にすることができます!

int rv=NULL;

初期化により、キャストなしでポインターから整数が作成されます [デフォルトで有効] 42行目

NULL はポインター値、rv は整数です。0それが意味する場合は、に設定してください。

execvp(line[0],line);

'execv' の引数 1 を渡すと、キャストなしで整数からポインターが作成されます [デフォルトで有効] 64 行目 互換性のないポインター型から 'execv' の引数 2 を渡す [デフォルトで有効] 64 行目

を呼び出している場合execv、コンパイルしているコードは投稿したものではありません。しかし...linechar *ですline[0]。またはcharの最初の引数は です。execvexecvpconst char *

execv は何を達成しようとしていますか? 実行するプログラム名 (最初の引数、const char *) と引数の配列 (これらはargv[]新しいプログラムのmain関数に渡される配列を形成し、配列の最後の項目は NULL でなければなりません) が必要です。

char *line=(char*) malloc(nbytes+1);
bytes_read=getline(&line,&nbytes,stdin);/*read line from stdin*/

互換性のないポインター型から 'getline' の引数 2 を渡す [デフォルトで有効] 29 行目

getline文字を入れるバッファのアドレスが必要です ...line そのようなアドレスです。&lineただし、 はポインタのアドレスです。を取り出すだけ&


コードには他にも問題がありますが、これらの警告にはすべて共通点があります。

  • 関数が期待する型を理解していないようです。
  • 変数の型、
  • 実際に渡している型、
  • または、型が一致しないと不平を言うときのコンパイラの意味

マルチプロセス プログラムを書き始める前に、このことを理解しておく必要があります。簡単なことから学び、ドキュメントを読み、コンパイラの警告を理解してください。

于 2012-09-17T21:06:13.200 に答える
0
default:
waitpid(child_pid, &status, 0);
//wait(&rv);
printf("PARENT:My child's exit status is: %d\n", WEXITSTATUS(rv));
if((WEXITSTATUS(rv))==3){exit(1);}

初期化されていない変数child_pidをに渡していますwaitpid。その変数は子プロセスでのみ設定されます。パスする必要がありpidます。初期化されていない変数を使用すると、未定義の動作が発生するため、何が起こるか予測できません。WEXITSTATUSまた、別の初期化されていない変数を呼び出すrv場合は、そこに渡す必要がstatusあります。

子供はここでは何もしません。

path_buffer=getcwd(buffer,sizeof(buffer));

に渡される size 引数getcwdは のサイズでありchar*、通常は 4 または 8 バイトであり、ほとんどのディレクトリの絶対パスには短すぎます。そこにはpath_buffer is set toNULL and the child immediately exits. You should pass the size of the buffer,maxsize` があります。

于 2012-09-17T19:41:56.847 に答える