fopen 频繁写文件问题,谢谢

recieve 线程收到消息后,转给另外一个线程B进行处理,B会打开一个文件,
并将消息内容写入文件,然后关闭文件。现在因为频繁写,出现了open file error问题。

2018/04/26 10:28:44.222 I ThreadB Process message: src= 5

2018/04/26 10:28:44.223 I ThreadB Process message: src= 0

2018/04/26 10:28:44.482 I ThreadB Process message: src= 1

2018/04/26 10:28:44.482 E ThreadB Error Opening ** file: C:\writting.txt

2018/04/26 10:28:44.482 I ThreadB Process message: src= 2

2018/04/26 10:28:44.482 E ThreadB Error Opening ** file: C:\writting.txt

2018/04/26 10:28:44.482 I ThreadB Process message: src= 3

2018/04/26 10:28:44.482 E ThreadB Error Opening ** file: C:\writting.txt

从log可以看到从src 0和5发来的message,可以正确处理,并更新文件,但是从src 1/2/3发来的消息,会在同一时间发起fopen操作,然后报error,请问大牛,在同一个线程中,为什么会出现这种情况呢?

code结构很老,没有看到用message queue或者同步的处理,基于这种现象,求解释。

谢谢

补充一下,需求是,有两个进程对同一个文件进行读写操作,进程A 要频繁写文件,更新里面的数据。进程B会每隔几秒读取一次文件中的数据,
因为操作太过于频繁,所以当前代码的处理是,先在一个临时文件中进行写操作,然后copy文件到另外一个文件中,由进程B对另一个文件进行读操作。
尽量分开读写操作,这是好多年前的做法了,现在应该有更好的解决办法了吧。

但是报error的情况也比较特殊,看log是毫秒级别的写,但是大多数情况没有问题,只有个别时间点,会集中进行两三次的fopen操作,这个我难以解释。
所以来求助了:)

首先你整个文件要确保只有B thread 访问,否则,多线程访问一定要加锁互斥保护。
基于这个前提,请检查一下,写入之后是否又及时关闭文件 fclose 关闭文件。
另外就是你这个读写操作太频繁了,毫秒级别,试试在 每次fclose之后 执行 system("sync"); 或者加1毫秒的delay,如果performance 要求不高。
IO比较慢,需要时间的

不明白你的意思。
不过你是否只有一个线程写文件呀。

recieve 线程收到消息后,转给另外一个线程B进行处理?
是如何“转给”的呀?按理说符合你的要求只有可能是采用数据池(写线程检索数据池)或 采用消息机制(写线程不停PeekMessage)才能实现。

一般情况下,满足你的要求会采用如下办法:
1、收线程:收到数据写入数据池,并且置起信号量。(收线程可以有多个)
2、写线程:Wait到信息量后,从数据池中取出数据,写文件。(写线程只能是一个)
3、进一步的话:数据池会采用空间换时间的方法,写时加锁,读时不加锁。
4、进一步的话:采用特殊机制,以保护硬盘,不然太热时,硬盘会很容易坏。
5、进一步的话:采用内存文件,无须每次fClose,文件本身会自动切换、自动压缩、自动删除。

追加,你将打印 “ThreadB” 改改, 改成打印 GetCurrentThreadId(),我怀疑你打印的不是同一个线程了。
不然无法解释了。

这种情况只能考虑线安全。将写文件的功能单独独立出来写一个方法,而这个方法进行线程安全的设置。为了提高性能,可以考虑使用队列术。

有些不解,问一下,是否有必要频繁的打开关闭文件,是每次写一个新文件?
如果是写一个文件,那么为什么打开和关闭不能放在线程的外面,这样不就可以一直写入了?

你可以自己验证了,很简单的了。
写一个死循环,不停的fopen,fwrite,fclose,一直循环100万次,不做任何延迟。
看是否会失败了,如不会就不是太快导致的,需要另找原因了。
如也会失败,则只能降低需求(延时)或 大改了。

我觉得,先打开文件,写数据,之后在复制之前,关闭文件,复制时不允许写入,用缓冲区或者怎样的,把获取的数据先存起来,复制完毕后再打开写入文件;不建议这样频繁打开写再关闭,你这个状况是打开关闭占用时间大于实际读入的频率

如果是严格一个线程打开,写,关闭,应该不会有问题。
所以问题估计出在另外有进程读,另一个进程读的时候,这个文件应该是不可做写打开。
不改机制的情况下,解决只能靠重试等待了,重试几次,每次等待一定毫秒数,要充分考虑读的时间设置一个合理的等待时间。

一个文件是允许多个线程同时打开和同时写的,如果不作互斥或者不按照一定的顺序写文件,预期写入的内容与最终写入文件的内容是有出入的。
多个线程写一定要加上互斥的信号量或者互斥锁,如果操作过程中有休眠的情况,就不能加自旋锁 。如果多个线程写文件,最好文件只打开一次,
然后再做资源互斥竞争写,这样就可以确保操作正确性。

根据你的补充,这其实 就是 多进程共享资源问题。
A process 的 thread B 进行写文件,但是你还有一个 B process 的某个thread 在读文件,不加保护 就会出现你遇到的错误,
这时候你可以考虑采用文件锁 来达到安全访问文件的目的,具体文件锁的使用方法,你可以参考一下:
https://www.cnblogs.com/yjbjingcha/p/6932162.html