操作系统原理实验报告.docx

上传人:b****5 文档编号:6909377 上传时间:2023-01-12 格式:DOCX 页数:94 大小:1.04MB
下载 相关 举报
操作系统原理实验报告.docx_第1页
第1页 / 共94页
操作系统原理实验报告.docx_第2页
第2页 / 共94页
操作系统原理实验报告.docx_第3页
第3页 / 共94页
操作系统原理实验报告.docx_第4页
第4页 / 共94页
操作系统原理实验报告.docx_第5页
第5页 / 共94页
点击查看更多>>
下载资源
资源描述

操作系统原理实验报告.docx

《操作系统原理实验报告.docx》由会员分享,可在线阅读,更多相关《操作系统原理实验报告.docx(94页珍藏版)》请在冰豆网上搜索。

操作系统原理实验报告.docx

操作系统原理实验报告

 

《操作系统原理》

实验报告

 

班级:

姓名:

学号:

指导老师:

目录:

实验题目:

实验一线程创建与撤销

完成人:

XXX

报告日期:

2018年3月31日

一、实验内容简要描述

(1)熟悉VC++、VisualStudio开发环境。

(2)使用相关函数创建和撤销线程。

(3)在一个进程中创建3个线程,名字分别为threada、threadb、threadc。

threada输出“helloworld!

”。

threadb输出“Mynameis…”。

threadc输出“Pleasewait…”,然后sleep5秒钟,接着输出“Iwakeup”。

二、程序设计

1、设计思路

该函数创建一个在调用进程的地址空间中执行的线程。

2、主要数据结构

HANDLECreateThread(

LPSECURITY_ATTRIBUTESlpThreadAttributes,

DWORDdwStackSize,

LPTHREAD_START_ROUTINElpStartAddress,

LPVOIDlpParameter,

DWORDdwCreationFlags,

LPDWORDlpThreadId

);

VOIDExitThread(DWORDdwExitCode);

VOIDSleep(DWORDdwMilliseconds);

VOIDSleep(DWORDdwMilliseconds);

 

三、实验结果

1、基本数据

lpThreadAttributes:

指向一个SECURITY_ATTRIBUTES结构,该结构决定了返回的句柄是否可被子进程继承。

若lpThreadAttributes为NULL,则句柄不能被继承。

在WindowsNT中该结构的lpSecurityDescriptor成员定义了新进程的安全性描述符。

若lpThreadAttributes为NULL,则线程获得一个默认的安全性描述符。

dwStackSize:

定义原始堆栈提交时的大小(按字节计)。

系统将该值舍入为最近的页。

若该值为0,或小于默认时提交的大小,默认情况是使用与调用线程同样的大小。

更多的信息,请看ThreadStackSize。

lpStartAddress:

指向一个LPTHREAD_START_ROUTlNE类型的应用定义的函数,该线程执行此函数。

该指针还表示溃程进程中线程的起始地址。

该函数必须存在于远程进程中。

lpParameter:

定义一个传递给该迸程的32位值。

dwCreationFIags:

定义控制进程创建的附加标志。

若定义了CREATE_SUSPENDED标志,线程创建时处于挂起状态,并且直到ResumeThread函数调用时d能运行。

若该值为0,则该线程在创建后立即执行。

lpThreadId:

指向一个32位值,它接收该线程的标识符。

2.

源程序代码行数

完成该实验投入的时间(小时数)

与其他同学讨论次数

31

1

1

 

3、测试结果分析

四、实验体会

1、实验体会和收获

深入理解了线程与进程的概念,熟悉了在Windows环境下何时使用进程,何时使用线程,怎么创建和撤销线程。

五、源代码

#include

#include

usingnamespacestd;

DWORDWINAPIta(LPVOIDargv)

{

cout<<"HelloWorld!

\n";

}

DWORDWINAPItb(LPVOIDargv)

{

cout<<"我的名字:

孙婷\n";

cout<<"我的学号:

141340209\n";

}

DWORDWINAPItc(LPVOIDargv)

{

cout<<"Pleasewait...\n";

Sleep(5000);

cout<<"Iwakeup.\n";

}

intmain()

{

HANDLEthreada,threadb,threadc;

DWORDTEST;

threada=CreateThread(NULL,0,ta,NULL,0,0);

threadb=CreateThread(0,0,tb,0,0,0);

threadc=CreateThread(0,0,tc,0,0,0);

ExitThread(TEST);

ExitThread(TEST);

ExitThread(TEST);

return0;

}

 

