C共享内存整数没有得到更新

C shared memory integer doesn't get updated

我正在用 C 实现 reader-writers 问题。如您所见,我 fork 了 2 次,每次都会生成一个 reader 或 writer 并等待一些时间。我还使用两个信号量满足了线程安全性。首先是保护 rcount 的 mutex,其次是保护互斥的 writeblock。问题是我的计数器值没有改变,尽管我已经将它用作共享内存。

代码:

#include <stdio.h>
#include <semaphore.h>
#include <sys/ipc.h>
#include <sys/shm.h>





sem_t mutex,writeblock;
int data = 0,rcount = 0,shmid;


void reader()
{

 
  sem_wait(&mutex);
  rcount = rcount + 1;
  if(rcount==1)
   sem_wait(&writeblock);

  int *counter=shmat(shmid,NULL,0);
  printf("im a reader and counter is %d \n\n",*counter);
  shmdt(counter);
  sem_post(&mutex);

  sleep(1);
  sem_wait(&mutex);
  rcount = rcount - 1;
  if(rcount==0)
   sem_post(&writeblock);
  sem_post(&mutex);
}

void writer()
{


  sem_wait(&writeblock);

  int status=0;
  int *counter=shmat(shmid,NULL,0);
  *counter++;
  printf("im a writer and I incremented the counter and after that the counter is %d \n\n",*counter);
  shmdt(counter);

  sleep(1);
  sem_post(&writeblock);
}

int main()
{
    
  int i,b; 
  
  sem_init(&mutex,0,1);
  sem_init(&writeblock,0,1);
  
  shmid = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | 0666);
 
 if (shmid <0)
    printf("shmget err");
    



 if(fork()==0)
 {
    for (i=0;i<2;i++)
    {
        if(fork()==0)
        {
            sleep(i);
            writer();
            
            
        }
    }
 }

 else
 {
   for (i=0;i<2;i++)
    {
        if(fork()==0)
        {
            sleep(i*2);
            reader();
            
        }
    }
 }



}    

错误终端:

$ im a reader and counter is 0 

im a writer and I incremented the counter and after that the counter is 0 

im a writer and I incremented the counter and after that the counter is 0 

im a reader and counter is 0 

im a writer and I incremented the counter and after that the counter is 0 

im a reader and counter is 0

*counter++ 递增计数器,而不是计数器指向的内容。 (*counter)++ 递增计数器指向的内容。

正如另一个答案中已经指出的那样,表达式 *counter++ 是错误的。由于rules of operator precedence,所以一定是(*counter)++.

但是,即使修复了该错误,您的程序仍无法按预期运行,原因如下:

在您的问题中,您使用以下语句描述了程序的预期行为:

As you can see I fork 2 times and each time will generate a reader or writer with some amount of waiting.

你的这种说法是不正确的。你实际上 fork 了 7 次,也就是说你有 8 个进程。其中 3 个进程将调用 writer 函数,3 个将调用 reader 函数。

在第一个for循环中,在循环的第一次迭代中fork出来的子进程会正常调用writer函数,但之后就不会跳出环形。相反,它将执行循环的第二次迭代。这意味着您有两个进程执行循环的第二次迭代。

由于这可能不是故意的,我建议您将第一个 for 循环更改为以下内容:

for (i=0;i<2;i++)
{
    if(fork()==0)
    {
        sleep(i);
        writer();
        break; //breaks out of "for" loop
    }
}

你的第二个 for 循环(else 块内的循环)有同样的问题。

修复两个循环后,您现在只会分叉 5 次,因此总共有 6 个进程。这可能是你想要的。第一个进程创建了两个写入进程,还创建了一个创建两个 reader 进程的进程。

但是,您的程序的另一个问题是每个进程都有自己的 rcount 变量副本。因此,您必须对该变量执行与 counter 变量相同的操作(即使用共享内存)。

另外,您调用函数 sem_init 时参数 pshared 设置为零。根据 documentation of this function,只有在同一进程的线程之间共享信号量时才应该这样做。但是,使用 fork,您正在创建单独的进程。因此,您应该将此参数设置为非零值。