操作系统上机报告实验一、匿名管道通信一、实验目的学会创建匿名管道,并且能够利用管道进行进程间的通信。
二、实验内容分别建立名为Parent的单文档应用程序和Child的单文档应用程序作为父子进程,由父进程创建一个匿名管道,实现父子进程向匿名管道写入和读取数据。
三、设计与实现过程本实验在VC6.0上实现▪ A.父进程▪先建一个Parent的单文档应用程序,增加“创建管道”“读取数据”“写入数据”三个菜单,并添加消息响应函数OnPipeCreate(),OnPipeRead(),OnPipeWrite()。
在CParentView类中增加成员变量HANDLE类型的hRead,hWrite,初始化变量,并在析构函数中释放句柄:▪void CParentView::OnPipeWrite()▪{▪if(!CreatePipe(…)) /*创建匿名管道*/▪{▪ /*显示消息“创建管道失败!”*/▪ /*退出*/▪}▪if(!CreateProcess(…)) /*创建子进程*/▪{▪ /*关闭句柄hRead、hWrite*/▪ /*显示消息“创建子进程失败!”*/▪ /*退出*/▪}▪}▪void CParentView::OnPipeRead()▪{▪ /*定义一个字符数组,用于存放读取的数据*/▪if(!ReadFile(…)) /*读取数据*/▪{▪ /*显示消息“读取数据失败!”*/▪ /*退出*/▪}▪/*打印读取的数据*/▪/*退出*/▪void CParentView::OnPipeWrite()▪{▪/*定义一个字符数组,用于存放写入的数据*/▪if(!WriteFile(…)) /*写入数据*/▪ /*显示消息“写入数据失败!”*/▪ /*退出*/▪}▪}▪ B.子进程▪建一个Child的单文档,在CChildView中增加两个成员HANDLE 型的成员变量hRead,hWrite,并添加消息响应函数OnPipeRead(),OnPipeWrite(),再添加虚函数OnInitialUpdate(),并在析构函数中释放句柄。
▪void CChildView::OnInitialUpdate()▪{▪hRead=GetStdHandle(…)/*获取标准输入句柄*/▪hWrite=GetStdHandle(…)/*获取标准输出句柄*/▪}▪void CParentView::OnPipeRead()▪{▪ /*定义一个字符数组,用于存放读取的数据*/▪if(!ReadFile(…)) /*读取数据*/▪{▪ /*显示消息“读取数据失败!”*/▪ /*退出*/▪}▪/*打印读取的数据*/▪/*退出*/▪}▪void CParentView::OnPipeWrite()▪{▪/*定义一个字符数组,用于存放写入的数据*/▪if(!WriteFile(…)) /*写入数据*/▪{▪ /*显示消息“写入数据失败!”*/▪ /*退出*/▪}#######################父进程代码####################### void CFatherView::OnPipeCreate(){// TODO: Add your command handler code hereSECURITY_ATTRIBUTES sa;sa.bInheritHandle=TRUE;sa.lpSecurityDescriptor=NULL;sa.nLength=sizeof(SECURITY_ATTRIBUTES);if(!CreatePipe(&hRead,&hWrite,&sa,0)){MessageBox("创建管道失败!");return;}STARTUPINFO sui;PROCESS_INFORMATION pi;ZeroMemory(&sui,sizeof(STARTUPINFO));//将数据清零sui.cb=sizeof(STARTUPINFO);sui.dwFlags=STARTF_USESTDHANDLES;sui.hStdInput=hRead;sui.hStdOutput=hWrite;sui.hStdError=GetStdHandle(STD_ERROR_HANDLE);if(!CreateProcess("H:\\OS作业\\Experiment1_匿名管道通信\\Child\\Debug\\child.exe",NULL,NULL,NULL,TRUE,0,NULL,NU LL,&sui,&pi)){CloseHandle(hRead);CloseHandle(hWrite);//关闭句柄,将内核对象的使用计数减1,这样当操作系统发现内核对象//的使用计数为0时,将清除内核对象。
hRead=NULL;hWrite=NULL;MessageBox("创建子进程失败!");—return;}else{CloseHandle(pi.hProcess);CloseHandle(pi.hThread);}}void CFatherView::OnRead(){// TODO: Add your command handler code herechar buf[100];DWORD dwRead;if(!ReadFile(hRead,buf,100,&dwRead,NULL)){MessageBox("读取数据失败!");return;}MessageBox(buf);}void CFatherView::OnInput(){// TODO: Add your command handler code herechar buf[]="你好,我是父进程!";DWORD dwWrite;if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL)) {MessageBox("写入数据失败!");return;}}#######################子进程代码####################### void CChildView::OnInput(){// TODO: Add your command handler code herechar buf[100];DWORD dwRead;if(!ReadFile(hRead,buf,100,&dwRead,NULL)){MessageBox("读取数据失败!");return;}MessageBox(buf);}void CChildView::OnWrite(){// TODO: Add your command handler code herechar buf[]="匿名管道测试程序";DWORD dwWrite;if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL)) {MessageBox("写入数据失败!");return;}}void CChildView::OnInitialUpdate(){CView::OnInitialUpdate();// TODO: Add your specialized code here and/or call the base classhRead=GetStdHandle(STD_INPUT_HANDLE);hWrite=GetStdHandle(STD_OUTPUT_HANDLE);}四、执行结果与分析创建管道:父进程向子进程发送信息:子进程向父进程发送信息:五、思考与收获这是第一次上机实验,本来没有学过C++,只有C的编程基础,初接触MFC,觉得编程十分吃力,经过辅导老师多次耐心的演示,和指导着做,终于能够自己按流程走一遍。
感觉很有收获,主要是这些课上学到的知识,在生活中很难接触到,通过上机让我真正的能够用代码来操纵计算机的操作系统去工作,减少了理论与实践的差距,让我觉得课堂不再枯燥和空洞。
这次实验让我对管道这种进程间的通信方法有了很直观的感受,通过人机交互的方式,手动地在进程间选择发送和接受数据,强化了对管道通信特点(连接于两个进程之间,以先进先出的方式实现消息的单向传送)的认识。
实验二、创建进程一、实验目的学会通过基本的Windows或者Linux进程控制函数,由父进程创建子进程,并实现父子进程协同工作。
二、实验内容创建两个进程,让子进程读取一个文件,父进程等待子进程读取完文件后继续执行,实现进程协同工作。
进程协同工作就是协调好两个进程,使之安排好先后次序并以此执行,可以用等待函数来实现这一点。
当需要等待子进程运行结束时,可在父进程中调用等待函数。
假设现在有这样的一个工作,需要计算1——100的和,还需要做一个工作是读写文件。
我们可以让父进程计算,创建一个子进程实现读写文件。
三、设计与实现过程主要工作:❝1、首先由父进程创建子进程❝2、让子进程创建一个文件并写入数据,子进程写文件过程中,父进程继续执行计算工作❝3、等子进程执行完以后,父进程读取文件内容输出,实现进程协同工作。
父进程框架❝void main()❝{❝//为创建进程做准备工作❝//创建子进程❝If(创建失败)❝返回❝Else(创建成功)❝//执行计算1——100的和❝//等子进程执行完,读取子进程的文件内容,并输出。
❝}子进程框架❝void main()❝{❝//创建文件❝If(失败)❝返回❝Else(成功)❝//向文件写入数据❝//读取文件内容输出❝}######################父进程代码######################int main(){int i;int sum=0;char Read[100]="";PROCESS_INFORMATION pi;STARTUPINFO sui; //创建进程的准备工作ZeroMemory(&sui,sizeof(sui));sui.cb=sizeof(STARTUPINFO);if(!CreateProcess("H:\\OS作业\\Experiment2_创建进程\\Child\\Debug\\child.exe",NULL,NULL,NULL,FALSE,CREATE_NEW_ CONSOLE,NULL,NULL,&sui,&pi))return 0;else //创建成功//父进程继续执行for(i=1;i<=100;i++){sum+=i;Sleep(10);printf("sum=%d\n",sum);}WaitForSingleObject(pi.hProcess,INFINITE);FILE *pfile1=fopen("H:\\OS作业\\Experiment2_创建进程\\kang.txt","r");fread(Read,sizeof(char),100,pfile1); //fread 第二个参数是每个字符的大小//文件打开方式需改为可读写fclose(pfile1);printf("%s\n",Read);return 0;}######################子进程代码######################int main(){char *Contents="You've made it,aha!\n";char Read[100]="";for(int i=0;i<100;i++){printf("%s",Read+i);}FILE *pfile=fopen("H:\\OS作业\\Experiment2_创建进程\\kang.txt","w+");if(NULL==pfile) //地址双斜线return 0;elseprintf("创建文件文件成功\n");Sleep(500);fwrite(Contents,strlen(Contents),1,pfile);fwrite("You're great!",strlen("You'regreat!"),1,pfile);fclose(pfile);printf("文件成功写入\n");Sleep(500);FILE *pfile1=fopen("H:\\OS作业\\Experiment2_创建进程\\kang.txt","r");fread(Read,sizeof(char),strlen(Contents)+strlen("You're great!"),pfile1); //fread 第二个参数是每个字符的大小 //文件打开方式需改为可读写fclose(pfile1);printf("%s\n",Read);return 0;}四、执行结果与分析父进程执行结果:子进程执行结果:五、思考与收获这次实验通过学习使用windows下的进程创建函数,能够自己创建进程并让两个进程同时工作,并通过等待函数实现两进程的同步。