C 多进程同时在文件中写入日志时锁定的可能性
我跟踪了在多进程环境中使用fputs和fflush的一些错误。 因此,我编写了如下简单代码:C 多进程同时在文件中写入日志时锁定的可能性,c,file,concurrency,locking,fopen,C,File,Concurrency,Locking,Fopen,我跟踪了在多进程环境中使用fputs和fflush的一些错误。 因此,我编写了如下简单代码: #include <stdio.h> #include <stdlib.h> #include <time.h> #include "windows.h" #define FILENAME "test.txt" int main(int argc , char *argv[]) { FILE *file; file = fopen(FILENA
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "windows.h"
#define FILENAME "test.txt"
int main(int argc , char *argv[])
{
FILE *file;
file = fopen(FILENAME , "a");
char buf[10240 + 100];
int pid = GetCurrentProcessId();
char buf_pid[20];
itoa(pid, buf_pid, 10);
int ii = 0;
while(ii < 10000)
{
time_t now = time(0);
struct tm tstruct;
char tt[80];
tstruct = *localtime(&now);
strftime(tt, sizeof(tt), "%Y/%m/%d %X", &tstruct);
strcpy(buf, tt);
strcpy(buf + strlen(tt), " ");
strcpy(buf + strlen(tt) + 1, buf_pid);
strcpy(buf + strlen(tt) + strlen(buf_pid), " ");
int len = strlen(tt) + strlen(buf_pid) + 1;
int a = rand()%10240;
char temp;
for(int i=0;i<a;i++)
{
temp = 'a' + rand()%25;
memset(buf + len, temp, 1);
len++;
}
buf[len++] = '\n';
buf[len++] = 0;
//Sleep(1);
printf("%d %s %d %d\n", ii, tt, pid, a);
fputs(buf, file);
fflush(file);**
ii++;
}
当然,结果如下所示
2019/11/08 22:57:14 261 rjatydimofugclqurclqecdrhvqsuwbvntmryktdl..
2019/11/08 22:57:14 261 ixoqldswtmhmjxqedqkprngproxvfpeuagbsxexje..
2019/11/08 22:57:14 261 skrhmutgpnkpwopudobptikjrfogdeairwyglcrqe..
2019/11/08 22:57:14 261 sqytmhtrnqkrtnfigwgcvvacgklmcjxinhehaqish..
2019/11/08 22:57:14 261 pvdvsfksuonldbwstvgflwjpecfymtfdrsnxlqqod..
2019/11/08 22:57:14 261 oqatxghvkhhjyvgnlymcjapedmpdakuuphbxnuqtd..
2019/11/08 22:57:14 261 ufrjkikbwvlvjejhpnndyebmgfjbmwvldsrlephow..
..
没有显式互斥,因此fput和fflush不是自动的。
我知道fputs是用操作系统内核中的句柄将文本写入文件的缓冲区
fflush是将缓冲区刷新到磁盘中。尽管没有同步对象,但访问每个缓冲区或刷新代码的顺序将保持不变
是否可能发生上述代码锁定?
或者,如果有2个文件正在由多个进程写入,
可能是锁吗
我找到了相关的好文章,但我不相信它真的发生了。
谢谢 程序中有一个“隐藏”锁-当代码打开日志文件时,它使用附加模式(“a”打开)。这将导致在
open
系统调用上设置标记O_APPEND
引述文开:
O_追加
文件以附加模式打开。在每次写入(2)之前,文件偏移量位于
文件的结尾,就像使用lseek(2)一样。文件偏移量的修改和
写入操作作为单个原子步骤执行
该标志保证每个“写入”操作(每当执行printf将行刷新到文件时执行)都是原子操作,并且不会与其他进程的输出混合同步和锁定发生在操作系统内核中,无需用户操作您是否在问,尽管没有锁定,为什么输出仍按预期显示?或者您正在询问是否需要锁定?或者您正在询问如何正确地从多个并发进程写入同一文件?或者其他什么?另外,请添加您的环境(特别是操作系统和文件系统),因为这将有助于提供具体的答案。我的问题是,上面的代码可能会出现一些情况。当然,我知道有必要使用同步对象以及如何改进它。但是有问题的代码还没有。我只是想知道是什么让程序挂起。该环境是HP unix,可能是2年内的最新版本。谢谢您指示HP unix,购买使用“start filewrite.exe”执行的代码,并调用GetCurrentProcessId。听起来像窗户。@dash-o,你好。对环境是HP unix。上面的代码是我在家里做的一个例子。
put()
不能保证使用单个write()
调用将数据实际写入文件。也不是任何其他基于文件*
的函数。从打开(…,O_WRONLY | O_APPEND…)写入文件描述符代码>使用写入(fd、buf、strlen(buf))代码>假设您没有得到部分write()
(技术上是允许的,但我从未在常规文件上看到过),这几乎肯定会是原子性的-很可能是因为系统不符合POSIX,但角落案例可能会暴露问题。@Andrewenle同意您的评论。但请参阅下面关于实际实施的评论。事实上,大多数现代系统在默认情况下都会使用512(最小值,即使是嵌入式系统)到4K的缓冲区。这边有消息吗。以新行终止,将以单写方式发送。输出是文件缓冲的,而不是tty,因此几乎可以保证随机交错。每个FPUT大约在40到10280个字符之间(由rand()控制)。
2019/11/08 22:57:14 261 rjatydimofugclqurclqecdrhvqsuwbvntmryktdl..
2019/11/08 22:57:14 261 ixoqldswtmhmjxqedqkprngproxvfpeuagbsxexje..
2019/11/08 22:57:14 261 skrhmutgpnkpwopudobptikjrfogdeairwyglcrqe..
2019/11/08 22:57:14 261 sqytmhtrnqkrtnfigwgcvvacgklmcjxinhehaqish..
2019/11/08 22:57:14 261 pvdvsfksuonldbwstvgflwjpecfymtfdrsnxlqqod..
2019/11/08 22:57:14 261 oqatxghvkhhjyvgnlymcjapedmpdakuuphbxnuqtd..
2019/11/08 22:57:14 261 ufrjkikbwvlvjejhpnndyebmgfjbmwvldsrlephow..
..