void sigend(int sig) { shmctl(shmid, IPC_RMID, 0); semctl(semid, IPC_RMID, 0); exit(0); } void relblock(void) { if(local.top<0) { printf("No block to release!"); return; } shmptr->top++; shmptr->stack[shmptr->top]=local.stack[local.top--]; } void getblock(void) { if(shmptr->top<0) { printf("No free block to get!"); return; } local.stack[++local.top]=shmptr->stack[shmptr->top]; shmptr->top--; } //显示可用命令 void showhelp(void) { printf("\navailable COMMAND:\n\n"); printf("help\tlist this help\n"); printf("list\tlist all gotten block number\n"); printf("get\tget a new block\n"); printf("rel\trelease the last gotten block\n"); printf("end\texit this program\n"); } //列出所有已分配块号 void showlist(void) { int i; printf("Listall gotten block number:\n"); for(i=0;i<=local.top;i++) printf("%d\t",local.stack); } //接受输入命令 void getcmdline(void) { printf("\n?> "); fgets(cmdbuf, MAX_CMD-1, stdin); } 2、模拟临界资源访问
实现相应的示例程序功能,记录执行结果,
运行结果:
看是否能观察到程序出现错误情况;
不能。
改造该程序,使错误情况易于观察到,记录执行情况并进行分析;
分析:
为了使错误易于观察,在分配和释放数据块的函数relblock(void)和 getblock(void)改为如下:
void relblock(void) { if(local.top<0) { printf("No block to release!"); return; } shmptr->top++; sleep(10); shmptr->stack[shmptr->top]=local.stack[local.top--]; } void getblock(void) { if(shmptr->top<0) { printf("No free block to get!"); return; } local.stack[++local.top]=shmptr->stack[shmptr->top]; sleep(10); shmptr->top--; } 打开两个终端,即两个申请数据块的进程按照如下运行,及结果:
1》错误一:两个进程同时申请数据块,即get——get。两个进程同时得到了数据块号3, 而一个数据块只能分配给一个进程,同时还把数据块4丢了,故出现错误。
运行结果如下:
进程一:
进程二:
具体执行代码顺序如下:
1>local.stack[++local.top]=shmptr->stack[shmptr->top]; 2>local.stack[++local.top]=shmptr->stack[shmptr->top]; 1>shmptr->top--; 2>shmptr->top--;
错误二:一个进程释放数据块,一个进程申请数据块时,则出错。
运行结果如下:无效的数据块6,再次被分配,错误。
进程一:
进程二:
具体执行代码顺序如下:
1>shmptr->top++; 2>local.stack[++local.top]=shmptr->stack[shmptr->top]; 1>shmptr->stack[shmptr->top]=local.stack[local.top--]; 2>shmptr->top--; |