Windows系统——多进程多线程任务队列管理(进程通信)(临界资源访问)

Windows系统——多进程多线程任务队列管理(进程通信)(临界资源访问)

相关知识

Windows系统——进程通信共享内存区
Windows系统——进程创建
Windows系统——多线程互斥访问临界资源
Windows系统——线程创建

实现代码

  • Printer.cpp
/*
author : eclipse
email  : eclipsecs@qq.com
time   : Sun Apr 26 12:44:13 2020
*/
#include <bits/stdc++.h>
#include <windows.h>
#include "Queue.cpp"
using namespace std;

//queue<string> q;
Queue q;
const int BUFFER_SIZE = 1024;
const char shareMemory[] = "task";
CRITICAL_SECTION mutex;
char *buffer = NULL;

DWORD CALLBACK read(LPVOID param) {
    while (true) {
        if (buffer[0]) {
            EnterCriticalSection(&mutex);
            string t = string(buffer);
            q.push(t);
            LeaveCriticalSection(&mutex);
            if (!strcmp(buffer, "finish")) {
                break;
            }
            buffer[0] = '\0';
        }
    }
    return 0;
}


int main(int argc, char const *argv[])
{
    InitializeCriticalSection(&mutex);

    HANDLE mappingFileHandle;
    if (!(mappingFileHandle = CreateFileMapping(
        INVALID_HANDLE_VALUE,
        NULL,
        PAGE_READWRITE,
        0,
        BUFFER_SIZE,
        shareMemory))) {
        printf("Create file mapping error(%d)!", GetLastError());
        abort();
    }

    if (!(buffer = (char *)MapViewOfFile(
		mappingFileHandle,
        FILE_MAP_ALL_ACCESS,
        0,
        0,
        BUFFER_SIZE))) {
        printf("Map file error(%d)", GetLastError());
        abort();
    }
    
    HANDLE readThreadHandle = NULL;
    DWORD readThreadId;
    if (!(readThreadHandle = CreateThread(NULL, 0, read, NULL, 0, &readThreadId))) {
        printf("Thread create error(%d)\n", GetLastError());
        abort();
    }

    while (q.empty() || q.front() != "finish") {
        if (!q.empty() && q.front() != "finish") {
            printf("Received data\n");
            printf("Ready to print\n");
            printf("Printing [");
            for (int i = 0; i < 10; i++) {
                Sleep(200);
                printf("=");
            }
            printf("]\n");
            EnterCriticalSection(&mutex);
            cout << q.front() << endl;
            q.pop();
            LeaveCriticalSection(&mutex);
            printf("\07Print successfully\n");
        }
    }
    
    DeleteCriticalSection(&mutex);
	UnmapViewOfFile(buffer);
    CloseHandle(mappingFileHandle);
	return 0;
}

  • Writer.cpp
/*
author : eclipse
email  : eclipsecs@qq.com
time   : Sun Apr 26 12:44:13 2020
*/
#include<bits/stdc++.h>
#include<windows.h>
using namespace std;

const int BUFFER_SIZE = 1024;
const char shareMemory[] = "task";

int main(int argc, char const *argv[])
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));

    si.cb = sizeof(si);

    ZeroMemory(&pi, sizeof(pi));

    if (!CreateProcess(NULL,
        (LPSTR) "printer.exe",
        NULL,
        NULL,
        FALSE,
        CREATE_NEW_CONSOLE,
        NULL,
        NULL,
        &si,
        &pi)) {
        printf("Create Process error(%d)!\n", GetLastError());
        abort();
    }

    HANDLE mappingFileHandle;

    if (!(mappingFileHandle = CreateFileMapping(
        INVALID_HANDLE_VALUE,
        NULL,
        PAGE_READWRITE,
        0,
        BUFFER_SIZE,
        shareMemory))) {
        printf("Create file mapping error(%d)!", GetLastError());
        abort();
    }
 
 
    char *buffer = NULL;

    if (!(buffer = (char*) MapViewOfFile(
		mappingFileHandle,
        FILE_MAP_ALL_ACCESS,
        0,
        0,
        BUFFER_SIZE
    ))) {
        printf("Map file error(%d)\n", GetLastError());
        abort();
    }

    while (strcmp(buffer, "finish")) {
        printf("Send data\n");
        gets(buffer);
    }
 
	UnmapViewOfFile(buffer);
    CloseHandle(mappingFileHandle);
	return 0;
}
  • Queue.cpp
/*
author : eclipse
email  : eclipsecs@qq.com
time   : Sun Apr 26 14:46:53 2020
*/

#include<bits/stdc++.h>
using namespace std;
typedef string ElemType;

const int MAXSIZE = 1000;

struct Queue
{
    ElemType data[MAXSIZE];
    int frontPointer;
    int rearPointer;
    bool tag;
    ElemType front();
    void pop();
    void push(ElemType x);
    bool empty();
    bool full();
    Queue() : frontPointer(0), rearPointer(0), tag(false) {}
};

ElemType Queue::front() {
    return empty() ? "-1" : data[frontPointer]; 
}

void Queue::pop() {
    if (empty()) {
        printf("The queue is empty!\n");
        return;
    }
    frontPointer = (frontPointer + 1) % MAXSIZE;
    if (frontPointer == rearPointer) {
        tag = false;
    }
}

void Queue::push(ElemType x) {
    if (full()) {
        printf("The queue is full!\n");
        return;
    }
    data[rearPointer] = x;
    rearPointer = (rearPointer + 1) % MAXSIZE;
    if (rearPointer == frontPointer) {
        tag = true;
    }
}

bool Queue::empty() {
    return frontPointer == rearPointer && !tag;
}

bool Queue::full() {
    return frontPointer == rearPointer && tag;
}

实现

  • 效果
    从Writer进程输入数据,Writer进程创建子进程Printer,子进程主线程创建子线程从内存区读取数据进入等待队列,子进程Printer主线程从队列取队首元素异步地输出数据(间隔两秒打印一次数据)
  • 思路
    上述实现借用两个进程,父进程输入,子进程借助两个线程,一个线程读取共享内存区的数据,主线程每个两秒相对于子线程异步地打印数据, 上述实现中的队列是自行编写的,将Queue q;改成queue<string> q;即可使用STL队列
  • 互斥访问队列
    子进程Printer主线程和子线程互斥地进入临界区访问共享全局变量队列q,子线程等待输入,主线程打印结果
  • 进程通信共享内存区
    进程Writer和子进程Printer通过共享内存区进行进程间通信,父进程输入数据进入共享内存区,子进程子线程从共享内存区读取数据,父进程输出数据到控制台

编译过程

g++ Printer.cpp -o printer
g++ Writer.cpp -o writer
writer.exe

效果截图

在这里插入图片描述

最后

  • 由于博主水平有限,不免有疏漏之处,欢迎读者随时批评指正,以免造成不必要的误解
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值