2015-05-03 72 views
0

我在操作系統類中,我有一個處理fork和pipe的項目。在開始我的項目之前,我試圖更好地理解叉子和管道,所以我正在通過一個示例進行工作。這是有問題的代碼(當PID =叉()等於0情況下爲0,是一個子處理):管道,子進程和子進程的範圍

switch(pid = fork()) 

{

case -1: 

    perror("fork call"); 
    exit(2); 
    break; 
case 0: 
    char str1[MSGSIZE]; 
    char str2[MSGSIZE]; 
    char str3[MSGSIZE]; 
    printf("Enter a string! "); 
    fgets(str1, MSGSIZE, stdin); 
    printf("Enter another string! "); 
    fgets(str2, MSGSIZE, stdin); 

    printf("Enter the last string! "); 
    fgets(str3, MSGSIZE, stdin); 


    close(p[0]); 
    write(p[1], msg1, MSGSIZE); 
    write(p[1], msg2, MSGSIZE); 
    write(p[1], msg3, MSGSIZE); 
    printf("About to write str1,str2,str3...\n"); 
    write(p[1], str1, MSGSIZE); 
    write(p[1], str2, MSGSIZE); 
    write(p[1], str3, MSGSIZE); 
    break; 
default: 
    close(p[1]); 
    for(j = 0; j < 6; j++) 
    { 
    read(p[0], inbuf, MSGSIZE); 
    printf("%s\n", inbuf); 
    } 
    wait(NULL); 

    }//switch 

當我編譯在命令行上我得到這些錯誤:

$ GCC -o P3 pipe3.c

pipe3.c:45:7:錯誤:預期表達 炭STR1 [MSGSIZE];^

pipe3.c:49:13:錯誤:使用未聲明的標識符'str1' fgets(str1,MSGSIZE,stdin);使用未聲明的標識符'str1' write(p [1],str1,MSGSIZE);使用未聲明的標識符str1' 寫入(p [1],str1,MSGSIZE); ^

生成3個錯誤。

我最初在main函數的開頭聲明瞭str1,str2和str3(我知道這裏仍然是父進程),並且在編譯時沒有得到這些錯誤。我試圖在子進程中聲明這些的唯一原因是因爲我試圖理解子進程的範圍以及它的能力,這意味着我只是試着圍繞什麼是合法的和非法的。我不明白爲什麼編譯器會關心子進程是創建和初始化變量的子進程,然後只在子進程的範圍內使用它們來寫入管道。所以我想我想問的主要問題是,這實際上是管道的限制嗎?我嘗試使用char * str1;在子進程中,然後使用fgets存儲輸入,但我仍然得到相同的編譯器錯誤。另外,我錯誤地認爲子進程的範圍只是情況0之間的代碼:break;還是子進程獲得父進程的整個副本,因爲父進程中的其餘代碼被忽略,因爲子進程執行代碼的唯一時間是當pid == 0時?我知道這可能是一些基本的東西,但操作系統是第一個讓我徹底難倒程序員的人。

這裏是上下文和完整性我的全部源代碼:

#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 

#define MSGSIZE 16 
int main(int argc, char *argv[]) 
{ 
    char inbuf[MSGSIZE]; 
    char *msg1 = "Hello world #1"; 
    char *msg2 = "Hello world #2"; 
    char *msg3 = "Hello world #3"; 
    char str1[MSGSIZE]; 
    char str2[MSGSIZE]; 
    char str3[MSGSIZE]; 

    int p[2], j; 
    pid_t pid;  

    if(pipe(p) == -1) 
    { 
    perror("pipe call"); 
    exit(1); 
    } 

    switch(pid = fork()) 
    { 

case -1: 

    perror("fork call"); 
    exit(2); 
    break; 
case 0: 
    //char *str1; 
    //char *str2; 
    //char *str3; 
    printf("Enter a string! "); 
    fgets(str1, MSGSIZE, stdin); 
    printf("Enter another string! "); 
    fgets(str2, MSGSIZE, stdin); 

    printf("Enter the last string! "); 
    fgets(str3, MSGSIZE, stdin); 


    close(p[0]); 
    write(p[1], msg1, MSGSIZE); 
    write(p[1], msg2, MSGSIZE); 
    write(p[1], msg3, MSGSIZE); 
    printf("About to write the input strings...\n"); 
    write(p[1], str1, MSGSIZE); 
    write(p[1], str2, MSGSIZE); 
    write(p[1], str3, MSGSIZE); 
    break; 
default: 
    close(p[1]); 
    for(j = 0; j < 6; j++) 
    { 
    read(p[0], inbuf, MSGSIZE); 
    printf("%s\n", inbuf); 
    } 
    wait(NULL); 

    }//switch 

    return 0; 
} 

