C++多进程数据共享
1.创建子进程
int process_1(wchar_t commandLine2[]) {
STARTUPINFO si = { sizeof(STARTUPINFO) };//在产生子进程时,子进程的窗口相关信息
PROCESS_INFORMATION pi; //子进程的ID/线程相关信息
DWORD returnCode;//用于保存子程进的返回值;
//wchar_t commandLine2[] = L"../x64\\Debug\\exe_a\\py_to_c"; //测试命令行参数二
BOOL bRet = CreateProcess( //调用失败,返回0;调用成功返回非0;
NULL, //一般都是空;(另一种批处理情况:此参数指定"cmd.exe",下一个命令行参数 "/c otherBatFile")
commandLine2, //进程路径,例 L"C:\\Users\\ps\\Desktop\\c++_into_python\\python_to_c-1\\process_2\\x64\\Debug\\process_2",不需要.exe后缀
NULL, //_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
NULL, //_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
FALSE, //_In_ BOOL bInheritHandles,
CREATE_NEW_CONSOLE, //新的进程使用新的窗口。显示窗口CREATE_NEW_CONSOLE 隐藏窗口CREATE_NO_WINDOW
NULL, //_In_opt_ LPVOID lpEnvironment,
NULL, //_In_opt_ LPCTSTR lpCurrentDirectory,
&si, //_In_ LPSTARTUPINFO lpStartupInfo,
&pi); //_Out_ LPPROCESS_INFORMATION lpProcessInformation
if (bRet)
{
std::cout << "process is running..." << std::endl;
//等待子进程结束
//WaitForSingleObject(pi.hProcess, -1);
std::cout << "process is finished" << std::endl;
//获取子进程的返回值
GetExitCodeProcess(pi.hProcess, &returnCode);
std::cout << "process return code:" << returnCode << std::endl;
}
else
{
std::cout << "Create Process error!" << std::endl;
return 0;
}
//getchar();
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return 0;
}
2.获取进程是否开启
int GetProcess()
{
//PROCESSENTRY32结构体,保存进程具体信息
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
char exe_name0[] = "py_to_c_gpu0.exe";
char exe_name1[] = "py_to_c_gpu1.exe";
int cout_flag0 = 0;
int cout_flag1 = 0;
//获得系统进程快照的句柄
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
printf("CreateToolhelp32Snapshot error.\n");
return 0;
}
//首先获得第一个进程
BOOL bProcess = Process32First(hProcessSnap, &pe32);
//循环获得所有进程
while (bProcess)
{
//打印进程名和进程ID
//申请char类型存储空间
char* pe_cha = new char[sizeof(pe32.szExeFile)];
//将wchar_t宽类型转char窄类型
WideCharToMultiByte(CP_ACP, 0, pe32.szExeFile, -1, pe_cha, sizeof(pe32.szExeFile), NULL, FALSE);
if (strcmp(pe_cha, exe_name0) == 0)//判断两字符串是否一致
cout_flag0 += 1;
if (strcmp(pe_cha, exe_name1) == 0)
cout_flag1 += 1;
//printf("%ls----%d\n", pe32.szExeFile, pe32.th32ProcessID);
bProcess = Process32Next(hProcessSnap, &pe32);
}
CloseHandle(hProcessSnap);
}
2.创建共享内存
#define BUF_SIZE 4096*8192+20+64+64
void creat_space()
{
CreateFileMapping(
INVALID_HANDLE_VALUE, // 物理文件句柄
NULL, // 默认安全级别
PAGE_READWRITE, // 可读可写
0, // 高位文件大小
BUF_SIZE, // 低位文件大小
L"ShareMemory" // 共享内存名称
);
}
注意:创建的共享内存需要在使用完毕再关闭,CloseHandle(hMapFile)
3.写入图片
typedef struct
{
int width;
int height;
int type;
int flag_write;
int flag_read;
}MatHeader;
int creat_file()
{
// 定义共享数据
Mat img = read_img();
HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, TRUE, L"ShareMemory");
// 映射缓存区视图 , 得到指向共享内存的指针
LPVOID lpBase = MapViewOfFile(
hMapFile, // 共享内存的句柄
FILE_MAP_ALL_ACCESS, // 可读写许可
0,
0,
BUF_SIZE
);
// 将数据拷贝到共享内存
MatHeader matHead;
matHead.width = img.cols;
matHead.height = img.rows;
matHead.type = img.type();
matHead.flag_write = 1;//写标志位
matHead.flag_read = 0;//读标志位
//int cc = sizeof(MatHeader);
char* lp = (char*)lpBase;//转换后才能与sizeof(MatHeader)相加
//将图片数据复制到共享内存
memcpy(lp + sizeof(MatHeader), img.data, img.cols * img.rows);//写入图片数据
memcpy(lpBase, &matHead, sizeof(MatHeader));//写入文件头部信息
UnmapViewOfFile(lpBase);//关闭映射
CloseHandle(hMapFile);//关闭句柄
return 0;
}
4.读取图片
typedef struct
{
int width;
int height;
int type;
int flag_write;
int flag_read;
}MatHeader;
void init_numpy()
{
_import_array();
}
typedef struct _img_detect_data_py1
{
//int img_num = -1; // 图片索引
std::vector<int>scores1;
std::vector<float>classes1;
std::vector<int>masks1;
}img_detect_data_py1;
int main
{
MatHeader matHead;
img_detect_data_py img_detect_tmp;
//打开共享的文件对象
HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, TRUE, L"ShareMemory");
cout << "GPU2错误编号:" << GetLastError() << endl;
if (hMapFile)
{
LPVOID lpBase = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE);
char* lp = (char*)lpBase;
// 将共享内存数据拷贝出来
//读入信息头
cout << "头长度:" << sizeof(matHead) << endl;
memcpy(&matHead, lp, sizeof(MatHeader));
cout << "高" << matHead.height << endl;
//创建image
Mat image;
image.create(matHead.height, matHead.width, matHead.type);
memcpy(image.data, lp + sizeof(MatHeader), matHead.height * matHead.width);
matHead.flag_read = 1;
matHead.flag_write = 0;//图像读取完成标志位置0
memcpy(lpBase, &matHead, sizeof(MatHeader));//更新头部信息
解除文件映射
UnmapViewOfFile(lpBase);
关闭内存映射文件对象句柄
CloseHandle(hMapFile);
// namedWindow("img", WINDOW_NORMAL);
// cv::imshow("img", image);
// cv::waitKey();
// cv::destroyAllWindows();
}
注意事项:
1)打开共享内存使用后需要及时释放掉
2)将图片写入共享内存时,先将图片头部信息写入再写入图片数据img.data
3)在读取图片信息时,需要创建一个新的Mat类型变量,用于存储图片信息
4)在使用MapViewOfFile返回值lpBase进行加法运算时,需要进行强制类型转换char* lp = (char*)lpBase;