簡體   English   中英

Shell似乎可以識別命令,但不執行命令

[英]Shell seems to recognize commands but doesn't execute them

我正在嘗試在類似unix的xv6 OS的Shell程序中實現基本命令執行。 我正在編輯的Shell代碼的一部分是runcmd函數,在這里我使用execvp命令執行終端中使用的命令。 當我編譯程序時,該程序編譯沒有錯誤,但是當我嘗試在命令行上鍵入命令時,沒有任何反應。 我已經閱讀了exec命令的手冊頁 ,但是我仍然不太了解需要在exec()命令中傳遞這些參數的正確方式,或者我什么時候需要使用哪個版本的exec()。對於OS編程來說還是很新的。

為了執行命令,我這里還沒有實現哪些功能? 我有以下runcmd函數的代碼:

編輯:

我只是為每個命令添加了更多的exec語句和二進制文件的路徑。 但是,只有第一個exec命令有效(本例中為cd)。 當我使用任何其他命令時,命令行會像執行CD一樣執行它。 如何使它適用於多個命令?

struct cmd {
  int type;          //  ' ' (exec), | (pipe), '<' or '>' for redirection
};
struct
 execcmd {
  int type;              // ' '
  char *argv[MAXARGS];   // arguments to the command to be exec-ed
};

// Execute cmd.  Never returns.
void
runcmd(struct cmd *cmd)
{
  int p[2], r;
  struct execcmd *ecmd;
  struct pipecmd *pcmd;
  struct redircmd *rcmd;

  if(cmd == 0)
    exit(0);

  switch(cmd->type){
  default:
    fprintf(stderr, "unknown runcmd\n");
    exit(-1);

  case ' ':
    ecmd = (struct execcmd*)cmd;

    if(ecmd->argv[0] == 0)
      exit(0);
    //fprintf(stderr, "exec not implemented\n");
     execvp("/bin/cd" , ecmd->argv );
     execvp("/bin/grep" , ecmd->argv );
     execvp("/bin/echo" , ecmd->argv );
     execvp("/bin/cat" , ecmd->argv );
     execvp("/bin/ls" , ecmd->argv );
    break;

  case '>':
  case '<':
    rcmd = (struct redircmd*)cmd;
    //fprintf(stderr, "redir not implemented\n");
    execvp("/bin" , ecmd->argv );
    runcmd(rcmd->cmd);
    break;

  case '|':
    pcmd = (struct pipecmd*)cmd;
    fprintf(stderr, "pipe not implemented\n");
    int execl(const char *path, const char *arg, ...);
    break;
  }    
  exit(0);
}

您似乎正在嘗試執行“ / bin”目錄。

您應該使exec調用的第一個參數為用戶要運行的二進制文件。

當命令失敗時,使用perror函數還將為您提供有用的輸出。

認為這是您真正需要的:

case ' ':
    ecmd = (struct execcmd*)cmd;
    if (ecmd->argv[0] == 0)
        _exit(0);
    execvp(ecmd->argv[0], ecmd->argv);
    /* if control reaches this point, execvp failed */
    perror(ecmd->argv[0]);
    _exit(127);

您可能想知道為什么execvpargv[0]交給它時,為什么execvp將可執行文件作為與參數向量分開的單獨參數加載。 這是舊版功能; 如果我今天從頭開始設計此API,我認為我不會包含它。 但是,想法是程序可能會根據其argv[0]不同而有所不同。 例如, ex一天, exvi相同的可執行文件 (到同一個inode的兩個硬鏈接-symlinks尚未發明),它基於argv[0]決定以哪種模式啟動。 而且,自Unix誕生以來, login(1) 調用了將argv[0]的第一個字符設置為'-'argv[0] 沒有/bin/-sh ,因此它實際上需要與參數向量分開指定要調用的程序的能力。

我目前無法想到shell會使用argv[0]以外的任何東西作為execvp的第一個參數的情況。

有關代碼其他更改的注釋:

  • 切勿只在_exit上調用fork的子級上的exit
  • 當系統調用失敗時,請始終將有問題的文件名和strerror(errno) 打印到stderr 而不是 stdout perror是此操作的方便快捷方式。
  • 為了使perror調用安全,必須在fork之前緊接在父級中調用fflush(0) ,並且您的C庫必須正確地實現stderr的行緩沖。 我之所以這樣說是因為XV6似乎是一個教學操作系統,您必須自己實現它的一部分,而且我不知道stdio是否是您的責任。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM