正在从C中写入文件的处理队列

问题描述 投票:1回答:1

我正在编写C代码,它将其任务从文件执行(在Linux上)。有多个进程并行写入此文件(使用echo "COMMAND" >> "file_queue_input")。直到现在,仍使用此逻辑:

  rename (file_queue_input, file_queue_process);
  queue_file = fopen (file_queue_process,"r");
  while (!feof (queue_file))
  {
      <process file line by line>
  } // end of while reading queue file
  fclose (queue_file);
  remove (file_queue_process);

想法是,通过将文件移动到另一个名称,新的描述符将针对原始名称打开,并且将读取所有命令。但是现实表明,某些命令在途中丢失了。

[我的假设:写描述符在移动操作之前打开,对新名称保持打开状态,但尚未写入其数据,没有数据的情况下读取文件,然后写描述符写入数据,但是由于读取循环已在此处完成没有人读取数据,文件被删除。如何预防?

读取频繁写入的队列文件的正确方法是什么?我很确定我不是对此感兴趣的第一人,但是找不到正确的问题让Google找到有用的东西。

根据注释的要求,在此处添加了最小的示例(请注意,我已经进行了所有检查,记录等...,但想使代码尽可能短,因此删除了并非绝对必要的所有内容):https://drive.google.com/open?id=1U9vh7DEUPopuyTJ5j4J8T8FqVj812AzV

它包含2个文件:Queue_read_test.c(我正在编写的文件,可以控制该文件的执行方式,bash_load_generator.sh是我完全无法控制的模拟文件编写器的文件。

首先我们检查数字并运行生成器,当生成器完成时,我们运行队列读取器:

ice@center:/usr/src/Demo$ ./bash_load_generator.sh
All commands started waiting for finish
DONE
ice@center:/usr/src/Demo$ ./Queue_read_test # Stop with CTRL+C
^CFinished with 10000 queue items read: ice@center:/usr/src/Demo$

然后,我们先运行队列读取器,然后在第二个屏幕中运行生成器,在所有操作完成并且队列文件消失之后,我们停止队列读取器(这是现实生活中的场景:]

ice@center:/usr/src/Demo$ ./Queue_read_test # Run in screen 1
ice@center:/usr/src/Demo$ ./bash_load_generator.sh # Run in screen 2
All commands started waiting for finish
DONE
ice@center:/usr/src/Demo$ ls -ltra /tmp/ | grep queue # Check all was processed (no file should be found) in screen 2
ice@center:/usr/src/Demo$
ice@center:/usr/src/Demo$ # return to screen 1 and CTRL+C
^CFinished with 9905 queue items read: ice@center:/usr/src/Demo$

并且我们看到95条命令丢失了。这是为了说明所描述的问题,现在我的问题可能是由于您的评论更加精确:作为队列阅读器的作者,我可以做些什么来防止丢失命令? (无法修改队列编写器)我可以检查是否存在打开的文件描述符(猜测不是我不是root)。

c file queue atomic file-descriptor
1个回答
1
投票

整个问题实际上与所示代码无关,而与所确定的特定问题未充分涵盖的体系结构问题有关。在理解并解决了您工作所在的整个环境之前,问题将一直存在。而且,尽管解决您引用的问题会有所改善,但不足以解决这些潜在问题。在解决您引用的较低的代码级别问题时,这些问题包括您提到的多个进程,并访问一个非重入函数。本身显示的函数有其自己的一系列问题,但导致主要问题的一个问题是它不是线程安全的。它需要通过thread safe queues or tokens 进行外部保护,或者通过making it reentrant进行内部保护,从而确保线程安全的设计。简而言之,在不解决该功能正在使用的多线程环境的情况下,您只能尝试同时读取和写入单个文件。这是一个危险的设计。除此之外,并假设您的代码将被修改为protect it in a thread safe environment,请考虑另外两个要点,这些要点将改善所示的功能。

关于显示的代码...目前尚不清楚变量file_queue_process中包含什么。它应该是有效的filespec。 (即,如链接中所述,并且它指向的文件存在。)假设这是真的,那么下一个潜在的问题是您试图(1)输入poorly controlled loop(2),而没有先检查fopen()函数是否返回了有效的文件句柄。我建议使用fgets()作为循环控制是一种更安全的方法:

char line[80] = {0};
queue_file = fopen (file_queue_process,"r");
if(queue_file)
{
    while (fgets(line, 80, queue_file)
    {
        <process file line by line>
    } // end of while reading queue file
  fclose (queue_file);
}
remove (file_queue_process);
© www.soinside.com 2019 - 2024. All rights reserved.