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 + -
显示快捷键?