CreateProcess和MapViewOfFile有很多麻烦

时间:2014-11-07 04:12:34

标签: c++ multithreading visual-studio-2010

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

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

代码很重,虽然我使用的是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 created\n";

    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 Status\n";
    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 TP\debug.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: %d\n", GetLastError());

    pEventSent= OpenEvent(EVENT_ALL_ACCESS, FALSE, (LPCWSTR) "SentMSG");
    check(pEventSent, "Impossivel abrir evento SentMSG: %d\n", GetLastError());

    // Cria evento com reset automático
    pEventRead= OpenEvent(EVENT_ALL_ACCESS, FALSE, (LPCWSTR) "RecievedMSG");
    check(pEventRead, "Impossivel abrir evento RecievedMSG: %d\n", 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= %s\n", 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.这是什么意思o尝试OpenEvent并得到错误号2?

我坚信这个问题依赖于MapViewOfFile,因为我读过某个地方,如果你没有得到正确的偏移量和文件大小(关于粒度和文件不是0大小的东西,我只是无法理解)。也许有一大块记忆被过度重视并弄乱了我的程序。

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

1 个答案:

答案 0 :(得分:0)

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

正确的应用是在CREATE_NEW_CONSOLE内设置CreateProcess,就像它最初发布时一样:

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