2015-09-15 47 views
1

我有下面的代碼有問題父進程的孩子之前運行。 這就像在Unix平臺上使用C的手動shell程序實現。如果用戶輸入一個命令,它應該執行並返回相應的結果。 如果用戶在末尾輸入「&」,則父進程不需要等待子進程完成。等待(NULL)功能無法正常工作並始終

#include <stdio.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <signal.h> 
#include <stdlib.h> 
#include <string.h> 

#define HISTORY_LIMIT 20 
#define BUFFER_LIMIT 100 
#define MAX_WORDS 50 

int count = 0; 
char history[HISTORY_LIMIT][BUFFER_LIMIT]; 

int tokenize(char *str, char **args, int *bRun) 
{ 
    int i, argc = 0; 
    char *token; 
    if (count == HISTORY_LIMIT) 
    { 
     // alignHistory(); 
    } 
    // strcpy(history[count],str); 
    count++; 
    token = strtok(str, " \t\n"); 
    for (i = 0; token != NULL; i++) 
    { 
     args[i] = token; 
     token = strtok(NULL, " \t\n"); 
     argc++; 
    } 

    for (i = 0; i < argc; i++) 
    { 
     if (strcmp(args[i], "&") == 0) 
     { 
      *bRun = 1; 
      args[i] = NULL; 
     } 
    } 

    return argc; 
} // end of tokenize function 

void handleSignal(int sign) 
{ 
    if (sign == SIGINT) 
    { 
     // getHistory(); 
    } 
} // end of handlesignal 

int main(void) 
{ 
    char *args[MAX_WORDS]; 
    char buffer[BUFFER_LIMIT]; 
    pid_t pid; 
    int argc; 
    int bgRun = 0; 
    if (signal(SIGINT, handleSignal) == SIG_ERR) 
    { 
     printf("can't handle ctrl-c"); 
     return 0; 
    } 
    while (1) 
    { 
     bgRun = 0; 
     memset(args, 0, MAX_WORDS); 
     printf("osh>"); 
     fgets(buffer, BUFFER_LIMIT, stdin); 
     argc = tokenize(buffer, args, &bgRun); 
     if (argc == 0) 
      continue; 

     if (strcmp(args[0], "exit") == 0) 
      break; 
     if (strcmp(args[0], "history") == 0) 
      getHistory(); 
     // else if(strcmp(args[0],"hello")==0)printf("Hi There, How are you ?\n"); 
     else 
     { 
      pid = fork(); 

      if (pid == 0) 
      { 
       execvp(args[0], args); 
       return 0; 
      } 
      else 
      { 
       if (bgRun == 0) 
        wait(NULL); 
      } 
     } 
    } 
} 

輸出是:

osh>whoami 
root 
osh>whoami & 
osh>root 
whoami 
osh>root 

但所需的結果應該是這樣的(如果&在命令中使用)

osh>whoami 
root 
osh>whoami & 
osh>root 
whoami 
root  
osh> 

因此,我已經使用bgRun int變量並分配1如果命令有1 但那不起作用。我認爲這是wait(NULL)的問題。請把我從這個惡魔中拯救出來。

+1

你能澄清一下嗎?實際產出和預期產出之間有什麼實質性區別?我可以看到明顯的差異,但不清楚爲什麼一個是正確的輸出,另一個不是。並且請修正你的代碼的格式 - 很難閱讀而沒有正確的縮進。 – kaylum

+0

我的意圖是,如果命令中添加了&,那麼父母不需要等待子進程完成,但是如果您觀察到最後四行預期vs獲得的o/p ..我已經輸入了「whoami&」並單擊了回車因爲它是'&'父母不應該等待孩子,所以它首先執行和「osh>」打印在「根」之前)直到現在一切都很好..但問題出現在下一步,我已經進入「whoami」和這裏的父母應該等待子進程執行,因爲我用等待(空),但不幸的是父母並沒有等待,所以我得到了O/P「osh>」之前 –

回答

2

你們不是說子進程來等待,因此第三個命令(應不後臺運行)被認爲是當完成命令退出。

哎呀。

您需要處理SIGCHLD並在終止時收穫後臺進程,並檢查退出的進程是當前正在運行的「前臺」進程,而不是後臺作業完成。 waitpid()允許您等待特定的過程。

+1

而OP可能需要注意的孩子,它甚至沒有知道它有(我已經完成了這一過程 - 有意無意地)。你必須檢查'wait()'是否返回了你期望的PID,如果不是,決定如何處理它。只是盲目地忽視回報價值是不好的。通常,'wait(NULL)'也不好;你經常想知道孩子爲什麼/如何終止。而對於調試,這是至關重要的;您需要捕獲PID和狀態並報告它們,以便知道發生了什麼。 –

+0

@JonathanLeffler如果你解釋的變化我在我的代碼做這將是巨大 –

+0

請註明修改任何代碼需要在他的代碼@Ben福格特 –