【问题标题】:C shared memory integer doesn't get updatedC共享内存整数没有得到更新
【发布时间】:2020-09-17 17:18:25
【问题描述】:

我正在用 C 实现读写器问题。如您所见,我分叉了 2 次,每次都会生成一个需要等待一段时间的读取器或写入器。我还使用两个信号量满足了线程安全性。首先是保护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

【问题讨论】:

标签: c posix shared-memory


【解决方案1】:

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

【讨论】:

【解决方案2】:

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

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

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

如您所见,我分叉了 2 次,每次都会生成一个等待时间较长的读取器或写入器。

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

在第一个for循环中,在循环的第一次迭代中分叉的子进程将按预期调用writer函数,但之后不会跳出循环。相反,它将执行循环的第二次迭代。这意味着您有两个进程执行循环的第二次迭代。

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

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    • 2019-10-25
    • 2019-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多