实验题目:

实验二线程同步

完成人:

XXX

报告日期:

2018年4月7日

一、实验内容简要描述

1)在程序中使用CreateSemaphore(NULL,0,1,”SemaphoreName1”)创建一个名为SemaphoreName1的信号量,其初值为0。

2)使用OpenSemaphore(SYNCHRONIZE|SEMAPHORE__MODIFY_STA

TE,NULL,”SemaphoreName1”)打开该信号量。

3)创建一个子线程,主线程创建子线程后调WaitForSingleObject(hHandle,

INFINITE),这里等待时间设置为INFINITE表示要一直等待下去,直到该信号量被唤醒为止。

4)子线程sleep5秒钟,然后输出“Iamover.”结束,调用ReleaseSemaphore(hHandle1,1,NULL)释放信号量,使信号量的值加1。

二、程序设计

1、设计思路

A)等待一个对象

WaitForSingleObjects函数决定等待条件是否被满足。

如果等待条件并没有被满足,调用线程进人一个高效的等待状态,当等待满足条件时占用非常少的处理器时间。

在运行前,一个等待函数修改同步对象类型的状态。

修改仅发生在引起函数返回的对象身上。

例如,信号的计数减l。

WaitForSingleObject函数能等待的对象包括:

Changenotification(改变通告);Consoleinput(控制台输入);Event(事件);Job(作业);Mutex(互斥对象);Process(进程);Semaphore(信号量);Thread(线程);Waitabletimer(可等待定时器)。

当使用等待函数或代码直接或间接创建窗口时,一定要小心。

如果一个线程创建了任何窗口,它必须处理进程消息。

消息广播被发送到系统的所有窗口。

一个线程用没有超时的等待函数也许会引起系统死锁。

间接创建窗口的两个例子是DDE和COMCoInitialize。

因此,如果用户有一个创建窗口的线程,用MsgWaitForMultipleObjects或MsgWaitForMultipleObjectsEx函数,而不要用

SignalObjectAndWait函数。

B)等待多个对象

WaiForMultipleObjects函数当下列条件之一满足时返回:

(1)任意一个或全部指定对象处于信号态;

(2)超时间隔已过。

C)创建信号量

如果成功就传回一个handle,否则传回NULL。

不论哪一种情况,GetLastError都会传回一个合理的结果。

如果指定的Semaphore名称已经存在,则函数还是成功的,GetLastError会传回ERROR_ALREADY_EXISTS。

D)打开信号量

为现有的一个已命名信号机对象创建一个新句柄。

E)增加信号量的值

该函数将指定信号对象的计数增加一个指定的值。

 

2、主要数据结构

DWORDWaitForSingleObject(HANDLEhHandle,DWORDdwMilliseconds);

