2015-12-07 56 views
2

我正在嘗試做第一個子函數,例如,打印出一個字符串:hello!,並返回到父進程。然後,我爲第二個子函數分配n個進程,這將計算共享內存數量。我想那裏最後只顯示了一個「全部完成」,但它顯示了兩個?謝謝你的幫助!與分叉進程混淆?

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/shm.h> 
#include <string.h> 
#include <sys/ipc.h> 
#include <sys/sem.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
#include <errno.h> 
#include <sys/wait.h> 
#include <fcntl.h> 

#define NUM_LINES 5 

char * shm; 

void child_func(char *shm) 
{ 
     while (atoi(shm) != NUM_LINES) 
     { 
      // P(sem); 
      printf("now reading word:%d\n", atoi(shm)); 
      *shm+=1; 
      // V(sem); 
     } 

     exit(0); 
} 

void parent_func(pid_t pid) 
{ 
    int status; 
    pid_t pid_wait; 
    do 
    { 
     pid_wait = waitpid(pid, &status, WNOHANG); 
    }while (pid_wait != pid); 
    // printf("Process %d done\n", getppid()); 
} 

int main(int argc, char const *argv[]) 
{ 
    /* declarations */ 
    pid_t pid[8]; 
    int ret, shmid, status,corpse, i, ave, n; 
    char fn[20]; 
    key_t key = 123; 
    char *string_back; 

    /* create share memory */ 
    if ((shmid = shmget(key, SHMSIZE, IPC_CREAT|666)) <0) 
    { 
     perror("shmget"); 
     exit(1); 
    } 
    /* attach shm */ 
    if ((shm = shmat(shmid, NULL, 0)) == (char*)-1) 
    { 
     perror("shmat"); 
     exit(1); 
    } 
    /* init shm value */ 
    *shm = '0'; 

    /* input */ 
    printf("please enter n:\n"); 
    scanf("%d", &n); 

    /* section 1 */ 
     pid[0] = fork(); 
     if (pid[0] == 0) // child processes 
     { 
      printf("hello !\n"); 
     } 
     else if (pid[0] >0) 
     { 
      parent_func(pid[0]); 
     } 

    /* section 2 */ 
    for (i=0;i<n;i++) 
    { 
     pid[i] = fork(); 
     if (pid[i] == 0) // child processes 
     { 
       child_func(shm); 
     } 
     else if (pid[i] >0) 
     { 
      parent_func(pid[i]); 
     } 
    } 

    printf("all done\n"); 
    /* detach shm */ 
    shmdt(shm); 
    /* destroy shm */ 
    int retval = shmctl(shmid, IPC_RMID, NULL); 
    if (retval < 0) perror("remove shm"); 

    return 0; 
} 
+1

「部分1」中的第一個子進程沒有早先終止。 – user2864740

+0

好吧,我知道它可能不會更早終止,但爲什麼它會打印出「全部完成」兩次? – KennyYang

+0

由於第一個子進程到達「全部完成」語句(因爲它在此之前不會終止),然後父進程在等待所有子進程之後也會在稍後到達該語句。 – user2864740

回答

0

在第一部分中添加退出(0)後,我只在最後一次得到一個「全部完成」,這是我想要的答案。

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/shm.h> 
#include <string.h> 
#include <sys/ipc.h> 
#include <sys/sem.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
#include <errno.h> 
#include <sys/wait.h> 
#include <fcntl.h> 

#define NUM_LINES 5 

char * shm; 

void child_func(char *shm) 
{ 
     while (atoi(shm) != NUM_LINES) 
     { 
      // P(sem); 
      printf("now reading word:%d\n", atoi(shm)); 
      *shm+=1; 
      // V(sem); 
     } 

     exit(0); 
} 

void parent_func(pid_t pid) 
{ 
    int status; 
    pid_t pid_wait; 
    do 
    { 
     pid_wait = waitpid(pid, &status, WNOHANG); 
    }while (pid_wait != pid); 
    // printf("Process %d done\n", getppid()); 
} 

int main(int argc, char const *argv[]) 
{ 
    /* declarations */ 
    pid_t pid[8]; 
    int ret, shmid, status,corpse, i, ave, n; 
    char fn[20]; 
    key_t key = 123; 
    char *string_back; 

    /* create share memory */ 
    if ((shmid = shmget(key, SHMSIZE, IPC_CREAT|666)) <0) 
    { 
     perror("shmget"); 
     exit(1); 
    } 
    /* attach shm */ 
    if ((shm = shmat(shmid, NULL, 0)) == (char*)-1) 
    { 
     perror("shmat"); 
     exit(1); 
    } 
    /* init shm value */ 
    *shm = '0'; 

    /* input */ 
    printf("please enter n:\n"); 
    scanf("%d", &n); 

    /* section 1 */ 
     pid[0] = fork(); 
     if (pid[0] == 0) // child processes 
     { 
      printf("hello !\n"); 
      /* problem solved here */ 
      exit(0); 
     } 
     else if (pid[0] >0) 
     { 
      parent_func(pid[0]); 
     } 

    /* section 2 */ 
    for (i=0;i<n;i++) 
    { 
     pid[i] = fork(); 
     if (pid[i] == 0) // child processes 
     { 
       child_func(shm); 
     } 
     else if (pid[i] >0) 
     { 
      parent_func(pid[i]); 
     } 
    } 

    printf("all done\n"); 
    /* detach shm */ 
    shmdt(shm); 
    /* destroy shm */ 
    int retval = shmctl(shmid, IPC_RMID, NULL); 
    if (retval < 0) perror("remove shm"); 

    return 0; 
}