操作系统上机报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
操作系统上机报告
实验一、匿名管道通信
一、实验目的
学会创建匿名管道,并且能够利用管道进行进程间的通信。
二、实验内容
分别建立名为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 here
SECURITY_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 here
char buf[100];
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
MessageBox("读取数据失败!");
return;
}
MessageBox(buf);
}
void CFatherView::OnInput()
{
// TODO: Add your command handler code here
char buf[]="你好,我是父进程!";
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL)) {
MessageBox("写入数据失败!");
return;
}
}
#######################子进程代码####################### void CChildView::OnInput()
{
// TODO: Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
MessageBox("读取数据失败!");
return;
}
MessageBox(buf);
}
void CChildView::OnWrite()
{
// TODO: Add your command handler code here
char 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 class
hRead=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;
else
printf("创建文件文件成功\n");
Sleep(500);
fwrite(Contents,strlen(Contents),1,pfile);
fwrite("You're great!",strlen("You're
great!"),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下的进程创建函数,能够自己创建进程并让两个进程同时工作,并通过等待函数实现两进程的同步。
一个很直观的感觉就是原来编程运行只有一个命令框,现在有两个可以同时工作,直观的感受到CPU多个进程并发执行,而且通过课堂上的学习,我知道了CPU在微观上时交替、穿插的执行不同进程。
进程是操作系统核心的概念之一,这次实验为后续课程的学习以及后续实验打下了良好的基础。
实验三、线程共享进程数据
一、实验目的
了解线程与进程之间的数据共享关系。
创建一个线程,在线程
中更改进程中的数据。
二、实验内容
在进程中定义全局共享数据,在线程中直接引用该数据进行更
改并输出该数据。
三、设计与实现过程
主进程框架:static int count;//全局变量,属于主进程,主进程创建的线程共享此数据。
←void main()
←{
←//创建新线程
←//用WaitForSingleObject()等待线程运行结束
←}
←在上述等待函数处,进程等待线程运行,如果进程不等待,主进程结束时,系统会清理进程资源,也就清除了线程运行的一切资源,线程没来得及运行就结束了,也可以用Sleep()实现进程等待
线程函数
←//在线程中修改进程的全局变量并输出
←DWORD WINAPI ThreadProc(LPVOID lpParameter)
←{
←for(count=1;count<=5;count++)//循环5次,改变全局变量count的值
←{
←//输出count
←}
←//线程结束
←}
######################程序代码######################
static int Count;
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
printf("新线程运行\n");
for(Count=1;Count<=5;Count++)//循环5次,改变全局变量count的值
{
printf("线程Count=%d\n",Count);
Sleep(250);
}
printf("线程等待5s\n");
Sleep(5000);
printf("新线程结束\n");//线程结束
return 0;
}
int main()
{
HANDLE Thr;
printf("进程开始\n进程Count=10\n");
Thr=CreateThread(NULL,100,ThreadProc,NULL,0,NULL);
WaitForSingleObject(Thr,INFINITE);
printf("进程结束\n");
return 0;
}
四、执行结果与分析
程序执行结
果:
五、思考与感悟
这次实验,在上次实验对进程学习的基础上,又学习了线程,在程序中可以看到线程可以直接修改主进程中的全局变量,从中可以看出线程与进程间数据共享的关系。
本实验也体现出了进程与线程间相似的地方和不同的地方。
本实验是实现了一个单进程多线程结构,一个进程中的所有线程都共享该进程中的资源和地址空间,访问相同数据源,当一个线程修改了数据,其他线程都将读出修改后的数据。
实验四、信号通信
一、实验目的
利用信号通信机制在父子进程及兄弟进程间进行通信。
二、实验内容
利用信号通信机制在父子进程及兄弟进程间进行通信。
三、设计与实现过程
▪本实验在VC6.0上实现
▪ A.父进程
▪#include "process.h"
▪#include "windows.h"
▪#include "iostream.h"
▪int main( )
▪{
▪CreateEvent( …) /*创建一个有名事件*/
▪if(!CreateProcess(… )) /*创建子进程*/
▪{
▪ /*打印“创建子进程失败!”*/
▪/*退出*/
▪}
▪/*打印"Wait for event."*/
▪if(WAIT_FAILED==WaitForSingleObject(…))/*等待事件信号*/
▪{
▪/*打印“等待事件信号失败!”*/
▪ /*退出*/
▪}
▪/*打印"Get the event"*/
▪return 0;
▪}
B.子进程
▪#include "process.h"
▪#include "windows.h"
▪#include "iostream.h"
▪int main( )
▪{
▪OpenEvent(… )/*打开命名事件*/
▪/*休眠一段时间*/
▪/*打印“Signal the event to Parent?[y\\n]”*/
/*确定是否发送信号*/
▪SetEvent(… )/*将事件置为有信号状态*/
▪/*休眠一段时间*/
▪return 0;
▪}
######################父进程代码###################### int main()
{
//LPCTSTR lpName;
CreateEvent(NULL,FALSE,FALSE,"Event_of_kang");
PROCESS_INFORMATION pi;
STARTUPINFO sui; //创建进程的准备工作
ZeroMemory(&sui,sizeof(sui));
sui.cb=sizeof(STARTUPINFO);
if(!CreateProcess("H:\\OS作业\\Experiment4_信号通信
\\Child\\Debug\\child.exe",NULL,NULL,NULL,FALSE,CREATE_N EW_CONSOLE,NULL,NULL,&sui,&pi))
{
printf("Failed to create a process!\n");
return 0;
}
else //创建成功
{ //父进程继续执行
printf("Wait for event\n");
if(WAIT_FAILED==WaitForSingleObject(pi.hProcess,INFINITE ))/*等待事件信号*/
{
printf("Failed to get the signal of event");//打印“等待事件信号失败!”
return 0;/*退出*/
}
else
{
printf("Get the event\n");
}
}
return 0;
}
######################子进程代码##################### int main()
{
//LPCTSTR lpName;
HANDLE E;
char Sig_Flag;
E=OpenEvent(EVENT_ALL_ACCESS,TRUE,"Event_of_kang"); Sleep(3000);
printf("Signal the event to Parent?[y\\n]\n"); //There should be double"\" to print a'"\"
scanf("%c",&Sig_Flag);
if(Sig_Flag=='y')
{
SetEvent(E);
}
CloseHandle(E);
Sleep(3000);
return 0;
}
四、执行结果与分析父进程运行结果:
子进程运行结果:
五、思考与收获
这次实验同样用到进程创建,并且进行进程间的通信。
只是这次是通过事件信号来实现进程间时间的相互控制。
在以前的编程学习中,几乎没有调用过系统函数,经过这几次实验,对有关进程还有其他一些操作文件的函数有了很多的使用和了解,这些系统函数对自己来说不再显得那么复杂难懂。
能够真切的对操作系统有了感悟,能够使用操作系统从微观上按自己的目的去做一些工作,加深了对操作系统内部运行机制的了解。