Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 多进程环境中的多个写入程序单读取器同步?_C_Linux_Multithreading_Synchronization - Fatal编程技术网

C 多进程环境中的多个写入程序单读取器同步?

C 多进程环境中的多个写入程序单读取器同步?,c,linux,multithreading,synchronization,C,Linux,Multithreading,Synchronization,我有一个项目,其中几个编写器(使用多线程)使用一个进程进行编写,而单个读取器(单线程)通过另一个进程读取此编写。作家和读者一直在做同样的事情。Writer在每次写入时都写入可变的数据行,所以我不能使用缓冲区。我认为可以使用内存映射文件,也可以使用单个文件来编写 我对同步感到困惑。由于我在2进程中这样做,所以不能使用条件变量,所以只需要使用信号量 现在,若我使用信号量,那个么几个写入程序同时写入,所以它会覆盖另一个写入程序之前写入的数据,当读卡器读取时,它将只读取最近写入的数据,我将丢失所有以前写

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

我对同步感到困惑。由于我在2进程中这样做,所以不能使用条件变量,所以只需要使用信号量

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

我也可以尝试一件事,把所有的东西都写在一个文件中,然后让线程休眠一段时间,然后在休眠期间读取它们,但这样做可能会丢失一些在休眠期间到达的数据

你知道如何实现吗?任何帮助都很好。我使用的是C和Linux平台。因此,请推荐与C和Linux/Unix相关的

更新1: 对于信号量,我已经完成了以下步骤:

                       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)

您需要使用一对信号量—一个用于阻止读卡器,直到编写器创建了要读取的内容;另一个用于阻止编写器,直到读卡器读取了现有消息

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

sem_wait(&read_sem);
/* Read and remove message */
sem_post(&write_sem);
作者们:

sem_wait(&write_sem);
/* Write message */
sem_post(&read_sem);
注:
1。如果读取器进程正在读取,则不应写入任何写入进程。
2。如果任何写入线程正在写入,则由于源文件(如您所述)正忙,读卡器进程无法读取

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

编写器进程

 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);
  }
编辑
很抱歉,我忽略了邮件槽的限制。但我建议使用这种解决方案,因为我认为您使用的是一个共享文件(您在其中写作和阅读),正如您在问题中提到的那样。另外,您的问题提到它有几个writer线程,但很明显,不可能同时写入共享位置。

如果只有一个消息槽,则只能按照@caf所述进行。但是,我认为使用多个writer线程是没有用的,因为任何writer线程只能在reader进程读取数据时写入数据。

我在我的帖子中做了一些更改,你能建议我使用它而不是使用sem\u wait和sem\u post吗。另外,请建议,如果我使用正常的文件,并打开几个会话的写作会不会产生一些问题?或者我应该使用momory映射文件吗?您的代码使用旧式的SysV信号量,我建议改用POSIX信号量(
sem_init()
sem_wait()
sem_post()
)。您还有
-1
+1
的值,但方式不对——“锁定”操作应该减去一,而“解锁”则是错误的操作应该添加一个<代码>释放\写入\锁定和
释放\读取\锁定
操作错误的信号量。明白了。。谢谢你的指点错误。虽然我不知道如何使用它,但我会纠正它,并尝试用POSIX std实现它。将查看一些教程。@tusargoel:如果您愿意,可以使用SysV sempahores-注意
+1
sem\u op
对应于
sem\u post()
,而
-1
sem\u op
对应于
sem\u wait()
。此解决方案的问题是,后续写入程序将覆盖早期未读邮件-OP意味着只有一个可用的邮件槽,后续写入程序应等待,直到先前写入的邮件已被读取。@caf我正在实现相同的方法。据你所说,它不能正常工作。需要使用POSIX方式,但我们有什么方法可以更正此问题吗?@caf抱歉,我忽略了这一点。现在编辑。由于您的解决方案使用了两个信号量,因此在我看来,编写器线程只能在读取器进程读取前一个信号量时进行写入。因此,尽管有几个编写器,但我们不能使用它们,因为只有reader进程有
sem\u post(&read\u sem)
,每个编写器线程都在其上等待。@RaviKant:是的,但这并不一定意味着有多个编写器就没有意义。也许编写者正在执行一些长时间运行的、资源密集型的任务,并将结果传递给单个阅读器,阅读器处理结果的速度要比编写者生成结果的速度快得多。