C 按发生顺序写入具有不同进程的同一文件
我正在使用基于UNIX的操作系统(Lubuntu 14.10)。我有几个进程需要将消息打印到同一个文件和std输出 当我将信息打印到屏幕上时,它会按照我想要的方式工作,按发生顺序。例如:C 按发生顺序写入具有不同进程的同一文件,c,linux,process,C,Linux,Process,我正在使用基于UNIX的操作系统(Lubuntu 14.10)。我有几个进程需要将消息打印到同一个文件和std输出 当我将信息打印到屏幕上时,它会按照我想要的方式工作,按发生顺序。例如: Process1_message1 Process2_message1 Process3_message1 Process1_message2 Process2_message2 Process3_message2 ... 但是,当我检查输出文件时,它如下所示: Process1_message1 Proce
Process1_message1
Process2_message1
Process3_message1
Process1_message2
Process2_message2
Process3_message2
...
但是,当我检查输出文件时,它如下所示:
Process1_message1
Process1_message2
Process2_message1
Process2_message2
Process3_message1
Process3_message2
...
我使用fprintf(FILE*ptr,char*str)
将消息写入文件
注意:我在主进程中以以下格式打开了文件:
fptr=fopen("output.txt", "a");
其中fptr
是一个全局文件*
感谢您的帮助。fprintf()
不起作用。它很容易被转换成多次调用write()
来实际写出数据,就像您发布的那样。您调用fprintf()
一次,然后在封面下多次调用write()
将数据实际写入文件
您需要使用open(filename,O_WRONLY | O_create | O_APPEND,0600)
,并编写类似这样的数据,以确保只调用write()
一次,这保证是原子的:
ssize_t myprintf( int fd, const char *fmt, ... )
{
char buffer[ 1024 ];
ssize_t bytesWritten;
va_list argp;
va_start( argp, fmt );
int bytes = vsnprintf( buffer, sizeof( buffer ), fmt, argp );
if ( bytes < sizeof( buffer ) )
{
bytesWritten = write( fd, buffer, bytes );
}
// buffer was too small, get a bigger one
else
{
char *bufptr = malloc( bytes + 1 );
bytes = vsnprintf( bufptr, bytes + 1, fmp, argp );
bytesWritten = write( fd, bufptr, bytes );
free( bufptr );
}
return( bytesWritten );
}
ssize\u t myprintf(int-fd,const-char*fmt,…)
{
字符缓冲区[1024];
使用编写的字节;
va_列表argp;
va_启动(argp、fmt);
int bytes=vsnprintf(buffer,sizeof(buffer),fmt,argp);
如果(字节<大小(缓冲区))
{
BytesWrite=写入(fd、缓冲区、字节);
}
//缓冲区太小,请换一个大的
其他的
{
char*bufptr=malloc(字节+1);
bytes=vsnprintf(bufptr,bytes+1,fmp,argp);
BytesWrite=写入(fd,bufptr,字节);
免费(bufptr);
}
返回(字节);
}
fprinf()
无法工作。它很容易被转换为多次调用write()
以实际写入数据,就像您发布的那样。您调用fprinf()
一次,在封面下,它会多次调用write()
将数据实际写入文件
您需要使用open(filename,O_WRONLY | O_create | O_APPEND,0600)
,并编写类似这样的数据,以确保只调用write()
一次,这保证是原子的:
ssize_t myprintf( int fd, const char *fmt, ... )
{
char buffer[ 1024 ];
ssize_t bytesWritten;
va_list argp;
va_start( argp, fmt );
int bytes = vsnprintf( buffer, sizeof( buffer ), fmt, argp );
if ( bytes < sizeof( buffer ) )
{
bytesWritten = write( fd, buffer, bytes );
}
// buffer was too small, get a bigger one
else
{
char *bufptr = malloc( bytes + 1 );
bytes = vsnprintf( bufptr, bytes + 1, fmp, argp );
bytesWritten = write( fd, bufptr, bytes );
free( bufptr );
}
return( bytesWritten );
}
ssize\u t myprintf(int-fd,const-char*fmt,…)
{
字符缓冲区[1024];
使用编写的字节;
va_列表argp;
va_启动(argp、fmt);
int bytes=vsnprintf(buffer,sizeof(buffer),fmt,argp);
如果(字节<大小(缓冲区))
{
BytesWrite=写入(fd、缓冲区、字节);
}
//缓冲区太小,请换一个大的
其他的
{
char*bufptr=malloc(字节+1);
bytes=vsnprintf(bufptr,bytes+1,fmp,argp);
BytesWrite=写入(fd,bufptr,字节);
免费(bufptr);
}
返回(字节);
}
最有可能的问题是文件输出已完全缓冲,因此每个进程的输出直到流的标准I/O缓冲区(在该进程中)已满时才会出现
您可以通过设置行缓冲来充分解决此问题:
FILE *fptr = fopen("output.txt", "a");
if (fptr != 0)
{
setvbuf(fptr, 0, _IOLBF, BUFSIZ);
…code using fptr — including your fork() calls…
fclose(fptr);
}
每次进程将一行写入缓冲区时,它都会被刷新。如果输出行长于BUFSIZ,则可能会遇到问题;然后,您可能希望将传递给setvbuf()
的大小增加到需要自动写入的最大行长
如果这仍然不够好,或者如果您需要能够一次写入多组行,那么您必须使用文件描述符(如in’s)找到解决方案。您可能需要查看
O_SYNC
和O_DSYNC
选项。最可能的问题是,文件输出已完全缓冲,因此直到流的标准I/O缓冲区(在该进程中)已满,每个进程才会出现
您可以通过设置行缓冲来充分解决此问题:
FILE *fptr = fopen("output.txt", "a");
if (fptr != 0)
{
setvbuf(fptr, 0, _IOLBF, BUFSIZ);
…code using fptr — including your fork() calls…
fclose(fptr);
}
每次进程将一行写入缓冲区时,它都会被刷新。如果输出行长于BUFSIZ,则可能会遇到问题;然后,您可能希望将传递给setvbuf()
的大小增加到需要自动写入的最大行长
如果这仍然不够好,或者如果您需要能够一次写入多组行,那么您必须使用文件描述符(如in’s)找到解决方案。您可能需要查看
O_SYNC
和O_DSYNC
选项。在stdio中写入终端时刷新缓冲区是不同的(isatty(fptr)
——请参阅isatty(3)——返回的true
)比输出到文件时返回的要多。对于文件,stdio输出仅在缓冲区填满时执行写入(2)系统调用,这使得所有消息一起显示(当每个缓冲区在退出时刷新时,它们在一个输出缓冲区中填满)在ttys上,当缓冲区填满时或当\n
字符输出到缓冲区时,输出被刷新(作为缓冲/非缓冲的折衷方案)
您可以在fprintf(fptr,…);
之后使用fflush(fptr);
强制刷新缓冲区,甚至可以执行fflush(NULL);
(在一次调用中刷新所有输出缓冲区)
但是,要小心,因为写操作是控制调用原子性的操作(不是fprintf调用),因此,如果您必须在一个fprintf调用中写入多页输出,请准备好接受混乱的输出。当您写入终端时,刷新缓冲区在stdio中是不同的(
isatty(fptr)
——请参见isatty(3)---返回的true
)比输出到文件时返回的要多。对于文件,stdio输出仅在缓冲区已满且此mak