c - 彼得森算法的错误

标签 c linux critical-section

嘿,我想知道是否有人可以帮助我弄清楚为什么我的 Peterson 算法实现不起作用。

目前我的输出是:

From Process total = [number > 100,000]
Child with ID -1 has just exited
Child with ID [Child ID] has just exited
     End of Program
From Process 2 total = [number > 200,000]
Child with ID -1 has just exited

我的输出应该是这样的:

From Process 1: total = 60234. 
From Process 2: total = 100000.
Child with ID 2412 has just exited. 
Child with ID 2411 has just exited.
     End of  Program.

出于某种原因,我的一个子进程的 ID 为 -1,这意味着存在某种错误(我认为)。我不知道这是怎么回事。我仍然对这个算法如何工作感到困惑,因为如果 turn 永远不会改变,那么该进程如何访问临界区?

我的代码如下:

#define TRUE 1
#define FALSE 0


typedef struct
{
  int value;
  int flag[2] = {FALSE, FALSE};
  int turn = 0;
} shared_mem;


shared_mem *total;



       void process1 ()
{
  int k = 0;

  while (k < 100000)
    {
      total->flag[0] = TRUE;
      total->turn = 1;

      //prevent P1 from access CS
      while(total->flag[1] == TRUE && total->turn == 1)
      {
        int k = 0;
        if(k = 0)
        {
            total->p2Block = total->p2Block + 1;
        }
        k++;
      };

      k++;
      total->value = total->value + 1;

      total->flag[0] = FALSE;
    }

  printf("Process 2 interrupted %d times in critical section by Process 1.\n", total->p2Block);
  printf ("From process1 total = %d\n", total->value);
}

    void process2 ()
{
  int k = 0;

  while (k < 200000)
    {
      total->flag[1] = TRUE;
      total->turn = 0;
      int critical;
      //prevent P2 from accessing CS
      while(total->flag[0] == TRUE && total->turn == 0)
      {
            int k = 0;
            if(k = 0)
            {
                total->p2Block = total->p1Block + 1;
            }
        k++;
      };

      k++;
      total->value = total->value + 1;
      critical++;

      total->flag[1] = FALSE;
    }

  printf("Process 1 interrupted %d times in critical section by Process 2.\n", total->p1Block);
  printf("From process2 total = %d\n", total->value);
}



main()
{
  int   shmid;
  int   pid1;
  int   pid2;
  int   ID;
  int   status;
  int   waitID1, waitID2;

  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;
  total->flag[0] = FALSE;
  total->flag[1] = FALSE;
  total->turn = 0;
  total->p1Block = 0;
  total->p2Block = 0;

  if ((pid1 = fork()) == 0)
    process1();

  if ((pid1 != 0) && (pid2 = fork()) == 0)
    process2();

  do{
    waitID1 = waitpid(pid1, &status, 0);
    waitID2 = waitpid(pid2, &status, 0);
    if(WIFEXITED(status) && waitID1 != -1)
    {
      printf("Child with ID %d has just exited\n", waitID1);
    }
    if(WIFEXITED(status) && waitID2 != -1)
    {
      printf("Child with ID %d has just exited\n", waitID2);
    }
  }while (!WIFEXITED(status) && !WIFSIGNALED(status));  

  if ((pid1 != 0) && (pid2 != 0))
    {

      if ((shmctl (shmid, IPC_RMID, (struct shmid_ds *) 0)) == -1)
      {
        perror ("shmctl");
        exit (-1);
      }
      printf ("\t\t  End of Program.\n");
    }
} 

最佳答案

fork()wait() 函数在失败时返回 -1。你不测试那个。

此外,您的程序中涉及的所有进程都调用wait()。该调用肯定会在至少一个进程中失败(返回 -1),因为无论 fork() 的成功或失败,都会有一个进程没有任何子进程。

但是,您的程序存在更严重的问题。似乎假定普通全局变量 flagturn 将在进程之间共享,但由于我看到您使用 shmget(),我假设你知道那实际上不会发生。

即使您将 flagturn 移动到您的共享内存段中,您仍然会遇到同步问题:您不能依赖一个进程来查看另一个进程对及时共享内存——或者,事实上,曾经——没有采用适当的同步。与 SysV 风格的共享内存段自然搭配的同步辅助工具是 SysV 风格的信号量。

当您实现同步时,自然会发现您不再需要使用繁忙的循环来让每个进程等待另一个进程。

关于c - 彼得森算法的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35527557/

相关文章:

linux - 如何将文件从给定目录复制到目标目录的随机目录

python - Popen 命令链接返回 0 而不是 1

php - ICBC Payment Gateway – PHP infosec.so 动态共享库

windows - Mutex 是否调用系统调用?

C 编程 - 平均

c - 关于 C 参数提升的问题

multithreading - Delphi线程: CriticalSection not being "Release' d"when using Synchronize inside its method

C++ pragma omp critical(名称)

c - Toupper 不适用于 char 数组

c - 为什么在初始化结构时出现段错误?