2

したがって、以下のプログラムは、位置「shmid」にある共有メモリの一部にアクセスし、それをポインタ「total」に接続します。次に、このメモリにアクセスして変更する子プロセスが作成され、完了すると、別の子プロセスが作成されて同じことを実行し、次に3番目の子が作成されます。これらの3つの子が値の変更と実行を終了すると、親プロセスは共有メモリを解放し、プログラムが終了します。この「shmctl」ブロックが望ましい効果をもたらすだろうという印象を受けましたが、そうではないようです。

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

このブロックに続いて、実行中に以前と同じ値を出力した次のものがあるので、私はそうは思わない。これは、ポインタがまだ同じビットのメモリにアクセスしていることを示しているのではありませんか、それとも私が間違っているのでしょうか。

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*****/
4

1 に答える 1

2

shmctlのマニュアルページから:

IPC_RMID

破棄するセグメントにマークを付けます。セグメントが実際に破棄されるのは、最後のプロセスがセグメントをデタッチした後(つまり、関連する構造体shmid_dsのshm_nattchメンバーがゼロの場合)のみです。発信者は、所有者または作成者であるか、特権を持っている必要があります。セグメントに破棄のマークが付けられている場合、IPC_STATによって取得された関連データ構造のshm_perm.modeフィールドの(非標準の)SHM_DESTフラグが設定されます。

呼び出し元は、セグメントが最終的に破棄されることを確認する必要があります。そうしないと、障害が発生したページがメモリまたはスワップに残ります。

つまり、コードはセグメントに破棄のマークを付けますが、プログラムが終了するまでセグメントを切り離しません。

以前に切り離したい場合は、を呼び出すことができますshmdt(total);。その最後のprintfの前にこれを行うと、printfがセグメンテーション違反を引き起こす可能性があります。

于 2013-02-03T07:05:11.357 に答える