回答

1

標準C(在C99之前)需要變量在一個區塊的開始處聲明。功能(包括main)在這個意義上是一個集團。

switch可能是一個塊,但case不是,所以你不能在一個case中聲明新的變量。 實際錯誤在char str1[MSGSIZE];這是不被編譯器接受,因此str1未被聲明是什麼導致了其他兩個錯誤。

如果你只想在孩子聲明變量(什麼對你有感覺作爲一個程序員,而不是編譯:fork僅僅是一個函數爲它),你可以通過兩種方式做到這一點:

  • 一個乾淨的將是把在一個函數,調用該函數:

    void doCopy(int *p) { 
        char str1[MSGSIZE]; 
        char str2[MSGSIZE]; 
        char str3[MSGSIZE]; 
        printf("Enter a string! "); 
        fgets(str1, MSGSIZE, stdin); 
        printf("Enter another string! "); 
        fgets(str2, MSGSIZE, stdin); 
    
        printf("Enter the last string! "); 
        fgets(str3, MSGSIZE, stdin); 
    
    
        close(p[0]); 
        write(p[1], msg1, MSGSIZE); 
        write(p[1], msg2, MSGSIZE); 
        write(p[1], msg3, MSGSIZE); 
        printf("About to write the input strings...\n"); 
        write(p[1], str1, MSGSIZE); 
        write(p[1], str2, MSGSIZE); 
        write(p[1], str3, MSGSIZE); 
    } 
    
    int main(int argc, char *argv[]) 
    ... 
         case 0: 
          doCopy(p, MSGSIZE); 
          break; 
    ... 
    
  • 不太地道,但編譯的方式將迫使歐元區的創建與虛擬如果:

    ... 
        switch(pid = fork()) 
        { 
    
    case -1: 
    
        perror("fork call"); 
        exit(2); 
        break; 
    case 0: 
        if(1) { 
         char str1[MSGSIZE]; 
         char str2[MSGSIZE]; 
         char str3[MSGSIZE]; 
         printf("Enter a string! "); 
         fgets(str1, MSGSIZE, stdin); 
         printf("Enter another string! "); 
         fgets(str2, MSGSIZE, stdin); 
    
         printf("Enter the last string! "); 
         fgets(str3, MSGSIZE, stdin); 
    
    
         close(p[0]); 
         write(p[1], msg1, MSGSIZE); 
         write(p[1], msg2, MSGSIZE); 
         write(p[1], msg3, MSGSIZE); 
         printf("About to write the input strings...\n"); 
         write(p[1], str1, MSGSIZE); 
         write(p[1], str2, MSGSIZE); 
         write(p[1], str3, MSGSIZE); 
        } 
        break; 
    default: 
    ... 
    
+0

嘿,非常感謝你的幫助!這很有道理。我嘗試將情況0中的代碼推入自己的範圍並且工作正常。該功能絕對是更好的方式。 –

1

編譯器有沒有關於流程的想法。它只關心大括號。您正在收到錯誤,因爲您處於c89模式,其中必須在範圍的開頭聲明變量(請注意,case確實是而不是打開了一個範圍)。

嘗試使case 0的全部內容成爲塊,或將-std=c99選項傳遞給編譯器。

+0

哇哦,我從來沒有意識到這點。我開始覺得我錯過了一些關於叉子或過程的重要事情。非常感謝你,我非常感謝你的幫助! –