0

我有一个项目,其中几个编写器(使用多线程)使用一个进程写入,而单个读取器(单线程)通过另一个进程读取此写入。作家和读者一直在做同样的事情。Writer 在每次写入时都会写入可变的数据行,因此我无法使用缓冲区。我想使用我可以写这个的内存映射文件或单个文件。

我对同步感到困惑。由于我在 2 个过程中执行此操作,因此不能使用条件变量,因此只需要使用信号量。

现在,如果我使用信号量,那么几个写入器会同时写入,因此它会覆盖另一个写入器之前写入的数据,当读取器读取时,它将只读取最新的写入,我将丢失所有以前的写入。我希望读取器应该读取发生的每一次写入。有些延迟是可以接受的。

我也可以尝试将一件事全部写入文件,然后让线程休眠一段时间,然后在休眠期间读取它们,但这样做我可能会丢失一些可能在休眠期间到达的数据。

知道如何实现吗?任何帮助都很棒。我正在使用 C 和 Linux 平台。因此,请建议与 C 和 Linux/Unix 相关。

Update1:​​我已经为信号量完成了以下步骤:

                       semget(key,2,flag)  //define 2 semaphore
         semctl(semid,0,SETVAL,0)  //Initialize value for semaphore 0
         semctl(semid,1,SETVAL,0)  //Initialize value for semaphore 0

         writer_lock(semid)  //writer lock
              struct sembuf action[2] ;
            action[0].sem_num = 0;
            action[0].sem_flg = SEM_UNDO;
            action[0].sem_op  = 0 ;
            action[1].sem_num = 1;
            action[1].sem_flg = SEM_UNDO;
            action[1].sem_op  = +1 ;
              semop(sem_id,action,2);

          release_writer_lock
              struct sembuf action[1] ;
            action[0].sem_num = 1;
            action[0].sem_flg = SEM_UNDO;
            action[0].sem_op  = -1 ;
             semop(sem_id,action,1);

         reader_lock(semid)
               struct sembuf action[2] ;
            action[0].sem_num = 1;
            action[0].sem_flg = SEM_UNDO;
            action[0].sem_op  = 0 ;
            action[1].sem_num = 0;
            action[1].sem_flg = SEM_UNDO;
            action[1].sem_op  = +1 ;
             semop(sem_id,action,2) 


          release_reader_lock
              struct sembuf action[1] ;
            action[0].sem_num = 0;
            action[0].sem_flg = SEM_UNDO;
            action[0].sem_op  = -1 ;
             semop(sem_id,action,1);

        ** writer end***
        writer_lock(semid)
          /* my work*/
        release_writer_lock(semid)


        ** reader end***
        reader_lock(semid)
          /* read and clear */
        release_reader_lock(semid)
4

2 回答 2

1

您需要使用一对信号量 - 一个信号量阻止阅读器,直到作者创建要阅读的内容,另一个阻止作者,直到阅读器阅读现有消息。

将读取信号量初始化为 0,将写入信号量初始化为 1。读取器执行以下操作:

sem_wait(&read_sem);
/* Read and remove message */
sem_post(&write_sem);

作家们这样做:

sem_wait(&write_sem);
/* Write message */
sem_post(&read_sem);
于 2013-11-12T06:13:15.480 回答
0

注:
1。如果读取器进程正在读取,则写入器进程不应写入。
2 . 如果任何写入器线程正在写入,则读取器进程无法读取,因为源文件(如您所述)正忙。

因此,应该只有一个同步变量(比如 sem_id)应该由读取器进程和写入器进程使用。此外,所有编写器线程都应使用此变量以避免覆盖。

写程序

 writer_thread1 
  {
   writer_lock(sem_id);
     write the data
   release_writer_lock(sem_id);
  }
 writer_thread2 
  {
   writer_lock(sem_id);
     write the data
   release_writer_lock(sem_id);
  }

读者进程

  reader 
  {
   reader_lock(sem_id);
     read the data
   release_reader_lock(sem_id);
  }

编辑
很抱歉忽略了消息槽限制。但是我建议这个解决方案认为您正在使用共享文件(您正在写入和读取),正如您在问题中提到的那样。此外,您的问题提到它有几个编写器线程,但很明显它不可能同时写入共享位置。
如果只有一个消息槽,则只能按照@caf 所述进行。但是,我认为使用多个写入器线程没有用,因为任何写入器线程只能在读取器进程读取数据时写入数据。

于 2013-11-12T06:39:25.633 回答