1、操作系统大作业姓名:XXX 学号:02113XXX实验一一、实验目的获得当前系统中正在运行的所有进程的优先级。二、 设计思路和程序流程设计思路:通过CreateToolhelp32Snapshot函数获得系统中正在运行的进程的快照,再通过PROCESSENTRY32结构逐个获取并输出快照中进程的名称、ID与优先级。程序流程如下图所示:是否是最后一个进程获取快照句柄开始获取首个进程的PROCESSENTRY输出进程名称、ID与优先级Y结束获取下一进程的PROCESSENTRYN三、 API函数使用说明CreateToolhelp32Snapshot():获得系统中正在运行的进程的快照OpenPr
2、ocess():提取已经存在进程的句柄GetPriorityClass():获取进程的优先权CloseHandle():消除句柄四、 程序设计及程序代码分析/实验一# include # include # include # include using namespace std; / 当在用户模式机内核模式下都提供所耗时间时,在内核模式下进行所耗时间的64位计算的帮助方法DWORD GetKernelModePercentage(const FILETIME & ftKernel, const FILETIME & ftUser)/将FILETIME结构转化为64位整数ULONGLONG
3、qwKernel=(ULONGLONG) ftKernel.dwHighDateTime) 32)+ftKernel.dwLowDateTime;ULONGLONG qwUser=(ULONGLONG) ftUser.dwHighDateTime)32)+ftUser.dwLowDateTime;/ 将消耗时间相加,然后计算消耗在内核模式下的时间百分比ULONGLONG qwTotal = qwKernel + qwUser;DWORD dwPct=(DWORD) (ULONGLONG) 100*qwKernel)/qwTotal);return(dwPct) ;/ 以下是将当前运行进程名和消
4、耗在内核模式下的时间百分数都显示出来的应用程序void main()/ 对当前系统中运行的进程拍取快照HANDLE hSnapshot=:CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,/ 提取当前进程0);/ 如果是当前进程,就将其忽略/初始化进程入口PROCESSENTRY32 pe;: ZeroMemory(&pe,sizeof(pe);pe.dwSize=sizeof(pe);/ 按所有进程循环BOOL bMore=:Process32First(hSnapshot, &pe);while(bMore)/打开用于读取的进程HANDLE hProc
5、ess = : OpenProcess( PROCESS_QUERY_INFORMATION,/ 指明要得到的信息 FALSE,/ 不必继承这一句柄 pe.th32ProcessID) ;/ 要打开的进程if (hProcess!=NULL)DWORD dwPriority=:GetPriorityClass(hProcess); / 消除句柄 : CloseHandle(hProcess);std:cout n进程名称:leftsetw(20)pe.szExeFile进程ID:leftsetw(10)pe.th32ProcessID进程优先权:leftsetw(10);/打印进程名称、ID及
6、优先权switch(dwPriority)case HIGH_PRIORITY_CLASS:std : cout High;break;case NORMAL_PRIORITY_CLASS:std : cout Normal;break;case IDLE_PRIORITY_CLASS:std : cout Idle;break;case REALTIME_PRIORITY_CLASS:std : cout Realtime;break;default:std : cout ;break;std:coutstd:endl;/ 转向下一个进程 bMore=:Process32Next(hSnap
7、shot, &pe);五、 实验结果及结果分析实验结果如下图所示:结果分析:实验结果符合实际情况,实验成功。附录实验环境:windows7旗舰版Visual C+ 6.0环境实验二一、 实验目的进程压力测试二、 设计思路和程序流程设计思路:1、用循环的办法产生所要求的进程(线程),循环的退出条件是不能产生进程时,即CreateProcess()返回0时,统计产生的进程(线程)数目;2、子进程的运行方式分别考虑:子进程挂起或睡眠,挂起操作在父进程通过CREATE_SUSPENDED选项完成;子进程死循环,即父进程产生子进程后子进程立即执行,并且执行一个死循环;3、在进程被赋予不同的优先级情况下的
8、结果。三、 API函数使用说明GetModuleFileName():提取用于当前可执行文件的文件名CloseHandle():消除句柄GetCurrentProcessId():获取当前进程一个唯一的标识符四、 程序设计及程序代码分析/ proccreate项目# include # include # include / 创建传递过来的进程的克隆过程并赋于其ID值void StartClone(int nCloneID)/ 提取用于当前可执行文件的文件名TCHAR szFilenameMAX_PATH ;: GetModuleFileName(NULL, szFilename, MAX_P
9、ATH) ;/ 格式化用于子进程的命令行并通知其EXE文件名和克隆IDTCHAR szCmdLineMAX_PATH ;: sprintf(szCmdLine, %s %d, szFilename, nCloneID) ;/ 用于子进程的STARTUPINFO结构STARTUPINFO si;: ZeroMemory(reinterpret_cast (&si) , sizeof(si) ) ;si.cb = sizeof(si) ;/ 必须是本结构的大小/ 返回的用于子进程的进程信息PROCESS_INFORMATION pi;/ 利用同样的可执行文件和命令行创建进程,并赋于其子进程的性质B
10、OOL bCreateOK = : CreateProcess(szFilename,/ 产生这个EXE的应用程序的名称szCmdLine,/ 告诉其行为像一个子进程的标志NULL,/ 缺省的进程安全性NULL,/ 缺省的线程安全性FALSE,/ 不继承句柄CREATE_NEW_CONSOLE,/ 使用新的控制台NULL,/ 新的环境NULL,/ 当前目录&si,/ 启动信息&pi) ;/ 返回的进程信息/ 对子进程释放引用if (bCreateOK): CloseHandle(pi.hProcess) ;: CloseHandle(pi.hThread) ;int main(int argc
11、, char* argv )/ 确定进程在列表中的位置int nClone(0) ;if (argc 1)/ 从第二个参数中提取克隆ID: sscanf(argv1 , %d , &nClone) ;/ 显示进程位置std : cout Process ID: : GetCurrentProcessId() , Clone ID: nClone std : endl;/ 检查是否有创建子进程的需要const int c_nCloneMax=50;if (nClone c_nCloneMax)/ 发送新进程的命令行和克隆号StartClone(+nClone); / 在终止之前暂停一下 (l/2
12、秒): Sleep(500) ;return 0;五、 实验结果及结果分析实验结果:死循环进行中死循环进行前后CPU使用情况结果分析:由实验结果知,压力测试前后CPU使用情况变化很大,压力测试过程中CPU的使用甚至达到峰值,说明大量进程的创建对CPU的消耗很高。附录实验环境:windows7旗舰版Visual C+ 6.0环境实验三一、 实验目的使用互斥对象实现线程同步二、 设计思路和程序流程设计思路:两个线程对同一个变量进行访问,其中一个线程对变量做加1操作,一个线程对其做减1操作。改变其数值后将该数值写入输出流中。通过CreateMutex创建互斥对象,然后利用同一互斥对象,在某一时刻只能
13、被一个线程所访问来实现线程之间的同步性。三、 API函数使用说明ReleaseMutex():释放由线程拥有的一个互斥体GetCurrentThreadId():获取当前线程一个唯一的线程标识符WaitForSingleObject():使线程进入等待状态CreateMutex():创建互斥对象四、 程序设计及程序代码分析/ mutex项目# include # include # include using namespace std;/ 利用互斥体来保护同时访问的共享资源class CCountUpDownpublic:/ 创建者创建两个线程来访问共享值CCountUpDown(int n
14、Accesses)/*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,/ 缺省的安全
15、性 0,/ 缺省堆栈 IncThreadProc,/ 类线程进程 reinterpret_cast (this) ,/ 线程参数 0,/ 无特殊的标志 NULL) ;/ 忽略返回的id m_hThreadDec = : CreateThread( NULL,/ 缺省的安全性 0,/ 缺省堆栈 DecThreadProc,/ 类线程进程 reinterpret_cast (this) ,/ 线程参数 0,/ 无特殊的标志 NULL) ;/ 忽略返回的id / 允许另一线程获得互斥体 : ReleaseMutex(m_hMutexValue) ;/ 解除程序释放对对象的引用virtual CCou
16、ntUpDown() : 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_hThrea
17、dInc, 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: leftsetw(10) : GetCurrentThreadId() val
18、ue: leftsetw(5)m_nValue access: leftsetw(10)m_nAccess std : endl;/ 发出访问信号并允许线程切换-m_nAccess;: Sleep(1000) ;/ 使显示速度放慢/ 释放对数值的访问: ReleaseMutex(m_hMutexValue) ; static DWORD WINAPI IncThreadProc(LPVOID lpParam) / 将参数解释为 this 指针 CCountUpDown* pThis = reinterpret_cast (lpParam) ;/ 调用对象的增加方法并返回一个值 pThis -
19、DoCount(+1) ; return(0) ;static DWORD WINAPI DecThreadProc(LPVOID lpParam) / 将参数解释为 this 指针 CCountUpDown* pThis =reinterpret_cast (lpParam) ; / 调用对象的减少方法并返回一个值 pThis - DoCount(-1) ; return(0) ;protected:HANDLE m_hThreadInc;HANDLE m_hThreadDec;HANDLE m_hMutexValue;int m_nValue;int m_nAccess ; ;void main()CCountUpDown ud(20) ;ud.WaitForCompletion() ;五、 实验结果及结果分析实验结果:实验结果分析:由实验结果知,线程5428和线程5432交替执行,每次运行之后,数值返回初始值“0”,每次运行之后写入线程在等待队列中变成最后一个,内核保证它在其他线程工作时不会再运行。附录实验环境:windows7旗舰版Visual C+ 6.0环境13