CreateProcess和MapViewOfFile有很多问题

Lots of trouble with CreateProcess and MapViewOfFile

本文关键字:问题 MapViewOfFile CreateProcess      更新时间:2023-10-16

它已经困扰我好几个小时了,我无法解决这个问题。

到目前为止,我一直在编码,没有遇到太多问题。我的任务是通过循环文件将消息从一个进程发送到另一个进程。消息由第一个进程中的一个线程生成,通过共享内存发送到该进程中的另一个线程,然后该线程将此消息发送到分离的进程。我能够创建子进程并向它发送一些消息,但当我开始实现信号量以生成循环文件时,事情就发生了问题。

代码很重,虽然我使用的是c++,但它是结构化的,所以有点难以理解,也有点混乱。一旦我做对了,我就会开始清理。

这是进程1:的线程a

DWORD WINAPI StRetFunc(LPVOID id)
{
    LONG LPrevCount;
    HANDLE pFile;
    HANDLE pSent;
    HANDLE pRecieved;
    char* pImage;
    BOOL endThread = false;
    unsigned int pPos=0;
    BOOL bStatus;
    STARTUPINFO si;         // StartUpInformation for new process
    PROCESS_INFORMATION NewProcess; // New Process infos
    pFile = CreateFileMapping(
        (HANDLE)0xFFFFFFFF,
        NULL,
        PAGE_READWRITE,     // access type
        0,                  // dwMaximumSizeHigh
        BYTE_TAM_ARQ,                   // dwMaximumSizeLow
        (LPCWSTR) "CircFile");          // name
    check(pFile, "Cannot open file.");
    pSent = CreateEvent(NULL, TRUE, FALSE, (LPCWSTR) "SentMSG");
    check(pSent, "Cannot create event SentMSG (pSent).");
    pRecieved = CreateEvent(NULL, TRUE, FALSE, (LPCWSTR) "RecievedMSG");
    check(pRecieved, "Cannot create event RecievedMSG (pRecieved)");
    cout << "Handles createdn";
    LPWSTR szCmdline = _tcsdup(TEXT("..\Debug\ATR TP - LS.exe"));
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si); // Tamanho da estrutura em bytes
    si.dwFlags = CREATE_NEW_CONSOLE;
    bStatus = CreateProcess(
        szCmdline , // Nome
        NULL,   // linha de comando
        NULL,   // atributos de segurança: Processo
        NULL,   // atributos de segurança: Thread
        FALSE,  // herança de handles
        CREATE_NEW_CONSOLE, // CreationFlags
        //NORMAL_PRIORITY_CLASS,
        NULL,   // lpEnvironment
        NULL,   // diretório corrente do filho
        &si,            // lpStartUpInfo
        &NewProcess);   // lpProcessInformation
    check(bStatus, "Impossivel criar processo: %s", DecodeError());
    while(WaitForSingleObject(hEvent_Esc, 0) != WAIT_OBJECT_0) {
        CheckFreezeEvent(stretEvent, "Retira Status");
        WaitForSingleObject(stretSemaphore, INFINITE);
        {
            do {
                while(circ_mem[stret_index].empty() == true)
                        ++stret_index %= MAX_LISTA_CIRC;
                while(memrdy[stret_index] == false);
                if(circ_mem[stret_index].substr(7, 3) == "000")
                    break;
                else
                    ++stret_index %= MAX_LISTA_CIRC;
                if(WaitForSingleObject(hEvent_Esc, 0) == WAIT_OBJECT_0) {
                    endThread = true;
                    break;
                }
                if(WaitForSingleObject(stretEvent, 0) != WAIT_OBJECT_0)
                    CheckFreezeEvent(stretEvent, "Retira Status");
            } while(true);
            if(endThread) break;
            CheckFreezeEvent(stretEvent, "Retira Status");
            cout << "Status Retirado: " << circ_mem[stret_index] << " Na posicao: " << stret_index << "n";
            //WriteToFile
            pImage = (char*) MapViewOfFile(
                pFile,
                FILE_MAP_WRITE,
                0,
                0,
                35);
            strcpy(pImage, circ_mem[stret_index].c_str());
            SetEvent(pSent);
            while(WaitForSingleObject(pRecieved, 0) != WAIT_OBJECT_0 ) {
                if(WaitForSingleObject(hEvent_Esc, 0)) break;
            }
            ResetEvent(pRecieved);
            circ_mem[stret_index].clear();
            memrdy[stret_index] = false;
            ReleaseSemaphore(iSemaphore, 1, &LPrevCount);
        }
    }
    cout << "Encerrando Thread Retirada Statusn";
    CloseHandle(pFile);
    CloseHandle(pSent);
    CloseHandle(pRecieved);
    return(0);
}

这是子进程

