当前位置:首页 > 计算机操作系统实验指导书
《操作系统管理》实验指导书
FALSE, // 不继承句柄 0, // 特殊的创建标志 NULL, // 新环境 NULL, // 当前目录 &si, // 启动信息结构 &pi ) ; // 返回的进程信息结构
// 释放对子进程的引用
if (bCreateOK) {
:: CloseHandle(pi.hProcess); :: CloseHandle(pi.hThread); }
return(bCreateOK) ; }
// 下面的方法创建一个事件和一个子进程,然后等待子进程在返回前向事件发出信号 void WaitForChild() {
// create a new event object for the child process // to use when releasing this process
HANDLE hEventContinue = :: CreateEvent( NULL, // 缺省的安全性,子进程将具有访问权限 TRUE, // 手工重置事件 FALSE, // 初始时是非接受信号状态 g_szContinueEvent); // 事件名称 if (hEventContinue!=NULL)
{ std :: cout << \ // 创建子进程 if (:: CreateChild()) {
std :: cout << \
// 等待,直到子进程发出信号
std :: cout << \ :: WaitForSingleObject(hEventContinue, INFINITE);
:: Sleep(1500); // 删去这句试试 std :: cout << \endl;
}
// 清除句柄
:: CloseHandle(hEventContinue);
hEventContinue = INVALID_HANDLE_VALUE; } }
// 以下方法在子进程模式下被调用,其功能只是向父进程发出终止信号 void SignalParent() {
// 尝试打开句柄 std :: cout << \
26
《操作系统管理》实验指导书
HANDLE hEventContinue = :: OpenEvent( EVENT_MODIFY_STATE, // 所要求的最小访问权限 FALSE, // 不是可继承的句柄 g_szContinueEvent); // 事件名称 if (hEventContinue != NULL) {
:: SetEvent(hEventContinue); std :: cout << \ }
// 清除句柄
:: CloseHandle(hEventContinue) ;
hEventContinue = INVALID_HANDLE_VALUE; }
int main(int argc, char* argv[] ) {
// 检查父进程或是子进程是否启动
if (argc>1 && :: strcmp(argv[1] , \ { // 向父进程创建的事件发出信号 :: SignalParent() ;
} else { // 创建一个事件并等待子进程发出信号 :: WaitForChild() ; :: Sleep(1500) ;
std :: cout << \ }
return 0; }
步骤4:单击“Build”菜单中的“Compile 4-1.cpp”命令,并单击“是”按钮确认。系统对4-1.cpp进行编译。
步骤5:编译完成后,单击“Build”菜单中的“Build 4-1.exe”命令,建立4-1.exe可执行文件。
操作能否正常进行?如果不行,则可能的原因是什么?
____________________________________________________________________ ________________________________________________________________________ 步骤6:在工具栏单击“Execute Program” (执行程序) 按钮,执行4-1.exe程序。 运行结果 (分行书写。如果运行不成功,则可能的原因是什么?) :
1) __________________________________________________________________ 2) __________________________________________________________________ 3) __________________________________________________________________ 4) __________________________________________________________________ 5) __________________________________________________________________ 6) __________________________________________________________________ 这个结果与你期望的一致吗?(从进程并发的角度对结果进行分析) 阅读和分析程序4-1,请回答:
1) 程序中,创建一个事件使用了哪一个系统函数?创建时设置的初始信号状态是什么? a. __________________________________________________________________ b. __________________________________________________________________ 2) 创建一个进程 (子进程) 使用了哪一个系统函数?
____________________________________________________________________ 3) 从步骤6的输出结果,对照分析4-1程序,可以看出程序运行的流程吗?请简单描述:
27
《操作系统管理》实验指导书
____________________________________________________________________ ________________________________________________________________________ ________________________________________________________________________ ________________________________________________________________________ ________________________________________________________________________ ________________________________________________________________________
2. 互斥体对象
清单4-2的程序中显示的类CCountUpDown使用了一个互斥体来保证对两个线程间单一数值的访问。每个线程都企图获得控制权来改变该数值,然后将该数值写入输出流中。创建者实际上创建的是互斥体对象,计数方法执行等待并释放,为的是共同使用互斥体所需的资源 (因而也就是共享资源) 。
步骤7:在Visual C++ 窗口的工具栏中单击“打开”按钮,在“打开”对话框中找到并打开实验源程序4-2.cpp。
清单4-2 利用互斥体保护共享资源 // mutex项目
# include
// 利用互斥体来保护同时访问的共享资源 class CCountUpDown {
public:
// 创建者创建两个线程来访问共享值 CCountUpDown(int nAccesses) :
m_hThreadlnc(INVALID_HANDLE_VALUE) , m_hThreadDec(INVALID_HANDLE_VALUE) , m_hMutexValue(INVALID_HANDLE_VALUE) , m_nValue(0) ,
m_nAccess(nAccesses) {
// 创建互斥体用于访问数值
m_hMutexValue = :: CreateMutex( NULL, // 缺省的安全性 TRUE, // 初始时拥有,在所有的初始化结束时将释放 NULL) ; // 匿名的 m_hThreadInc = :: CreateThread( NULL, // 缺省的安全性 0, // 缺省堆栈 IncThreadProc, // 类线程进程 reinterpret_cast
// 允许另一线程获得互斥体
:: ReleaseMutex(m_hMutexValue) ;
28
《操作系统管理》实验指导书
}
// 解除程序释放对对象的引用
virtual ~CCountUpDown()
{
:: CloseHandle(m_hThreadInc) ; :: CloseHandle(m_hThreadDec) ; :: CloseHandle(m_hMutexValue) ; }
// 简单的等待方法,在两个线程终止之前可暂停主调者 virtual void WaitForCompletion() {
// 确保所有对象都已准备好
if (m_hThreadInc != INVALID_HANDLE_VALUE && m_hThreadDec != INVALID_HANDLE_VALUE) {
// 等待两者完成 (顺序并不重要)
:: WaitForSingleObject(m_hThreadInc, INFINITE) ; :: WaitForSingleObject(m_hThreadDec, INFINITE) ; } }
protected:
// 改变共享资源的简单的方法 virtual void DoCount(int nStep) {
// 循环,直到所有的访问都结束为止 while (m_nAccess > 0) {
// 等待访问数值
:: WaitForSingleObject(m_hMutexValue, INFINITE) ;
// 改变并显示该值 m_nValue += nStep;
std :: cout << “thread: ” << :: GetCurrentThreadId() << “value: ” << m_nvalue
<< “access: ” << m_nAccess << std :: endl;
// 发出访问信号并允许线程切换 --m_nAccess; :: sleep(l000) ; // 使显示速度放慢
// 释放对数值的访问
:: ReleaseMutex(m_hMutexValue) ; } }
static DWORD WINAPI IncThreadProc(LPVOID lpParam) {
// 将参数解释为 ?this? 指针 CCountUpDown* pThis =
reinterpret_cast < CCountUpDown* > (lpParam) ;
// 调用对象的增加方法并返回一个值
pThis -> DoCount(+1) ;
29
共分享92篇相关文档