多进程单读取器在多进程环境中同步?

时间:2013-11-12 05:58:37

标签: c linux multithreading synchronization

我有一个项目,其中几个编写器(使用多线程)使用一个进程写入,单个读取器(单线程)通过另一个进程读取此写入。作家和读者继续这样做。 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)

2 个答案:

答案 0 :(得分:1)

你需要使用一对信号量 - 一个用来阻止阅读器,直到一个作者创建了一些要读取的东西,另一个用来阻止作者,直到读者读完现有的信息为止。

将读取信号量初始化为0,将写入sempahore初始化为1.读者:

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

作家这样做:

sem_wait(&write_sem);
/* Write message */
sem_post(&read_sem);

答案 1 :(得分: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的说明完成。但是,我认为没有使用多个编写器线程,因为任何编写器线程只能在读取器进程读取它时写入数据。