m.cpp

来自「本程序可以用于实现操作系统中有关pv操作的演示的.」· C++ 代码 · 共 121 行

CPP
121
字号
#include<iostream.h>
#include <stdio.h>
#include <Windows.h>
#include<ctype.h>
//缓冲区和信号量
HANDLE g_hBuffer = NULL; //HANDLE表示句柄的意思,相当于一种指向指针的指针
HANDLE g_hSemSynR = NULL, g_hSemSynM = NULL, g_hSemSynP = NULL,g_hSemMutex = NULL;
char* g_pszBuffer = NULL;
//在缓冲区中的位置指针
unsigned char g_nR = 0, g_nM = 0, g_nP = 0;
//P,V操作
void P(HANDLE hSem)
{  
	WaitForSingleObject(hSem, INFINITE);//两个信号分别表示事件的句柄和时间间隔
}
void V(HANDLE hSem)
{  
	ReleaseSemaphore(hSem, 1, NULL);
}
void main()
{ //创建共享内存,大小为320 + 3B=10条记录 + 3个指针
	g_hBuffer= CreateFileMapping((HANDLE)0xFFFFFFFF, //物理文件句柄,当与物理文件文件无关是设置为0xFFFFFFFF
		NULL,PAGE_READWRITE, 0, 323, "my_buffer");//安全描述副指针,对映射对象的保护属性,高位和底位文件大小,共享内存对影射文件的名称
	if(g_hBuffer == NULL)// 如果创建失败
	{  
		printf("创建或连接共享内存失败!\n");
		return;  
	}
	else if(GetLastError() == ERROR_ALREADY_EXISTS)
	{   //如果已经存在这个同名对象, 说明共享内存已经创建
		g_pszBuffer=(char*)MapViewOfFile(g_hBuffer, FILE_MAP_WRITE | FILE_MAP_READ, 0,0,0);
		/* 在普通的应用程序里使用MapViewOfFile可以用:
		MapViewOfFile(MapHandle, FILE_MAP_READ, 0, 0, 0);
		映射整个文件,程序也可以正常访问2GB的文件,可将相同的代码移植到
		COM(Windows Shell Extension)中发现访问大文件里MapViewOfFile返回NULL,
		返回的GetLastError值*/
		unsigned char *pnPoint = (unsigned char*)g_pszBuffer;
		//分别对三个信号量进行赋值
		g_nR = pnPoint[0];
		g_nM = pnPoint[1];
		g_nP = pnPoint[2];
	}
	else 
	{ // 经过上面的检查, 说明这是第一次创建共享内存
		g_pszBuffer=(char*)MapViewOfFile(g_hBuffer,    //建立映射视图 (已建的文件对象的句柄,
			FILE_MAP_WRITE | FILE_MAP_READ, 0,0,0); //访问模式,文件偏移的高32位和低32位,映射视图的大小)
		// 初始化内存
		memset(g_pszBuffer, 0, 323);       //memset用来对一段内存空间全部设置为某个字符
		g_nR = g_nM = g_nP = 0;
	}
	//创建信号量
	g_hSemSynR=CreateSemaphore(NULL, 10, 10, "my_sem_R");
	g_hSemSynM=CreateSemaphore(NULL, 0, 10, "my_sem_M");
	g_hSemSynP=CreateSemaphore(NULL, 0, 10, "my_sem_P");
	g_hSemMutex=CreateSemaphore(NULL, 1, 1, "my_sem_C");
	if(g_hSemSynR == NULL || g_hSemSynM == NULL || g_hSemSynP == NULL)	
	{// 如果创建失败 
		printf("创建或连接信号量失败!\n");
		return;  
	}
	//下面开始M的工作
	BOOL end = FALSE; //bool 关键字是 System.Boolean 的别名。
	                 //此关键字用于声明存储布尔值 true 和 false 的变量。
	cout<<"···产品数据信息的处理···"<<endl;
	while(!end)
	{
		int i;
		char data2[32];
		cout<<"数据处理过程如下:"<<endl;
		printf("\tP(synM)\n");
		P(g_hSemSynM);
		printf("\tP(Mutex)\n");
		P(g_hSemMutex);
		g_nM = g_pszBuffer[1];
        strncpy(data2, g_pszBuffer + 3 + g_nM * 32, 31);  /*  strncpy 
                     如果目标长>指定长>源长,则将源长全部拷贝到目标长,自动加上'\0' 
                     如果指定长<源长,则将源长中按指定长度拷贝到目标字符串,不包括'\0' 
                     如果指定长>目标长,error happen! */ 
		for(i=1;i<sizeof(data2);i++)
		{
			if(data2[i]!='.'&&(data2[i]>=33&&data2[i]<'A'||data2[i]>'Z'&&data2[i]<'a'||data2[i]>'z'))
				data2[i]='.';
		}
		for(i=1;i<sizeof(data2);i++){data2[i]=tolower(data2[i]);}
		              //使用toupper/tolower函数进行大小写转换
		for(i=1;i<sizeof(data2);i++)
		{
			if(data2[i]=='.'&&data2[i+1]>='a'&&data2[i+1]<='z')
			data2[i+1]=toupper(data2[i+1]);    
		} //每个句子的第一个字母要大写
		for(i=1;i<sizeof(data2);i++)
		{
			if(data2[i]==' '){
				for(int j=i;j<sizeof(data2);j++){data2[j]=data2[j+1];}
				i--;}
		}//去掉空格,将句子联系起来
		if(data2[0]<='z'&&data2[0]>='a') data2[0]=toupper(data2[0]);
		//第一个句子的第一个字母应该大写    
		printf("处理后的数据:%s\n", data2);
		strncpy(g_pszBuffer + 3 + g_nM * 32,data2 , 31);
        g_pszBuffer[1] = g_nM = (g_nM + 1) % 10;  //实现功能lm=(lm+1)%10
        printf("\t数据处理完毕\n");
        printf("\tV(synP)\n");
        V(g_hSemSynP);
        printf("\tV(Mutex)\n");
        V(g_hSemMutex);
		char endCH;
	    printf("继续吗 ?(Y OR N )");
	    fflush(stdin);/* 正常来说,应该像下面这样
                         printf(.....);
                         fflush(stdout);
                         每一条printf语句后面都要跟随一条fflush语句才能有相应的显示。
		                 不然的话,printf语句的信息会被缓存起来。*/
	    scanf("%c", &endCH);//输入操作
	    if(endCH != 'y' && endCH != 'Y' ) end = TRUE;
	}//M的工作到此结束
	UnmapViewOfFile(g_pszBuffer); //断开和共享内存的连接
	CloseHandle(g_hBuffer);      //关闭这个句柄
	return;	
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?