实验一:Windows API函数
一:实验要求
- 请在代码中你认为重要处加上注释。
- 除了粘贴代码外,请用专门的文字对程序的设计做简要介绍。
- 如果你在做这个程序的过程中遇到了困难、走了弯路,请一一列出,并说明导致问题的原因,以及你最终的解决办法。
二:实验的工程目标
- 熟悉Windows API函数文档的结构、风格;掌握Windows API的调用方法。
- 仔细阅读API函数的文档,确保缓冲区大小参数的正确有效。必要时对返回值进行检查。
- 编写代码获得当前用户名(GetUserName)、系统目录(GetSystemDirectory)、Windows所在目录(GetWindowsDirectory)、环境变量PATH的值等信息(ExpandEnvironmentStrings)。
- 选作:编写代码获得操作系统的版本信息(GetVersionEx)。
三:实验代码
intmain() { charcomputer_name_buffer[MAX_COMPUTERNAME_LENGTH+1]; DWORDcomputer_name_buffer_size=MAX_COMPUTERNAME_LENGTH+1; GetComputerNameA(computer_name_buffer, &computer_name_buffer_size); printf("ComputerName:%s\n", computer_name_buffer); charuser_name_buffer[UNLEN+1]; DWORDuser_name_buffer_size=UNLEN+1; GetUserNameA(user_name_buffer, &user_name_buffer_size); printf("UserName:%s\n", user_name_buffer); charsystem_directory_buffer[1000]; GetSystemDirectoryA(system_directory_buffer, 1000); printf("SystemDirectory:%s\n", system_directory_buffer); charwindows_directory_buffer[MAX_PATH]; GetWindowsDirectoryA(windows_directory_buffer, MAX_PATH); printf("WindowsDirectory%s\n", windows_directory_buffer); constchar*environment_string="%path%"; charenvironment_string_expanded[10000]; ExpandEnvironmentStringsA(environment_string, environment_string_expanded, 10000); printf("EnvironmentPath:%s\n", environment_string_expanded); OSVERSIONINFOversion; ZeroMemory(&version, sizeof(OSVERSIONINFO)); version.dwOSVersionInfoSize=sizeof(OSVERSIONINFO); GetVersionEx(&version); printf("Version:%d.%d %s\n", version.dwMajorVersion, version.dwMinorVersion, version.szCSDVersion); return0; }
四:实验结果
实验二:线程与互斥
一:实验要求
- 请在代码中你认为重要处加上注释。
- 除了粘贴代码外,请用专门的文字对程序的设计做简要介绍。
- 如果你在做这个程序的过程中遇到了困难、走了弯路,请一一列出,并说明导致问题的原因,以及你最终的解决办法
二:实验的工程目标
- 改写money的代码,用“高级锁”即信号量代替“低级锁”,并感受二者的性能差异。如果可以,请用clock函数测量这种差异(选作)。还可以比较使用多线程与单线程的性能差异(选作)。
- 提示:此处信号量代表什么资源?对全局变量money的访问权就是一种资源,这种资源的数量为1。
三:实验代码
usingnamespacestd; intmoney=0; CRITICAL_SECTIONlock; DWORDWINAPIdad(LPVOID) { EnterCriticalSection(&lock); for (inti=0; i<100000; i++) { money++; } LeaveCriticalSection(&lock); return0; } DWORDWINAPImom(LPVOID) { EnterCriticalSection(&lock); for (inti=0; i<100000; i++) { money++; } LeaveCriticalSection(&lock); return0; } DWORDWINAPIoth(LPVOID) { EnterCriticalSection(&lock); for (inti=0; i<100000; i++) { money++; } LeaveCriticalSection(&lock); return0; } intmain() { clock_tstart, middle, finish; doubleTimes; start=clock(); HANDLEthread_dad; HANDLEthread_mom; HANDLEthread_oth; InitializeCriticalSection(&lock); thread_dad=CreateThread(nullptr, 0, dad, nullptr, 0, nullptr); thread_mom=CreateThread(nullptr, 0, mom, nullptr, 0, nullptr); thread_oth=CreateThread(nullptr, 0, oth, nullptr, 0, nullptr); middle=clock(); Times= (double) (middle-start) /CLOCKS_PER_SEC; cout<<"低级锁运行时间(秒): "<<Times<<endl; WaitForSingleObject(thread_dad, INFINITE); WaitForSingleObject(thread_mom, INFINITE); WaitForSingleObject(thread_oth, INFINITE); DeleteCriticalSection(&lock); finish=clock(); Times= (double) (finish-middle) /CLOCKS_PER_SEC; cout<<"高级锁运行时间(秒): "<<Times<<endl; return0; }
四:实验结果
实验三:页置换模拟
一:实验要求
- 请在代码中你认为重要处加上注释。
- 除了粘贴代码外,请用专门的文字对程序的设计做简要介绍。
- 如果你在做这个程序的过程中遇到了困难、走了弯路,请一一列出,并说明导致问题的原因,以及你最终的解决办法。
二:实验的工程目标
- 给定一个页面访问的轨迹,程序模拟先进先出置换算法下操作系统的行为。
- 参考FIFO置换算法的模拟程序,实现LRU算法的模拟程序。
- 选作:加上一列显示调出页;修复程序的bug(提示:FIFOQueue数组元素为0时,是表示没东西)
- 考虑下述页面走向:1,2,3,4,2,1,5,6,2,1,2,3,7,6,3,2,1,2,3,6,当内存块数量分别为3时,试问FIFO、LRU置换算法的缺页次数各是多少?
三:实验代码
constintMemCapacity=3; intFIFOQueue[MemCapacity] = {0}; intexit_page=0; intpageInMainMem(intpage) { for (inti=0; i<MemCapacity; i++) { if (FIFOQueue[i] ==page) returni; } return-1; } voidfoldPage(intpage) { for (inti=MemCapacity-1; i>0; i--) FIFOQueue[i] =FIFOQueue[i-1]; FIFOQueue[0] =page; } intmain() { intpageFootprints[] = {1, 2, 3, 4, 2, 1, 5, 6, 2, 1, 2, 3, 7, 6, 3, 2, 1, 2, 3, 6}; intpageNum=sizeofpageFootprints/sizeofpageFootprints[0]; intRequestCount=0; boolrequest; printf("时刻\t访问页面\t主存状态\t缺页中断\t调入页\t调出页\n"); for (inti=0; i<pageNum; i++) { printf("%3d\t %2d\t ", i, pageFootprints[i]); request=false; if (pageInMainMem(pageFootprints[i]) ==-1) { if (FIFOQueue[MemCapacity-1] !=0) { exit_page=FIFOQueue[MemCapacity-1]; } foldPage(pageFootprints[i]); RequestCount++; request=true; } for (intj: FIFOQueue) printf("%2d ", j); if (request) { printf("\t\t+"); printf("\t %d", pageFootprints[i]); if (exit_page!=0) { printf("\t %d", exit_page); } } printf("\n"); } printf("缺页中断次数 = %d\n", RequestCount); printf("缺页率 = %d/%d = %.2f%%\n", RequestCount, pageNum, (float) RequestCount/ (float) pageNum*100); return0; }
四:实验结果
实验四:创建进程
一:实验要求
- 请在代码中你认为重要处加上注释。
- 除了粘贴代码外,请用专门的文字对程序的设计做简要介绍。
- 如果你在做这个程序的过程中遇到了困难、走了弯路,请一一列出,并说明导致问题的原因,以及你最终的解决办法。
二:实验的工程目标
使用CreateProcess函数创建新的进程。程序中创建新的进程,新进程执行记事本的可执行文件打开记事本,主进程休眠,等待记事本进程结束。用户关闭记事本后,WinMain函数中的主进程关闭进程句柄后结束。
三:实验代码
intAPIENTRYWinMain(HINSTANCEhInstance, HINSTANCEhPrevInstance, LPSTRlpCmdLine, intnCmdShow) { TCHARsCommandLine[1000]; BOOLret; DWORDdwExitCode; PROCESS_INFORMATIONpi; STARTUPINFOsi= {sizeof(si)}; //得到Windows目录GetWindowsDirectory(sCommandLine, MAX_PATH); //启动"记事本"程序的命令行strcat(sCommandLine, "\\notepad.exe"); // 启动"记事本"作为子进程ret=CreateProcess(nullptr, sCommandLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi); if (ret) { CloseHandle(pi.hThread); //关闭子进程的主线程句柄WaitForSingleObject(pi.hProcess, INFINITE); //等待子进程的退出GetExitCodeProcess(pi.hProcess, &dwExitCode); //获取子进程的退出码CloseHandle(pi.hProcess); //关闭子进程句柄 } return0; }
四:实验结果
实验五:进程中启动计算器子程序
一:实验要求
- 请在代码中你认为重要处加上注释。
- 除了粘贴代码外,请用专门的文字对程序的设计做简要介绍。
- 如果你在做这个程序的过程中遇到了困难、走了弯路,请一一列出,并说明导致问题的原因,以及你最终的解决办法。
二:实验的工程目标
用程序实现启动一个新的进程,并在进程中启动计算器应用程序(calc.exe)。
三:实验代码
intmain() { charpath[10] ="calc.exe"; DWORDdwExitCode; PROCESS_INFORMATIONpi; DWORDret; STARTUPINFOsi= {sizeof(si)}; ret=CreateProcess(nullptr, path, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi); if (ret) { WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hThread); GetExitCodeProcess(pi.hProcess, &dwExitCode); CloseHandle(pi.hProcess); } printf("\n进程结束,退出码是 %ld\n", ret); return0; }
四:实验结果
实验六:建立线程(一个线程,主线程不休眠)
一:实验要求
- 请在代码中你认为重要处加上注释。
- 除了粘贴代码外,请用专门的文字对程序的设计做简要介绍。
- 如果你在做这个程序的过程中遇到了困难、走了弯路,请一一列出,并说明导致问题的原因,以及你最终的解决办法。
二:实验的工程目标
程序演示使用函数_beginthreadex启动线程。
三:实验代码
unsignedintWINAPIFun(LPVOIDlpParamter) { while (true) { printf("---Fun display!\n"); Sleep(500);//休眠0.5s } return0; } intmain() { HANDLEhThread; hThread= (HANDLE) _beginthreadex(nullptr, 0, Fun, nullptr, 0, nullptr);//创建线程,执行Fun函数while (true) { printf("main display!\n"); Sleep(500);//休眠0.5s } CloseHandle(hThread);//关闭句柄return0; }
四:实验结果