DWORDWaitForMultipleObjects(

DWORDnCount,

CONSTHANDLE*lpHandles,

BOOLfWaitAll,

DWORDdwMilliSeconds

HANDLECreateSemaphore(

LPSECURITY_ATTRIBUTESlpAttributes,

LONGlInitialCount,

LONGlMaximumCount,

LPCTSTRlpName

);

HANDLEOpenSemaphore(

DWORDdwDesiredAccess,//访问标志

BOOLbInheritHandle,//继承标志

LPCTSTRlpName//信号量名

);

BOOLReleaseSemaphore(

HANDLEhSemaphore,

LONGlReleaseCount,

LPLONGlpPreviousCount

三、实验结果

1、基本数据

源程序代码行数

完成该实验投入的时间(小时数)

与其他同学讨论次数

61

2

1

2、测试结果分析

 

四、实验体会

1、实验体会和收获

进一步认识了线程同步的实质,学会使用信号量控制线程间的同步。

 

五、源代码

#include

#include

#include

staticHANDLEhThread1;//子进程的句柄,作为主线程的局部变量也行

staticHANDLEhHandle1=NULL;//信号量的句柄,全局变量

voidfunc();//子线程的声明

intmain(intargc,TCHAR*argv[],TCHAR*envp[])

{

intnRetCode=0;

DWORDdwThreadID1;

DWORDdRes,err;

hHandle1=CreateSemaphore(NULL,0,1,"SemaphoreName1");//创建一个信号量

if(hHandle1==NULL)printf("SemaphoreCreateFail!

\n");

elseprintf("SemaphoreCreateSuccess!

\n");

hHandle1=OpenSemaphore(SYNCHRONIZE|SEMAPHORE_MODIFY_STATE,NULL,"SemaphoreName1");

if(hHandle1==NULL)printf("SemaphoreOpenFail!

\n");

elseprintf("SemaphoreOpenSuccess!

\n");

hThread1=CreateThread((LPSECURITY_ATTRIBUTES)NULL,0,

(LPTHREAD_START_ROUTINE)func,

(LPVOID)NULL,

0,&dwThreadID1);//创建子线程

if(hThread1==NULL)printf("Thread1createFail!

\n");

elseprintf("Thread1createSuccess!

\n");

dRes=WaitForSingleObject(hHandle1,INFINITE);//主线程等待子线程结束

err=GetLastError();

printf("WaitForSingleObjecterr=%d\n",err);

if(dRes==WAIT_TIMEOUT)

printf("TIMEOUT!

dRes=%d\n",dRes);

elseif(dRes==WAIT_OBJECT_0)

printf("WAIT_OBJECT!

dRes=%d\n",dRes);

elseif(dRes==WAIT_ABANDONED)

printf("WAIT_ABANDONED!

dRes=%d\n",dRes);

elseprintf("dRes=%d\n",dRes);

CloseHandle(hThread1);

CloseHandle(hHandle1);

printf("我的名字:

孙婷\n");

printf("我的学号:

141340209\n");

ExitThread(0);

returnnRetCode;

}

//实现子线程

voidfunc()

{

BOOLrc;

DWORDerr;

printf("NowInThread!

\n");

printf("Iamover.\n");

rc=ReleaseSemaphore(hHandle1,1,NULL);//子线程唤醒主线程

err=GetLastError();

printf("ReleaseSemaphoreerr=%d\n",err);

if(rc==0)printf("SemaphoreReleaseFail!

\n");

elseprintf("SemaphoreReleaseSuccess!

rc=%d\n",rc);

}

 

实验题目:

实验三线程互斥

完成人:

XXX

报告日期:

2018年4月14日

三、实验内容简要描述

完成两个子线程之间的互斥。

在主线程中使用系统调用CreateThread()创建两个子线程,并使两个子线程互斥的使用全局变量count。

四、程序设计

3、设计思路

a.使用临界区对象(Criticalsection)

CriticalSectionObject,Asegmentofcodethatisnotreentrantandthereforedoesnotsupportconcurrentaccessbymultiplethreads.Often,acriticalsectionobjectisusedtoprotectsharedresources。

通过定义在数据段中的一个CRITICAL_SECTION结构实现。

CRITICAL_SECTIONmyCritical;

并且在任何线程使用此临界区对象之前必须对它进行初始化。

voidInitializeCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);

之后,任何线程访问临界区中数据的时候,必须首先调用EnterCriticalSection函数,申请进入临界区(又叫关键代码段,使用共享资源的任何代码都必须封装在此)。

在同一时间内,Windows只允许一个线程进入临界区。

所以在申请的时候,如果有另一个线程在临界区的话,EnterCriticalSection函数会一直等待下去,直到其他线程离开临界区才返回。

EnterCriticalSection函数用法如下:

voidEnterCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);

当操作完成的时候,还要将临界区交还给Windows,以便其他线程可以申请使用。

这个工作由LeaveCriticalSection函数来完成。

voidLeaveCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);

当程序不再使用临界区对象的时候,必须使用DeleteCriticalSection函数将它删除。

voidDeleteCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);

b.使用互斥锁(Interlocked)

提供一种手段来保证值的递增(减)能够以原子操作方式来进行,也就是不中断地进行。

LONGInterlockedIncrement(LPLONGlpAddend);//增一操作

LONGInterlockedDecrement(LPLONGlpAddend);//减一操作

LONGInterlockedExchangeAdd(

PLONGAddend,//pointertotheaddend

LONGIncrement//incrementvalue

);//增减任意值

 

4、主要数据结构

voidInitializeCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);

voidEnterCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);

voidLeaveCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);

voidDeleteCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);

LONGInterlockedIncrement(LPLONGlpAddend);//增一操作

LONGInterlockedDecrement(LPLONGlpAddend);//减一操作

LONGInterlockedExchangeAdd(

PLONGAddend,//pointertotheaddend

LONGIncrement//incrementvalue

 

三、实验结果

1、基本数据

源程序代码行数

完成该实验投入的时间(小时数)

与其他同学讨论次数

68

2

0

 

2.测试结果分析

四、实验体会

1、实验体会和收获

熟练了Windows系统环境下线程的创建与撤销,熟悉了Windows系统提供的线程互斥API,使用Windows系统提供的线程互斥API解决实际问题。

五、源代码

#include

#include

#include

staticintcount=5;//共享变量

staticHANDLEh1,h2;//两个子进程的句柄变量

LPCRITICAL_SECTIONhCriticalSection;//定义指向临界区对象的地址指针

CRITICAL_SECTIONCritical;//定义临界区

voidfunc1();//线程函数的定义不符合WIN32格式,后面CreateThread函数中

voidfunc2();//要附加强制类型转换

//主线程的实现

intmain(intargc,TCHAR*argv[],TCHAR*envp[])

{

intnRetCode=0;

DWORDdwThreadID1,dwThreadID2;

hCriticalSection=&Critical;//将指向临界区的对象的指针指向临界区

InitializeCriticalSection(hCriticalSection);//初始化临界区

//创建子线程func1

h1=CreateThread((LPSECURITY_ATTRIBUTES)NULL,

0,

(LPTHREAD_START_ROUTINE)func1,

(LPVOID)NULL,

0,&dwThreadID1);

if(h1==NULL)printf("Thread1createFail!

\n");

elseprintf("Thread1createsuccess!

\n");

//创建子线程func2

h2=CreateThread((LPSECURITY_ATTRIBUTES)NULL,

0,

(LPTHREAD_START_ROUTINE)func2,

(LPVOID)NULL,

0,&dwThreadID2);

if(h2==NULL)printf("Thread2createFail!

\n");

elseprintf("Thread2createsuccess!

\n");

Sleep(1000);

CloseHandle(h1);

CloseHandle(h2);

DeleteCriticalSection(hCriticalSection);//删除临界区

ExitThread(0);

returnnRetCode;

}//主线程结束

//子线程func2的实现

voidfunc2()

{

intr2;

EnterCriticalSection(hCriticalSection);//进入临界区

r2=count;

Sleep(100);

r2=r2+1;

count=r2;

printf("countinfunc2=%d\n",count);

LeaveCriticalSection(hCriticalSection);//退出临界区

}

//子线程func1的实现

voidfunc1()

{

intr1;

EnterCriticalSection(hCriticalSection);//进入临界区

r1=count;

Sleep(500);

r1=r1+1;

count=r1;

printf("countinfunc1=%d\n",count);

LeaveCriticalSection(hCriticalSection);//退出临界区

}

 

实验题目:

实验四进程通信

完成人:

XXX

报告日期:

2018年4月21日

五、实验内容简要描述

1)利用命名管道的相关知识及函数,分别编写服务器进程和客户端进程程序。

2)要求服务器进程和客户端进程程序能够通过互相传送数据。

3)当服务器进程和客户端进程中的任何一端输入“end”时,结束会话。

六、程序设计

5、设计思路

(1)建立命名管道

(2)连接命名管道

(3)拆除命名管道的连接

(4)客户端进程连接服务器已建立的命名管道

(5)客户端进程等待命名管道

6、主要数据结构

HandleCreateNamedPipe(LPCTSTRlpName,……);

BOOLConnectNamedPipe(HANDLEhNamePipe,OVERLAPPEDlpOverlapped);

BOOLDisconnectNamedPipe(LonghNamedPipe);

BOOLCallNamedPipe(StringlpNamedPipeName,//欲打开管道的名称 

lpInBufferAny,//要写入管道的数据的内存缓冲区

nInBufferSizeLong,//内存缓冲区中的字符数量

lpOutBufferAny,//指定一个内存缓冲区,用于装载从管道中读出的数据  

nOutBufferSizeLong,//指定一个长整数变量,用于装载来自管道的数据

lpBytesReadLong,//指定从管道中读出的字节数

nTimeOutLong,//管道是否可用及超时设置

);

BOOLWaitNamedPipe(LPCTSTRlpNamedPipeNam

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工作范文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1