2013-09-11 113 views
1

我寫了一個簡單的代碼,其中一個進程傳遞一個結構到另一個進程,父進程寫入數據,但子進程是不能夠訪問它。我用fork()系統調用來創建兩個進程。但我在這裏有問題,我調用兩次的父進程,當我運行程序時,子進程也被調用兩次。任何人都可以讓我知道我在做什麼錯誤。傳遞一個結構通過FIFO

#include <stdlib.h> 
#include <signal.h> 
#include <stdio.h> 
#include <errno.h> 
#include <sys/errno.h> 
#include <fcntl.h> 
#include <string.h> 

#define MAX_LINE_LEN 100 
#define FIFO_NAME "my_fifo" 

typedef struct student_info { 
char *name; 
int age; 
char *sex; 
}student; 

int w_byte_parent = 0, r_byte_parent = 0; 
int w_byte_child = 0, r_byte_child = 0; 

void do_child() { 
    int fifo; 
    char buffer[MAX_LINE_LEN]; 
    int i = 0; 
    student child; 

    printf("Child opening FIFO \n"); 
    if((fifo = open(FIFO_NAME, O_RDWR)) < 0) { 
    perror("open in child failed"); 
    exit(EXIT_FAILURE); 
    } 
    printf("Child reading from FIFO \n"); 
    r_byte_child = read(fifo, child, sizeof(student)); 
    if(r_byte_child < 0) 
    printf("Read failed by child process\n"); 
    printf("%d Bytes read by child process\n", r_byte_child); 
    } 

int main(int argc, char **argv) { 
int fifo; 
char buffer[MAX_LINE_LEN]; 
int ch = 0, i = 0; 

/* 
** Create a FIFO 
*/ 
/* Parent creating FIFO */ 
if((mkfifo(FIFO_NAME, 0666)) < 0) { 
    if(errno != EEXIST) { 
     perror("mkfifo"); 
     exit(EXIT_FAILURE); 
    } 
} 
/* 
** Create other process 
*/ 

switch(fork()) { 
    case -1: 
     perror("fork()"); 
     exit(EXIT_FAILURE); 
    case 0: /* Child Process */ 
     do_child(); 
     break; 
    default:/* Parent Process */ 
     break; 
} 
/* Pass a structure to FIFO */ 
student *info; 
info = (student *)malloc(sizeof (student)) ; 
info->name = (char *)calloc(sizeof(char), 10); 
strcpy(info->name, "jack"); 
info->age = 27; 
info->sex = (char *)calloc(sizeof(char), 10); 
strcpy(info->sex , "Male"); 

/* Parent Opening FIFO */ 
printf("parent opening FIFO \n"); 
if((fifo = open(FIFO_NAME, O_RDWR)) < 0) { 
    perror("open in parent failed"); 
    exit(EXIT_FAILURE); 
} 

/* 
** Write some thing into FIFO so child can read it 
*/ 
printf("parent writing to FIFO \n"); 
w_byte_parent = write(fifo, info, sizeof(struct student_info)); 
if(w_byte_parent < 0) 
    printf("Nothing was written to FIFO by parent\n"); 
printf("Wrote %d bytes to FIFO\n",w_byte_parent); 
} 
+0

父節點和子節點都退出交換機(fork())。那是你想要的嗎? –

回答

3

讓我們從基礎開始。編譯使用GCC代碼與-Wall選項:

$ gcc fifo.c -o fifo -Wall 
fifo.c: In function ‘do_child’: 
fifo.c:33: warning: implicit declaration of function ‘read’ 
fifo.c:24: warning: unused variable ‘i’ 
fifo.c:23: warning: unused variable ‘buffer’ 
fifo.c: In function ‘main’: 
fifo.c:48: warning: implicit declaration of function ‘mkfifo’ 
fifo.c:58: warning: implicit declaration of function ‘fork’ 
fifo.c:88: warning: implicit declaration of function ‘write’ 
fifo.c:42: warning: unused variable ‘i’ 
fifo.c:42: warning: unused variable ‘ch’ 
fifo.c:41: warning: unused variable ‘buffer’ 
fifo.c:92: warning: control reaches end of non-void function 

忽略所有的未使用的變量的問題,你需要包括<unistd.h><sys/stat.h>得到的readmkfifoforkwrite適當聲明。再次編譯:

$ gcc fifo.c -o fifo -Wall -Wno-unused 
fifo.c: In function ‘do_child’: 
fifo.c:35: error: incompatible type for argument 2 of ‘read’ 
fifo.c: In function ‘main’: 
fifo.c:94: warning: control reaches end of non-void function 

你傳遞一個student實例作爲參數2 read,但它需要一個void*指針。你需要通過student實例的地址&child。此外,這將是很好的明確返回值的形式main(),雖然這不是絕對必要的,因爲無法返回一個值的形式main()隱式(爲main()功能,但只)返回0。

但即使有這些錯誤糾正,你仍然可以看到父進程的輸出的兩倍。爲什麼?因爲父進程和子進程都在執行switch語句下面的代碼塊。子進程調用do_child()函數並且永不退出,所以它返回並繼續執行。

簡單的修復方法是確保在do_child()結束時或在呼叫返回後立即退出子進程。

+0

我覺得你已經走到了一半。 OP將要知道的下一件事是如何傳遞由struct成員指向的動態分配的值。 – pilcrow

+0

'open()'的聲明在''中 - 很奇怪,但如此。 –

+0

@pilcrow:是的,的確如此。在這種情況下,由於子進程是用'exec'從父進程派生出來的,並且由於數據結構沒有被修改,所以可以在FIFO中耙指針並使它們在接收進程中可用。但是,只要其中一個進程修改了數據,寫入時複製就會啓動,並且進程不再共享內存(除非他們事先明確設置了共享內存區域),並且您需要使用適當的序列化機制。 –