实验1 Windows进程管理编程.docx
《实验1 Windows进程管理编程.docx》由会员分享,可在线阅读,更多相关《实验1 Windows进程管理编程.docx(18页珍藏版)》请在冰点文库上搜索。
![实验1 Windows进程管理编程.docx](https://file1.bingdoc.com/fileroot1/2023-7/3/962e2ab6-1595-475f-bfb7-8d03d7d5f5e7/962e2ab6-1595-475f-bfb7-8d03d7d5f5e71.gif)
实验1Windows进程管理编程
实验一Windows进程管理和进程编程
实验内容1.1Windows任务管理器的进程管理
1、背景知识简介
§Windows的任务管理器提供了用户计算机上正在运行的程序和进程的相关信息,也显示了最常用的度量进程性能的单位
§使用任务管理器
•可以打开监视计算机性能的关键指示器,快速查看正在运行的程序的状态,或者终止已停止响应的程序
•也可以使用多个参数评估正在运行的进程的活动,以及查看CPU和内存使用情况的图形和数据
§任务管理器中
•“应用程序”选项卡:
显示正在运行程序的状态,用户能够结束、切换或者启动程序
•“进程”选项卡:
显示正在运行的进程信息。
例如,可以显示关于CPU和内存使用情况、页面错误、句柄计数以及许多其他参数的信息
•“性能”选项卡:
显示计算机动态性能,包括CPU和内存使用情况的图表,正在运行的句柄、线程和进程的总数,物理、核心和认可的内存总数(KB)等
2、实验目的和要求
§通过在Windows任务管理器中对程序进程进行响应的管理操作
§熟悉操作系统进程管理的概念
§学习观察操作系统运行的动态性能
3、实验环境
§需要准备一台运行WindowsXPProfessional操作系统的计算机
4、实验内容与步骤
1.§启动任务管理器。
按Alt+Ctrl+Delete,或右键单击任务栏,选择任务管理器。
在WindowsXP的任务管理器中,“进程”选项卡增加了一个“用户名”栏目,其中区分了SYSTEM、NETWORKSERVICE、LOCALSERVICE和用户的不同进程类别。
2.使用任务管理器终止进程。
选择进程名,点击右下角的“结束进程”。
终止进程时要小心,有可能导致不希望发生的结果,包括数据丢失和系统不稳定等。
点击进程,右键选择“终止进程树”,会结束该进程以及它直接或间接创建的所有子进程。
3.显示其他进程记数器:
任务管理器菜单栏点击查看->选择列。
4.更改正在运行的程序的优先级。
点击进程,右键选择“设置优先级”。
实验内容1.2Windows进程编程
1、背景知识简介
.NetFramework提供Process类监视整个网络的系统进程以及启动和停止本地系统进程。
除了检索运行进程列表(通过指定计算机、进程名称或进程ID)或查看有关当前可访问处理器的进程的信息之外,还可以获取有关进程线程和模块的详细信息,其方法是通过Process类本身,以及分别通过与ProcessThread和ProcessModule类进行交互来获取。
本实验用VisualStudio开发工具在Windows操作平台下实现创建、终止进程及有关进程信息管理,掌握进一步熟悉进程的概念。
2、实验目的和要求
•通过创建进程、观察正在运行的进程和终止进程的程序设计和调试操作,进一步熟悉操作系统的进程概念,理解Windows进程的“一生”。
3、实验环境
§需要做以下准备
•一台运行WindowsXPProfessional操作系统的计算机
•计算机中需安装VisualStudio开发环境(版本不限)
4、实验内容与步骤
1、启动VisualStudio,新建一个空的控制台项目,工程名为xxProcHandle,其中“xx”为你的姓名拼音首字母+学号末两位,如张三学号末两位为21,则其工程名为ZS21ProcHandle。
2、在Program.cs中输入以下代码(边输入边理解代码):
3、增加代码,实现更改并显示当前运行进程的优先级。
可以在任务管理器内查看进程优先级是否已被修改。
4、查阅MSDN或网络,学习Process类成员,使用Process类成员属性、方法获得、修改进程信息。
例如进程关联的线程信息在Thread属性中。
进程相关的内存使用信息在PrivateMemorySize64等属性中。
5、(选作)新建一个Windows窗口程序,编写一个类任务管理器(可作为课程设计)。
要求:
1.显示进程列表中各进程的信息:
进程ID、进程名、进程优先级、内存使用情况等等。
提供更改进程优先级功能。
2.提供新创建进程、终止进程功能。
3.具体界面及功能自行设计。
4.实现提示:
可采用Process类的静态方法GetProcesses获得进程列表。
5、进阶:
调用WindowsAPI
Windows这个多作业系统除了提供协调应用程式的执行、分配内存、管理系统资源等功能之外,同时也是一个很大的服务中心,调用这个服务中心的各种服务(每一种服务就是一个函数),可以帮应用程式达到开启视窗、描绘图形、使用周边设备等目的。
由于这些函数服务的对象是应用程式(Application),所以便称之为ApplicationProgrammingInterface,简称API函数。
当WINDOWS操作系统开始占据主导地位的时候,开发WINDOWS平台下的应用程序成为人们的需要。
而在WINDOWS程序设计领域处于发展的初期,WINDOWS程序员所能使用的编程工具唯有API函数,这些函数是WINDOWS提供给应用程序与操作系统的接口,他们犹如“积木块”一样,可以搭建出各种界面丰富,功能灵活的应用程序。
所以可以认为API函数是构筑整个WINDOWS框架的基石,在它的下面是WINDOWS的操作系统核心,而它的上面则是所有的华丽的WINDOWS应用程序。
程序员必须熟记一大堆常用的API函数,而且还得对WINDOWS操作系统有深入的了解。
然而随着软件技术的不断发展,在WINDOWS平台上出现了很多优秀的可视化编程环境,程序员可以采用“即见即所得”的编程方式来开发具有精美用户界面和功能强大的应用程序。
这些工具中提供了大量的类库和各种控件,它们替代了API的神秘功能,事实上这些类库和控件都是构架在WIN32API函数基础之上的,是封装了的API函数的集合。
它们把常用的API函数的组合在一起成为一个控件或类库,并赋予其方便的使用方法,所以极大的加速了WINDOWS应用程序开发的过程。
有了这些控件和类库,程序员便可以把主要精力放在程序整体功能的设计上,而不必过于关注技术细节。
实际上如果我们要开发出更灵活、更实用、更具效率的应用程序,必然要涉及到直接使用API函数,虽然类库和控件使应用程序的开发简单的多,但它们只提供WINDOWS的一般功能,对于比较复杂和特殊的功能来说,使用类库和控件是非常难以实现的,这时就需要采用API函数来实现。
例:
调用WindowsAPIGetProcessVersion获得进程运行所需操作系统的最低版本信息。
附:
C++代码
//version项目
#include
#include
#include
usingnamespacestd;
//利用进程和操作系统的版本信息的简单示例
voidmain()
{
//提取这个进程的ID
DWORDdwIdThis=GetCurrentProcessId();
//获得进程运行所需系统的版本,也可以传递参数0以便指明是当前进程
DWORDdwVerReq=GetProcessVersion(dwIdThis);
WORDwMajorReq=(WORD)(dwVerReq>>16);
WORDwMinorReq=(WORD)(dwVerReq&0xffff);
cout<<"ProcessID:
"<<<",requiresOS:
"<<//设置版本信息的数据结构,以便保存操作系统的版本信息
OSVERSIONINFOEXosvix;
ZeroMemory(&osvix,sizeof(osvix));
osvix.dwOSVersionInfoSize=sizeof(osvix);
//获取版本信息并输出报告
GetVersionEx((LPOSVERSIONINFO)&osvix);
cout<<"RunningonOS:
"<<getchar();
}
实验二Linux进程管理和进程编程
实验内容2.1Linux常用命令
(注意:
Linux命令区分大小写。
本例子采用zsc用户登陆)
1.ls命令:
按字母顺序列出当前目录中所有非隐藏文件。
例如:
ls命令显示当前文件夹下有一个名为os的文件夹,和一个名为test.txt的文件。
常用参数:
ls–a:
按字母顺序列出当前目录中所有文件,包括隐藏文件。
例如:
ls–l:
查看当前目录所有文件包括当前目录和父目录,包括长度、拥有者和权限。
例如:
2.cd命令:
改变当前路径。
命令格式:
cd[路径名]
例如:
解释:
ls–la命令显示当前目录下有一个os目录。
cdos进入os目录
cd..回到上一层目录。
3.pwd命令:
显示当前目录的绝对路径。
4.mkdir命令:
建立目录。
命令格式:
mkdir[目录名]
新创建一个目录abc
5.cat命令:
创建或显示文件
创建文件:
cat>[文件名],例如:
解释:
执行cat>a.txt,创建文件a.txt,然后输入文件内容”HelloWorld”,按ctrl+d结束输入
显示文件:
cat[文件名],例如显示上述创建的文件:
6.rm命令:
删除文件
rm[文件名]:
删除文件而不提示确认。
rm–rf[目录名]:
删除目录及其子目录。
7.cp命令:
复制文件。
命令格式:
cp[文件1][文件2]。
将文件1拷贝给文件2
8.mv命令:
移动文件或目录。
解释:
mva.txt./os/a.txt,将a.txt文件移动到(当前目录下的)os目录下,仍取名a.txt
9.more命令:
分页显示内容。
解释:
ps–ax显示系统进程信息。
|表示管道。
more将ps–ax的输出分页显示。
实验内容2.2使用编辑器vim编辑文件
在命令行下输入vimtest.c,编辑文件test.c(c文件)。
1.进入编辑模式:
当进入刚打开的文件时,不能写入信息,这时按一下键盘上的i键(i表示insert),就可以进入编辑模式了。
在编辑模式下。
窗口左下方出现-INSERT-字样。
2.存盘退出:
编辑完文件后,需要存盘退出,需要执行以下两个步骤:
(1)按一下Esc键(按Esc后窗口左下方的-INSERT-字样消失);
(2)键入冒号,紧跟冒号后面是wq,即键入:
wq。
wq表示存盘退出。
若不想存盘,则键入:
q!
实验内容2.3使用gcc编译c文件
gcc是c语言编译器。
编译命令格式是:
gcc[c文件名]–o[输出文件名]。
-o表示输出,后面跟着输出文件名,表示生成的可执行文件名。
例如:
键入./test执行
实验内容2.4进程管理
[背景知识]
1.进程
Linux中,进程既是一个独立拥有资源的基本单位,又是一个独立调度的基本单位。
一个进程实体由若干个区(段)组成,包括程序区、数据区、栈区、共享存储区等。
每个区又分为若干页,每个进程配置有唯一的进程控制块PCB,用于控制和管理进程。
2.进程映像
Linux系统中,进程是进程映像的执行过程,也就是正在执行的进程实体。
它由三部分组成:
(1)用户级上、下文。
主要成分是用户程序;
(2)寄存器上、下文。
由CPU中的一些寄存器的内容组成,如PC,PSW,SP及通用寄存器等;
(3)系统级上、下文。
包括OS为管理进程所用的信息,有静态和动态之分。
实验一、使用ps命令查看系统进程
ps命令可以显示系统正在运行的进程、其他用户正在运行的进程或者目前在系统上运行的所有进程。
下面是ps命令的输出样本部分截图。
这个命令显示了许多进程的相关信息。
例如,TTY一列显示了进程是从哪一个终端启动的,TIME一列是进程目前为止所占用的CPU时间,CMD一列显示启动进程所使用的命令。
我们在这里看到了一个非常重要的进程init(上图红框所示)。
一般而言,每个进程都是由另一个我们称之为父进程的进程启动的,被父进程启动的进程叫做子进程。
Linux系统启动时,它将运行一个名为init的进程,该进程是系统运行的第一个进程,它的进程号为1。
你可以把init进程看作为操作系统的进程管理器,它是其它所有进程的祖先进程。
其它系统进程要么是由init启动的,要么是由被init进程启动的其它进程启动的。
实验二、使用exec系列函数替换进程映像
1.exec系列函数介绍
exec系列函数可以把当前进程替换为一个新进程,新进程由path或file参数指定。
你可以在使用exec函数将程序的执行从一个程序切换到另外一个程序。
新的程序启动后,原来的程序就不再运行了。
#include
intexecl(constchar*path,constchar*arg0,…,(char*)0);
intexeclp(constchar*file,constchar*arg0,…,(char*)0);
……
2.参考代码
在vim下编辑execlp.c
#include
#include
#include
intmain()
{
printf("Runningpswithecelp\n");
execlp("ps","ps","ax",0);
printf("Done.\n");
exit(0);
}
采用gccexeclp.c–oexeclp编译文件,执行。
……
运行这个程序是,你会看到正常的ps输出,但字符串Done却根本没有出现。
程序首先打印出它的第一条信息,接着调用execlp,这个函数搜索程序ps,然后用ps程序替换当前程序,就好像直接使用shell命令“psax”一样。
ps命令结束时,我们看到一个新的shell提示符,因为我们并没有再返回到原程序中,所以信息Done.不会输出。
事实上,这里放生的一切就是,运行中的程序开始执行exec调用中指定的新的可执行文件中的代码。
实验三、使用系统调用fork()创建一个子进程。
1.fork( ) 的作用
fork()系统调用用来创建一个新进程。
这个系统调用复制当前进程,在进程表中创建一个新的表项,新表项中的许多属性与当前进程是相同的。
新进程几乎与原进程一模一样,执行的代码也完全相同,但新进程有自己的数据空间、环境和文件描述符。
参数定义:
pid_t fork( );//pid_t为进程标识符类型
系统调用格式:
pid_tpid=fork();
fork( )返回值意义如下:
=0:
在子进程中,pid变量保存的fork( )返回值为0,表示当前进程是子进程。
>0:
在父进程中,pid变量保存的fork( )返回值为子进程的id值(进程唯一标识符)。
-1:
创建失败。
如果fork()调用成功,它向父进程返回子进程的PID,并向子进程返回0,即fork()被调用了一次,但返回了两次。
此时OS在内存中建立一个新进程,所建的新进程是调用fork()父进程(parentprocess)的副本,称为子进程(childprocess)。
子进程继承了父进程的许多特性,并具有与父进程完全相同的用户级上下文。
父进程与子进程并发执行。
上述过程如上图所示:
父子进程可以通过fork()调用的返回值判断谁是父进程,谁是子进程。
一个典型的使用fork的代码片段如下所示:
pid_tnew_pid=fork();
switch(new_pid)
{
case-1:
/*error*/
break;
case0:
/*子进程*/
break;
default:
/*父进程*/
break;
}
虽然父进程与子进程程序完全相同,但每个进程都有自己的程序计数器PC(注意子进程的PC开始位置),然后根据fork( )返回值的不同,执行了不同的分支语句。
2.参考代码
以下程序运行时,在系统中有一个父进程和一个子进程活动。
父进程输出消息三次,子进程输出消息五次。
试观察记录屏幕上的显示结果,并分析原因。
#include
#include
#include
#include
intmain()
{
pid_tpid;
char*message;
intn;
printf("forkprogramstarting\n");
pid=fork();
switch(pid)
{
case-1:
perror("forkfailed");//创建进程失败
exit(EXIT_FAILURE);
case0:
message="Thisisthechild";//返回0,该进程是子进程
n=5;
break;
default:
message="Thisistheparent";//返回非0的值,该进程是父进程
n=3;
break;
}
for(;n>0;n--)
{
puts(message);//输出message
sleep
(1);
}
exit(EXIT_SUCCESS);
}
解释:
程序在调用fork时被分成两个独立进程。
程序通过fork调用的返回值确定父、子进程。
父子并发执行。
子进程被创建并且输出五次消息,每次输出之间相隔一秒。
父进程(即原进程)输出完它的所有消息就结束了,因此我们将看到输出结果中有一个shell提示符”zsc@ubuntu:
~$”。