2

あるプロセス A が別のプロセス BI によってファイルに追加されたデータを読み取るプログラムを作成しています。BI は通知に ReadDirectoryChangesW を使用しています。問題は、コンテンツをファイルにフラッシュしているにもかかわらず、B のハンドルを閉じるまで通知が生成されないことです。 fflush を使用します。コードは以下のとおりです

ファイルライター:

int _tmain(int argc, _TCHAR* argv[])
{
    FILE *fp;

    fp=_fsopen("log.txt", "a", _SH_DENYNO);

    char str[4096];

    for(int i=1;i<4096;i++)
        str[i]=i;

    while(true){
        fwrite(str,1,4096,fp);
        fflush(fp);
        Sleep(2000);
    }

    return 0;
}

ファイルリーダー:

#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>
#include <conio.h>
#include <assert.h> 
#include <share.h>

void _tmain(int argc, TCHAR *argv[])
{
    FILE *fp;
    fp=_fsopen("C:\\Users\\dell\\Documents\\Visual Studio 2012\\Projects\\FileWriter\\FileWriter\\log.txt", "r", _SH_DENYNO);
    int last_size=0,new_size=0;

    if(fp==NULL)
        return ;

    HANDLE m_hMonitoredDir = CreateFile(TEXT("C:\\Users\\dell\\Documents\\Visual Studio 2012\\Projects\\FileWriter\\FileWriter"), FILE_LIST_DIRECTORY, 
        FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, 
        NULL, OPEN_EXISTING, 
        FILE_FLAG_BACKUP_SEMANTICS, NULL );

    if ( m_hMonitoredDir == INVALID_HANDLE_VALUE )
    {
        DWORD dwErr = GetLastError();
        printf("error");
        return;
    }

    char szBuf[ MAX_PATH ];
    DWORD dwBytesRead = 0;
    int flag=0;
    char *buffer;

    while ( ReadDirectoryChangesW( m_hMonitoredDir, szBuf, MAX_PATH, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE,&dwBytesRead, NULL, NULL ))
    {
        PFILE_NOTIFY_INFORMATION pstFileNotif = (PFILE_NOTIFY_INFORMATION)( szBuf );
        if ( pstFileNotif->Action == FILE_ACTION_MODIFIED ) 
        {
            char szNotifFilename[ MAX_PATH ] = { 0 };
            if ( int iNotifFilenameLen = WideCharToMultiByte( CP_OEMCP, NULL, 
                pstFileNotif->FileName, 
                pstFileNotif->FileNameLength / sizeof( WCHAR ), 
                szNotifFilename, sizeof( szNotifFilename ) / sizeof( char ), 
                NULL, NULL ) )
            {

                if ( strcmp("log.txt", szNotifFilename ) == 0 )
                {   
                    fseek(fp, 0, SEEK_END);
                    new_size = ftell(fp);   
                    fseek(fp,last_size,SEEK_SET);
                    int size=new_size-last_size;
                    buffer=new char[size+1];
                    fread(buffer,1,size,fp);
                    buffer[size]='\0';
                    printf("%s",buffer);
                    free(buffer);
                }
            }
        }
    }

}

B で fflush を使用するとすぐに通知を受け取ることができますか?

4

3 に答える 3

1

これは不可能だと思います。(強調鉱山)のドキュメントによると:FILE_NOTIFY_CHANGE_LAST_WRITE

監視対象のディレクトリまたはサブツリー内のファイルの最終書き込み時刻が変更されると、変更通知の待機操作が返されます。オペレーティング システムは、ファイルがディスクに書き込まれるときにのみ、最終書き込み時刻の変更を検出します。大規模なキャッシュを使用するオペレーティング システムの場合、検出はキャッシュが十分にフラッシュされた場合にのみ行われます。

fflush()ファイル データがオペレーティング システムに戻されることは保証されますが、データがディスクに書き込まれることは保証されません。これは通常、多くのキャッシュが含まれるためです。

バッファーは通常、オペレーティング システムによって維持されます。オペレーティング システムは、データを自動的にディスクに書き込む最適なタイミングを決定します。バッファーがいっぱいになったとき、ストリームが閉じられたとき、またはストリームを閉じずにプログラムが正常に終了したときです。ランタイム ライブラリのディスクへのコミット機能により、重要なデータがオペレーティング システムのバッファではなくディスクに直接書き込まれるようになります。

コメントで他の人が言っているように、既知のファイルを 1 つしか扱っていないため、目的に応じて名前付きパイプを使用する方がよい場合があります。

于 2013-09-26T21:41:03.387 に答える
0

_flushall( http://msdn.microsoft.com/en-us/library/s9xk9ehd.aspx )を呼び出して、ディスクへのコミットを強制できます。

または、ディスクへのコミットを強制する方法については、この記事 ( http://support.microsoft.com/kb/148505 ) を参照してください。ディスクへのコミットを自動的にcommode.obj強制するには、 とリンクする必要があります。fflush

別の方法としてはfclose、毎回ファイルにアクセスし、2 秒ごとに実行するだけの場合 (オーバーヘッドが小さい場合)、追加モードでファイルを再度開くこともできます。

于 2013-09-26T21:56:51.367 に答える