我正在开发基于UNIX的操作系统(Lubuntu 14.10。我有几个进程需要将消息打印到同一个文件和std输出。
当我将信息打印到屏幕上时,它按照我想要的方式按照出现的顺序工作。 E.g:
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
是全局FILE *
。
任何帮助将不胜感激。谢谢!
答案 0 :(得分:2)
fprintf()
无效。它很容易被转换成多次调用write()
来实际写出数据,就像你发布的那样。您只需拨打fprintf()
一次,并且会在write()
内多次调用以实际将数据写入文件。
你需要使用open( filename, O_WRONLY | O_CREAT | 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 );
}
答案 1 :(得分:2)
最有可能的问题是,文件输出是完全缓冲的,因此每个进程的输出都不会出现,直到流的标准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()
的大小增加到您需要原子编写的最大行长度。
如果仍然不够好,或者您需要一次能够编写一组行,那么您必须使用{{3}中的文件描述符来寻求解决方案{&#39; s Andrew Henle。您可能希望查看answer的O_SYNC
和O_DSYNC
选项。
答案 2 :(得分:0)
当您写入终端(isatty(fptr)
---请参阅 isatty(3) ---返回true
)时,刷新缓冲区在stdio中有所不同输出到文件。对于文件, stdio 输出仅在缓冲区填满时执行 write(2)系统调用,这会使所有消息一起显示(因为每个缓冲区都会刷新在退出时,它们填充一个单独的输出缓冲区)在ttys上,当缓冲区填满或当\n
字符输出到缓冲区时,输出被刷新(作为对缓冲的妥协/非缓冲)
您可以在fflush(fptr);
之后使用fprintf(fptr, ...);
强制执行缓冲区刷新,或者甚至执行fflush(NULL);
(在一次调用中刷新所有输出缓冲区)。
但是,要小心,因为写操作是控制调用的原子性(而不是fprintf调用)所以,如果你必须在一个fprintf调用中写几页输出,请准备好接受混乱的输出。