// ATR TP - LS.cpp : Defines the entry point for the console application.
//
#include "FileFuncs.h"
#include "..ATR TPdebug.h"
int main(int argc, char* argv[])
{
    BOOL bStatus;
    char *lpImage;          // Apontador para imagem local
    HANDLE pFile;
    HANDLE pEventSent;
    HANDLE pEventRead;
    HANDLE hEsc;

    pFile= OpenFileMapping(
        FILE_MAP_ALL_ACCESS,
        FALSE,              // Handle herdável
        (LPCWSTR) "CircFile");          // Escolha o seu nome preferido
    check(pFile, "Nao foi possivel abrir file mapping: %s", DecodeError());
    lpImage= (char *)MapViewOfFile(
        pFile,
        FILE_MAP_WRITE,     // Direitos de acesso: leitura e escrita
        0,                  // dwOffsetHigh
        0,                  // dwOffset Low
        BYTE_TAM_ARQ);          // Número de bytes a serem mapeados
    check(lpImage, "Impossivel criar map view.");
    // Abre eventos criados
    hEsc = OpenEvent(EVENT_ALL_ACCESS, FALSE, (LPCWSTR) "myEsc");
    check(hEsc, "Impossivel abrir evento ESC: %dn", GetLastError());
    pEventSent= OpenEvent(EVENT_ALL_ACCESS, FALSE, (LPCWSTR) "SentMSG");
    check(pEventSent, "Impossivel abrir evento SentMSG: %dn", GetLastError());
    // Cria evento com reset automático
    pEventRead= OpenEvent(EVENT_ALL_ACCESS, FALSE, (LPCWSTR) "RecievedMSG");
    check(pEventRead, "Impossivel abrir evento RecievedMSG: %dn", GetLastError());
    cout << "[Exibicao] Handles Abertos" << endl;
    bool endProg = false;
    while(WaitForSingleObject(hEsc, 0) != WAIT_OBJECT_0) {
        // Espera que processo A escreva mensagem 
        while(WaitForSingleObject(pEventSent, 0) != WAIT_OBJECT_0) {
            if(WaitForSingleObject(hEsc, 0) == WAIT_OBJECT_0) endProg = true;
        }
        if(endProg) break;
        ResetEvent(pEventSent);
        if (strcmp(lpImage, "")==0) break;
        printf("[Exibicao] Mensagem Status Recebida= %sn", lpImage);
        // Limpa memória compartilhada
        strcpy(lpImage, "");    
        SetEvent(pEventRead);   // Avisa processo A
    }
    // Elimina mapeamento
    CloseHandle(pFile);
    CloseHandle(pEventSent);
    CloseHandle(pEventRead);
    bStatus=UnmapViewOfFile(lpImage);
    check(bStatus, "Unmap Falhou.");
    //cout << "Encerrando Processo Retirada Status ARQUIVO" << endl;
    // ^if i uncomment this line, hell breaks loose
    ExitProcess(0);
    return EXIT_SUCCESS;
    return 0;
}

如果我取消注释上一个文件中包含cout的最后一行,我就无法打开我的事件,也无法对子进程执行任何操作。cout与我的活动开幕有什么关系?

此外,在我检查错误后,GetLastError()会给我数字2。尝试OpenEvent并得到错误号2意味着什么?

我坚信这个问题依赖于MapViewOfFile,因为我在某个地方读到过,如果偏移量和文件大小不正确(关于粒度和文件大小不是0的问题,我就是无法理解)。也许有一大块内存被占用了,打乱了我的程序。

Check是一个宏,是Zed的Awesome Debug宏的修改版本:http://c.learncodethehardway.org/book/ex20.html

对于任何好奇发生了什么的人来说,我试图通过si.dwFlags创建一个新的控制台。但是,位设置si.dwFlags = CREATE_NEW_CONSOLE;不是由MSDN定义的,因此它不是一个有效的配置。我的猜测是,它扰乱了一些与IPC内存访问相关的寄存器,从而扰乱了句柄的打开和通过文件映射共享内存的实际使用。

正确的做法是在CreateProcess中设置CREATE_NEW_CONSOLE,就像最初发布的那样:

bStatus = CreateProcess(
    szCmdline , // Nome
    NULL,   // linha de comando
    NULL,   // atributos de segurança: Processo
    NULL,   // atributos de segurança: Thread
    FALSE,  // herança de handles
    CREATE_NEW_CONSOLE, // CreationFlags
    //NORMAL_PRIORITY_CLASS,
    NULL,   // lpEnvironment
    NULL,   // diretório corrente do filho
    &si,            // lpStartUpInfo
    &NewProcess);   // lpProcessInformation
check(bStatus, "Impossivel criar processo: %s", DecodeError());

如果您不确定如何使用dwFlags,请避免使用。