2013-02-03 32 views
2

因此,下面的程序訪問位於「shmid」位置的共享內存並將其附加到指針「total」。然後創建一個子進程,用於訪問和修改這段內存,然後一旦完成,又創建另一個子進程並執行相同的操作,然後執行第三個子進程。一旦這三個孩子完成修改值並完成執行,父進程就釋放共享內存,然後程序退出。我的印象是,這個「shmctl」塊會產生預期的效果,但似乎沒有。正在釋放共享內存

if ((shmctl (shmid, IPC_RMID, (struct shmid_ds *) 0)) == -1) 
{ 
    perror ("shmctl"); 
exit (-1); 
} 

我不相信它,因爲這之後塊I具有執行過程中如之前打印出相同的值以下。這不表示指針仍然訪問相同的內存位,或者我誤解了嗎?

printf("value after memory release:%d\n", total->value); 

謝謝您的輸入!

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/shm.h> 
#include <stdlib.h> 
#include <unistd.h> 

/* change the key number */ 
#define SHMKEY ((key_t) 5600) //7890 

typedef struct 
{ 
    int value; 
} shared_mem; 

shared_mem *total; 

/*----------------------------------------------------------------------* 
* This function increases the value of shared variable "total" 
* by one all the way to 100000 
*----------------------------------------------------------------------*/ 

void process1() 
{ 
    int k = 0; 

    while (k < 100000) 
    { 
     k++; 
     total->value = total->value + 1; 
    } 
    printf ("From process1 total = %d\n", total->value); //process 1 prints out total and returns to main() function 
} 

/*----------------------------------------------------------------------* 
* This function increases the vlaue of shared memory variable "total" 
* by one all the way to 170000 
*----------------------------------------------------------------------*/ 

void process2() 
{ 
    int k = 0; 

    while (k < 170000) 
    { 
    k++; 
    total->value = total->value + 1; 
    } 
    printf ("From process2 total = %d\n", total->value); //process 2 prints out total and returns to main() function 
} 
/*----------------------------------------------------------------------* 
* This function increases the vlaue of shared memory variable "total" 
* by one all the way to 200000 
*----------------------------------------------------------------------*/ 

void process3() 
{ 
    int k = 0; 

    while (k < 200000) 
    { 
    k++; 
    total->value = total->value + 1; 
    } 
    printf ("From process3 total = %d\n", total->value); //process 3 prints out total and returns to main() function 
} 

/*----------------------------------------------------------------------* 
* MAIN() 
*----------------------------------------------------------------------*/ 

int main() 
{ 
    int shmid; 
    int pid1; 
    int pid2; 
    int pid3; 
    int ID; 
    int status; 

    char *shmadd; 
    shmadd = (char *) 0; 

/* Create and connect to a shared memory segmentt*/ 

if ((shmid = shmget (SHMKEY, sizeof(int), IPC_CREAT | 0666)) < 0) 
{ 
    perror ("shmget"); 
    exit (1); 
} 


if ((total = (shared_mem *) shmat (shmid, shmadd, 0)) == (shared_mem *) -1) 
{ 
    perror ("shmat"); 
    exit (0); 
} 

total->value = 0; 

if ((pid1 = fork()) == 0) //first child created 
{ 
    process1(); //first child process begins 
} 

while((ID = wait(&status)) != -1) //parent loops until 1st child is finished 
printf("child %d is finished\n", ID); //parent prints out returned value after child is finished 


if ((pid1 != 0) && ((pid2 = fork()) == 0)) //second child created 
{ 
    process2(); //second child process begins 
} 

while((ID = wait(&status)) != -1) //parent loops until 2nd child is finished 
printf("child %d is finished\n", ID); //parent prints out returned value after child is finished 

if ((pid1 != 0) && (pid2 != 0) && ((pid3 = fork()) == 0)) //third child created 
{ 
    process3(); //third child process begins 
} 

while((ID = wait(&status)) != -1) //parent loops until 3rd child is finished 
printf("child %d is finished\n", ID); //parent prints out returned value after child is finished 



if ((pid1 != 0) && (pid2 != 0) && (pid3 != 0)) 
{ 
    if ((shmctl (shmid, IPC_RMID, (struct shmid_ds *) 0)) == -1) 
    { 
perror ("shmctl"); 
exit (-1); 
    } 

    printf ("\t\t End of Program.\n"); //prints after all children have finished 

    printf("value after memory release:%d\n", total->value); 
} 
return 0; 
} 

/***** Note: loop for parent to wait for child processes to finish and print ID of each child*****/ 
+0

這是應該用C++標記嗎? C會更有意義? –

+0

我的不好。感謝您的支持。 – NicholasNickleby

回答

2

從了shmctl手冊頁:

IPC_RMID

標記段被破壞。在最後一個進程分離它之後(即當關聯結構shmid_ds的shm_nattch成員爲 爲零)時,段實際上只會被銷燬 。主叫方必須是所有者或創建者,或者有特權。如果段 已被標記爲銷燬,則將設置由IPC_STAT檢索到的關聯數據結構 中的shm_perm.mode字段的(非標準)SHM_DEST標誌 。

調用者必須確保段最終被銷燬; 否則其出現故障的頁面將保留在內存或 交換中。

即您的代碼標記段銷燬,但不會將其分離,直到程序退出。您可以撥打shmdt(total);。如果在最後一個printf之前執行此操作,printf可能會導致seg故障。

+0

優秀。非常感謝你的解釋! – NicholasNickleby