Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 按发生顺序写入具有不同进程的同一文件_C_Linux_Process - Fatal编程技术网

C 按发生顺序写入具有不同进程的同一文件

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

我正在使用基于UNIX的操作系统(Lubuntu 14.10)。我有几个进程需要将消息打印到同一个文件和std输出

当我将信息打印到屏幕上时,它会按照我想要的方式工作,按发生顺序。例如:

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