繁体   English   中英

WinAPI 将多个进程的结果保存到一个文件

[英]WinAPI saving results from multiple processes to one file

我试图搜索类似的问题,但没有找到。 由于问题难以理解,将尝试尽可能简单地再次解释。 基本上,我有 3 个 C++ 源文件:

1.MainProcess3args.cpp - 正在执行与互斥锁同步的 2 个进程,第二个和第三个文件使用CreateProcess()函数运行。 Process2 应始终首先运行,并且该部分工作正常。 该文件接收 3 个参数 - 第一个是需要生成多少个数字,第二个是运行进程之间的时间距离,第三个参数定义进程必须执行多少次。 例如MainProcess.exe 2 5 2

第一个参数 2 -生成多少个数字,

第二个参数 5 - 下一个数字生成和计算平均值、最小值、最大值之间的时间距离(以秒为单位)

第三个参数 2 - 我们将生成多少次数字并计算平均值、最小值和最大值。

2.Random.cpp生成 N 个随机值作为参数并将它们保存到 RandomValues.txt 文件中。

3.ReadingRandoms.cpp有3 Threads-计算平均,找到存储在RandomValues.txt文件编号的最小值和最大值。

我想将有关文件和系统信息的给定参数的信息保存到新的 txt 文件中,并保存平均值、最小值和最大值的每个结果,文件应如下所示:

Total numbers: 2 | Version:Multithreads | Machine: OEM ID: 9 Processor Type: 8664 | Replies: 2 | Pause: 5
AVG     MIN    MAX
value1 value2 value3
values from next numbers generating...

我有 3 个源文件,尝试使用循环for(int i=0;i<argument2;i++)多种组合来同步该元素,但它从来没有像它应该的那样工作。 当每个进程执行一次时,一切正常。 MainProcess3args.cpp

#include <windows.h>
#include <stdio.h>
#include <pthread.h>
#include <tchar.h>
#include <mutex>
#include <iostream>
#include <string>
#include <cstdlib>
#include <fstream>
HANDLE hMutex; //used mutex object to implement spinlock
using namespace std;
SYSTEM_INFO siSysInfo;
int main(int argc, TCHAR *argv[])  
{  
   STARTUPINFO si1 = { 0 }, si2 = { 0 };
    si1.cb = sizeof si1;
    si2.cb = sizeof si2;
    PROCESS_INFORMATION pi1 = { 0 }, pi2 = { 0 };
    const TCHAR* target1 = _T("C:\\USERS\\Admin\\Documents\\Random3args.exe");
    const TCHAR* target2 = _T("C:\\USERS\\Admin\\Documents\\ReadingRandoms3args.exe");
    
    fstream Results;
    Results.open("Results.txt", ios::in | ios::out);
    if (!Results.is_open())
    cerr << "failed to open file\n";
    GetSystemInfo(&siSysInfo);
    int n = 0;//first argument, defines, how many files needs to be generated
    int times=0;//second argument,defines time distance beetween generating numbers
    int repeat = 0;//third argument
    n=_tstoi(argv[1]);
    times=_tstoi(argv[2]);
    repeat=_tstoi(argv[3]);
    Results<<"Total numbers: "<<n<<" | Version:Multithreads | Machine: OEM ID: "<<siSysInfo.dwOemId<<" Processor Type: "<<siSysInfo.dwProcessorType<<" | Replies: "<<repeat<<" | Pause: "<<times;
    times=times/0.001;
    
    hMutex = CreateMutex(NULL,0,NULL);
    //for(int i=0;i<repeat;i++){
   if (!CreateProcess(target1, GetCommandLine(), 0, FALSE, 0, CREATE_SUSPENDED, 0, 0, &si1, &pi1)) //CREATE_SUSPENDED argument makes process 1 hanging and waiting until process 2 excecute
    {
        cerr << "CreateProcess failed (" << GetLastError() << ").\n";
    }
    else
    {
        
         WaitForSingleObject(hMutex,INFINITE);  // process2 call WaitForSingleObject(hmutex) first to get mutex
        
        if (!CreateProcess(target2, 0, 0, FALSE, 0, 0, 0, 0, &si2, &pi2))//Process 2 is created and excecuted ...
        {
            cerr << "CreateProcess failed (" << GetLastError() << ").\n";
        }
        else
        {
            WaitForSingleObject(pi2.hProcess, INFINITE);
            
            CloseHandle(pi2.hProcess); //process2 closes
            CloseHandle(pi2.hThread);
        }
    
        ReleaseMutex(hMutex);//mutex released, process1 unlocked
        ResumeThread(pi1.hThread); //Process 1 is resumed and executed 
        WaitForSingleObject(pi1.hProcess, INFINITE);
    
        CloseHandle(hMutex);
        CloseHandle(pi1.hProcess);//process 1 closes
        CloseHandle(pi1.hThread);
 
    }
    LARGE_INTEGER li;
    double PCFreq = 0.0;
    __int64 CounterStart = 0; 
    if(!QueryPerformanceFrequency(&li))
    cout << "QueryPerformanceFrequency failed!\n";

    PCFreq = double(li.QuadPart)/1000.0;

    QueryPerformanceCounter(&li);
    CounterStart = li.QuadPart;
    QueryPerformanceCounter(&li);
    double c= (li.QuadPart - CounterStart)/PCFreq;
    cout<<"Performance time: "<<c<< " miliseconds";
    
    Results.close();
    cin.sync();
    cin.ignore();
    system("pause");
    return 0;
}  

第一个过程 - Random3args.cpp

#include <iostream>
#include <Windows.h>
#include <string>
#include <tchar.h>
#include <cstdlib>
#include <ctime>
#include <fstream>
using namespace std;
SYSTEM_INFO siSysInfo;
int main( int argc, TCHAR *argv[] )
{
    fstream File;
    File.open("RandomValues.txt", ios::in | ios::out);
    if (!File.is_open())
    cerr << "failed to open file\n";
    srand( time( NULL ) );
    
    int n = 0;//first argument, defines, how many files needs to be generated
    int times=0;//second argument,defines time distance beetween generating numbers
    int repeat = 0;//third argument
    n=_tstoi(argv[1]);
    times=_tstoi(argv[2]);
    repeat=_tstoi(argv[3]);
    times=times/0.001;
    
    int r=0;
    cout<<endl;
    for(int j=0;j<repeat;j++)
    {
        for(int i=0;i<n;i++)
    {
        r=rand() % 100;
        File<<r<<" ";
        cout<<r<<"values "; //checking if values are read correctly
        
    }
    cout<<endl;
     Sleep(times);
    }
    
    File.close();

    return 0;
}

第二个过程 - ReadingRandoms3args.cpp

#include <iostream>
#include <Windows.h>
#include <string>
#include <tchar.h>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <vector>
//this program calculates average value of numbers in file, finds minimum and maximum in the file using 3 threads
#define THREADCOUNT 3
using namespace std;
HANDLE hSemaphore; // using semaphore object to synchronize threads
vector<int> Values;
double Average,MIN,MAX;


DWORD Averages(LPVOID* arg)  
{  
      
      WaitForSingleObject(hSemaphore, INFINITE); 
      Average = 0;
      double Sum = 0;
      //for(int j=0;j<repeat;j++)
      
      for (unsigned int i = 0; i < Values.size(); i++) { 
    //cout << Values[i] << " "; checking, if the values from the file are being read correctly
       Sum+=Values[i];
       }
      Average = Sum/Values.size();
    cout<<"The average of given values is: "<<Average<<endl; 

    ReleaseSemaphore(hSemaphore,1,NULL);
    return 0;
}  
DWORD Minimum(LPVOID* arg)  
{  
       
     WaitForSingleObject(hSemaphore, INFINITE); 
     MIN=Values[0];
     for(unsigned int j=0;j<Values.size();j++)
     {
        if(MIN>Values[j])
        {
        MIN=Values[j];
        }
}
cout<<endl;
cout<<"Minimum value is "<<MIN<<endl;  
      ReleaseSemaphore(hSemaphore,1,NULL);
    return 0;
}  
DWORD Maximum(LPVOID* arg)  
{  
    
    WaitForSingleObject(hSemaphore, INFINITE);
     MAX=Values[0];
     for(unsigned int k=0;k<Values.size();k++)
    {
       if(MAX<Values[k])
        {
        MAX=Values[k];
        }
    }
cout<<endl;
cout<<"Maximum value is "<<MAX<<endl;  
      ReleaseSemaphore(hSemaphore,1,NULL);  
    return 0;
}  
int main( int argc, TCHAR *argv[] )
{
// open the file
ifstream File("RandomValues.txt", ios::in);
if (!File.is_open())
    cerr << "failed to open file\n";
  
// read the values 
int val;

while (File >> val){
    Values.push_back(val);
   
   }
fstream Results;
Results.open("Results.txt", ios::in | ios::out);
if (!Results.is_open())
    cerr << "failed to open file\n";
int repeat = _tstoi(argv[3]) ;   
//cout<<repeat;
Results<<"AVG  "<<"MIN  "<<"MAX  "<<endl;  
  
hSemaphore=CreateSemaphore(NULL,0,3,NULL); 
HANDLE hThreads[3];  
DWORD threadID1,threadID2,threadID3; 

for(int i=0;i<repeat;i++){
        // calculate average of values-first thread
hThreads[0]=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Averages, &hSemaphore,0, &threadID1);

// finding minimum - second thread
hThreads[1]=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Minimum, &hSemaphore, 0, &threadID2);
// finding maximum - third thread
hThreads[2]=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Maximum, &hSemaphore, 0, &threadID3);
}

ReleaseSemaphore(hSemaphore,1,NULL);  
WaitForMultipleObjects(THREADCOUNT, hThreads, TRUE, INFINITE);  
for( int i=0; i < THREADCOUNT; i++ ){

        CloseHandle(hThreads[i]);
    }
CloseHandle(hSemaphore);  
Results<<Average<<"  "<<MIN<<"  "<<MAX<<endl;
File.close();
Results.close();

return 0;
}

Process2 should always run first, and that part works ok.

这里有一个错误。 MainProcess3args.cpp挂起Process1MainProcess3args.cpp执行Process2Process2无法读取任何数据,所以应该先执行Process1 ,再通过Process1读取。

以下代码:

const TCHAR* target1 = _T("C:\\USERS\\Admin\\Documents\\Random3args.exe");
const TCHAR* target2 = _T("C:\\USERS\\Admin\\Documents\\ReadingRandoms3args.exe");
...
CreateProcess(target1, GetCommandLine(), 0, FALSE, 0, CREATE_SUSPENDED, 0, 0, &si1, &pi1);
...
CreateProcess(target2, GetCommandLine(), 0, FALSE, 0, 0, 0, 0, &si2, &pi2);
...

只需修改为:

const TCHAR* target1 = _T("C:\\USERS\\Admin\\Documents\\ReadingRandoms3args.exe");
const TCHAR* target2 = _T("C:\\USERS\\Admin\\Documents\\Random3args.exe");
...
CreateProcess(target1, GetCommandLine(), 0, FALSE, 0, CREATE_SUSPENDED, 0, 0, &si1, &pi1);
...
CreateProcess(target2, GetCommandLine(), 0, FALSE, 0, 0, 0, 0, &si2, &pi2);
...

这样可以保证读取数据的Process2先挂起,生成随机数据的过程先执行。

源代码有一些小问题。 MainProcess3args.cpp ,当你写完:

Results << "Total numbers: " << n << " | Version:Multithreads | Machine: OEM ID: " << siSysInfo.dwOemId << " Processor Type: " << siSysInfo.dwProcessorType << " | Replies: " << repeat << " | Pause: " << times;

在此之后,您没有写入文件,但是您的Process2需要打开文件句柄才能写入结果。 此时,您还没有关闭文件句柄(您在主进程结束时关闭了它)。

所以你需要在主进程写入之后和创建Process2之前关闭文件句柄。 比如下面的代码:

Results << "Total numbers: " << n << " | Version:Multithreads | Machine: OEM ID: " << siSysInfo.dwOemId << " Processor Type: " << siSysInfo.dwProcessorType << " | Replies: " << repeat << " | Pause: " << times;
Results.close();

最后它对我有用:

在此处输入图片说明

编辑:

两个CreateProcess需要传递GetCommandLine()参数,否则程序在调用 argv[3] 时会崩溃。我已经更改了我的代码。

否则,您可以使用以下代码输出:

ofstream Results;
Results.open("Results.txt", std::ofstream::out | std::ofstream::app);
if (!Results.is_open())
    cerr << "failed to open file\n";
int repeat = _tstoi(argv[3]);
//cout<<repeat;
Results << endl;
Results << "AVG  " << "MIN  " << "MAX  " << endl;

这样就可以将输出的内容追加到Result.txt而不是覆盖原来的内容。

还有一些资源泄漏问题:

for (int i = 0; i < repeat; i++) {
// calculate average of values-first thread
hThreads[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Averages, &hSemaphore, 0, &threadID1);
// finding minimum - second thread
hThreads[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Minimum, &hSemaphore, 0, &threadID2);
// finding maximum - third thread
hThreads[2] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Maximum, &hSemaphore, 0, &threadID3);
}

当repeat大于1时,运行上述代码会导致之前的hThreads句柄被覆盖,并保存上次创建的线程句柄。 需要保证线程句柄在每次循环后正常关闭。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM