当前位置:文档之家› 实验3 任务的基本管理

实验3 任务的基本管理

实验3 任务的基本管理
实验3 任务的基本管理

实验3 任务的基本管理

1 实验目的

?理解任务管理的基本原理,了解任务的各个基本状态及其变迁过程;

?掌握μC/OS-II中任务管理的基本方法(创建、启动、挂起、解挂任务);

?熟练使用μC/OS-II任务管理的基本系统调用。

2 实验原理及程序结构

2.1 实验设计

为了展现任务的各种基本状态及其变迁过程,本实验设计了Task0、Task1两个任务:任务Task0不断地挂起自己,再被任务Task1解挂,两个任务不断地切换执行。通过本实验可以清晰地了解到任务在各个时刻的状态以及状态变迁的原因。

t0 t1 t2 t3 t4 t5 t6 t7 t8

图1

注意:图中的栅格并不代表严格的时间刻度,而仅仅表现各任务启动和执行的相对先后关系。

2.1.1 运行流程

整个应用的运行流程如图1所示,其描述如下:

(1)main()函数调用OSInit()函数对μC/OS-II内核进行初始化,调用OSTaskCreate

创建起始任务TaskStart;

(2)main()函数调用函数OSStart()启动μC/OS-II内核的运行,开始多任务的调度,执行当前优先级最高的就绪任务TaskStart;

(3)TaskStart完成如下工作:

a、安装时钟中断并初始化时钟,串口0初始化,创建2个应用任务;

b、挂起自己(不再被其它任务唤醒),系统切换到当前优先级最高的就绪任务Task0。

之后整个系统的运行流程如下:

●t1时刻,Task0开始执行,它运行到t2时刻挂起自己;

●t2时刻,系统调度处于就绪状态的优先级最高任务Task1执行,它在t3时刻唤醒

Task0,后者由于优先级较高而抢占CPU;

●Task0执行到t4时刻又挂起自己,内核调度Task1执行;

●Task1运行至t5时刻再度唤醒Task0;

●……

2.1.2 μC/O S-Ⅱ中的任务描述

一个任务通常是一个无限的循环,由于任务的执行是由操作系统内核调度的,因此任务是绝不会返回的,其返回参数必须定义成void。在μC/OS-Ⅱ中,当一个运行着的任务使一个比它优先级高的任务进入了就绪态,当前任务的CPU使用权就会被抢占,高优先级任务会立刻得到CPU的控制权(在系统允许调度和任务切换的前提下)。μC/OS-Ⅱ可以管理多达64个任务,但目前版本的μC/OS-Ⅱ有两个任务已经被系统占用了(即空闲任务和统计任务)。必须给每个任务赋以不同的优先级,任务的优先级号就是任务编号(ID),优先级可以从0到OS_LOWEST_PR10-2。优先级号越低,任务的优先级越高。μC/OS-Ⅱ总是运行进入就绪态的优先级最高的任务。

2.2 操作系统配置

操作系统配置的目的在于根据应用的需要,对操作系统的功能和规模进行设置,以便优化对系统存储空间的使用。配置的方法为修改uC_OS-II源代码目录中的OS_CFG.h文件,配置文件配置如下:

#define OS_MAX_EVENTS 10 /*最多可以有10个事件*/

#define OS_MAX_FLAGS 5 /*最多可以有5个事件标志*/

#define OS_MAX_MEM_PART 5 /*最多可以划分5个内存块*/

#define OS_MAX_QS 2 /*最多可以使用2个队列*/

#define OS_MAX_TASKS 3 /*最多可以创建3个任务*/

#define OS_LOWEST_PRIO 14 /*任务优先级不可以大于14*/

#define OS_TASK_IDLE_STK_SIZE 1024 /*空闲任务堆栈大小*/

#define OS_TASK_STA T_EN 1 /*是否允许使用统计任务*/

#define OS_TASK_STA T_STK_SIZE 1024 /*统计任务堆栈大小*/

#define OS_FLAG_EN 0 /*是否允许使用事件标志功能*/

#define OS_FLAG_W AIT_CLR_EN 1 /*是否允许等待清除事件标志*/

#define OS_FLAG_ACCEPT_EN 1 /*是否允许使用OSFlagAccept()*/

#define OS_FLAG_DEL_EN 1 /*是否允许使用OSFlagDel()*/

#define OS_FLAG_QUERY_EN 1 /*是否允许使用OSFlagQuery()*/

#define OS_MBOX_EN 0 /*是否允许使用邮箱功能*/

#define OS_MBOX_ACCEPT_EN 1 /*是否允许使用OSMboxAccept() */ #define OS_MBOX_DEL_EN 1 /*是否允许使用OSMboxDel()*/

#define OS_MBOX_POST_EN 1 /*是否允许使用OSMboxPost()*/

#define OS_MBOX_POST_OPT_EN 1 /*是否允许使用OSMboxPostOpt() */ #define OS_MBOX_QUERY_EN 1 /*是否允许使用OSMboxQuery()*/

#define OS_MEM_EN 0 /*是否允许使用内存管理的功能*/ #define OS_MEM_QUERY_EN 1 /*是否允许使用OSMemQuery()*/

#define OS_MUTEX_EN 0 /*是否允许使用互斥信号量的功能*/ #define OS_MUTEX_ACCEPT_EN 1 /*是否允许使用OSMutexAccept()*/ #define OS_MUTEX_DEL_EN 1 /*是否允许使用OSMutexDel()*/

#define OS_MUTEX_QUERY_EN 1 /*是否允许使用OSMutexQuery()*/

#define OS_Q_EN 0 /*是否允许使用队列功能*/

#define OS_Q_ACCEPT_EN 1 /*是否允许使用OSQAccept()*/

#define OS_Q_DEL_EN 1 /*是否允许使用OSQDel()*/

#define OS_Q_FLUSH_EN 1 /*是否允许使用OSQFlush()*/

#define OS_Q_POST_EN 1 /*是否允许使用OSQPost()*/

#define OS_Q_POST_FRONT_EN 1 /*是否允许使用OSQPostFront()*/ #define OS_Q_POST_OPT_EN 1 /*是否允许使用OSQPostOpt()*/

#define OS_Q_QUERY_EN 1 /*是否允许使用OSQQuery()*/

#define OS_SEM_EN 0 /*是否允许使用信号量功能*/

#define OS_SEM_ACCEPT_EN 1 /*是否允许使用OSSemAccept()*/

#define OS_SEM_DEL_EN 1 /*是否允许使用OSSemDel() */

#define OS_SEM_QUERY_EN 1 /*是否允许使用OSSemQuery()*/

#define OS_TASK_CHANGE_PRIO_EN 0 /*是否允许使用OSTaskChangePrio()*/ #define OS_TASK_CREATE_EN 1 /*是否允许使用OSTaskCreate()*/

#define OS_TASK_CREATE_EXT_EN 1 /*是否允许使用OSTaskCreateExt()*/ #define OS_TASK_DEL_EN 1 /*是否允许使用OSTaskDel()*/

#define OS_TASK_SUSPEND_EN 1/*是否允许使用OSTaskSuspend() and OSTaskResume()*/ #define OS_TASK_QUERY_EN 1 /*是否允许使用OSTaskQuery()*/

#define OS_TIME_DL Y_HMSM_EN 0 /*是否允许使用OSTimeDlyHMSM()*/ #define OS_TIME_DL Y_RESUME_EN 1 /*是否允许使用OSTimeDlyResume()*/ #define OS_TIME_GET_SET_EN 1 /*是否允许使用OSTimeGet() 和OSTimeSet()*/ #define OS_SCHED_LOCK_EN 1 /*是否允许使用OSSchedLock()和OSSchedUnlock()*/ #define OS_TICKS_PER_SEC 200 /*设置每秒之内的时钟节拍数目*/

2.3 源程序说明

系统启动后,经过ARM2200启动代码后,进入main()函数,这是我们编写实现应用程序的起点。

首先调用OSInit()对uC/OS-II进行了初始化,接着创建了起始任务TaskStart:

OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0);

TaskStart任务

TaskStart任务负责安装操作系统的时钟中断服务例程、初始化操作系统时钟,初始化串口0,并创建所有的应用任务:

void TaskStart(void *pdata)

{

char str[] = "uC/OS-II is Started\n==============================\n";

TargetInit(); /* 目标板初始化*/

OSTaskCreate(Task0, (void *)0, &Task0Stk[TASK_STK_SIZE - 1], 5); /*创建任务Task0*/

OSTaskCreate(Task1, (void *)0, &Task1Stk[TASK_STK_SIZE - 1], 6);/*创建任务Task1*/

UART0_SendStr((uint8 const *)str); /* 向串口0发送字符串*/

for(;;)

{

OSTaskSuspend(0); /* 挂起优先级为0的任务,即为TaskStart任务本身*/ }

}

TaskStart任务完成上述操作后将自己挂起,操作系统将调度当前优先级最高的应用任务Task0运行。

应用任务

应用任务Task0运行后将自己挂起,之后操作系统就会调度处于就绪状态的优先级最高的任务,具体代码如下:

void Task0(void *pdata)

{

char str[] = " Task0 is running\n Task1 is Suspended\n==============================\n";

pdata = pdata; /* 避免编译警告*/

for(;;)

{

UART0_SendStr((uint8 const *)str); /* 向串口0发送字符串*/

DelayTime(3000); /* 延时*/

OSTaskSuspend(5); /* 挂起优先级为5的任务,即Task0本身*/ }

}

应用任务Task1运行后将Task0唤醒,使其进入到就绪队列中:

void Task1(void *pdata)

{

char str[] = " Task0 is Suspended\n Task1 is running\n==============================\n";

pdata = pdata; /* 避免编译警告*/

for (;;)

{

UART0_SendStr((uint8 const *)str); /* 向串口0发送字符串*/

OSTimeDly(1000); /* 延时*/

OSTaskResume(5); /* 为优先级为5的任务即Task0解挂*/ }

}

3 试验步骤

3.1 硬件连接

将ARM开发板的JTAG口通过EasyJTAG-H或EasyJTAG连接到PC机上,ARM板的串口0连接到PC机的串口1,插上ARM开发板电源。

3.2 利用周立功ARM2200工程模板建立工程

1)打开ADS 1.2集成开发软件

点击开始->所有程序->ARM Developer Suite v1.2 -> CodeWarrior for ARM

Developer Suite,如下图所示:

图2 打开ADS 1.2集成开发软件

图3 ADS 1.2集成开发软件界面

2)用周立功LPC2200工程模板建立工程

在D盘下建立文件夹Experiment3,点击file -> New,将弹出如下图的对话框。

图4 工程建立界面(a)

选择工程模板类型为“ARM Executable Image for uCOSII (for lpc22xx )”,为工程命名如Experiment3,选择工程存储路径如“D:/Experiment3”,设置完成后点击确定,工程建立完成。下图为工程建立完成后的界面。

图5 工程建立界面(b)

3) 为工程添加用户程序文件

将文件夹UART0、ARM 、SOURCE 及文件main.C 拷贝到Experiment3目录下。在ADS

1.2工程界面中点击右键,点击“Add Files …”,将文件“D:\Experiment3\main.c ”和“D:\Experiment3\UART0\ SendStr.c ”添加到工程中。

图6 添加用户程序到工程(c)

已经添加的C 文件

打开文件config.h,删除掉“#include “..\..\Arm_Pc\pc.h””语句,如下图所示:

图7

4)编译程序代码

添加用户程序完成后,选择程序调试运行模式,选择在外部RAM中进行调试,即选择DebugInExram,如图21所示:

程序在外部RAM中调试

程序在内部Flash中调试

程序在内部Flash中调试,并加密

程序在外部Flash中调试

选择程序调试运行环境

图8 设置程序运行环境

点击进入工程调试环境

点击编译工程

点击进入工程设置界面

图9 编译程序界面(a)

点击按钮开始编译程序,编译后界面如下,如果出现错误,要修改出错程序代码。

图10 编译程序界面(b)

最后点击下载调试,操作步骤与实验1、实验2相同。

在程序执行时,在PC机上打开串口调试助手,串口调试助手设置如下:

图11 串口调试助手界面

4 运行及观察应用输出信息

程序执行时,串口调试助手接收到信息如下:

图12 实验输出结果

阅读程序源代码,并根据串口输出结果,分析任务的调度,任务的挂起及任务解挂过程。

5 本实验中所用到的μC/OS-II相关函数

5.1 OSTaskCreate()

建立一个新任务。任务的建立可以在多任务环境启动之前,也可以在正在运行的任务中建立。中断处理程序中不能建立任务。一个任务可以为无限循环的结构。

函数原型:INT8U OSTaskCreate(void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U

prio);

参数说明:task是指向任务代码首地址的指针。

Pdata指向一个数据结构,该结构用来在建立任务时向任务传递参数。

返回值:

OSTaskCreate()的返回值为下述之一:

●OS_NO_ERR:函数调用成功。

●OS_PRIO_EXIST:具有该优先级的任务已经存在。

●OS_PRIO_INV ALID:参数指定的优先级大于OS_LOWEST_PRIO。

●OS_NO_MORE_TCB:系统中没有OS_TCB可以分配给任务了。

5.2 OSTaskSuspend()

无条件挂起一个任务。调用此函数的任务也可以传递参数OS_PRIO_SELF,挂起调用任务本身。当前任务挂起后,只有其他任务才能唤醒被挂起的任务。任务挂起后,系统会重新进行任务调度,运行下一个优先级最高的就绪任务。唤醒挂起任务需要调用函数OSTaskResume()。

任务的挂起是可以叠加到其他操作上的。例如,任务被挂起时正在进行延时操作,那么任务的唤醒就需要两个条件:延时的结束以及其他任务的唤醒操作。又如,任务被挂起时正在等待信号量,当任务从信号量的等待对列中清除后也不能立即运行,而必须等到被唤醒后。

函数原型:INT8U OSTaskSuspend ( INT8U prio);

参数说明:prio为指定要获取挂起的任务优先级,也可以指定参数OS_PRIO_SELF,挂起任务本身。此时,下一个优先级最高的就绪任务将运行。

返回值:

OSTaskSuspend()的返回值为下述之一:

●OS_NO_ERR:函数调用成功。

●OS_TASK_ SUSPEND_IDLE:试图挂起μC/OS-II中的空闲任务(Idle task)。此为非法

操作。

●OS_PRIO_INV ALID:参数指定的优先级大于OS_LOWEST_PRIO或没有设定

OS_PRIO_SELF的值。

●OS_TASK_ SUSPEND _PRIO:要挂起的任务不存在。

5.3 OSTaskResume()

唤醒一个用OSTaskSuspend()函数挂起的任务。OSTaskResume()也是唯一能“解挂”挂起任务的函数。

函数原型:NT8U OSTaskResume ( INT8U prio);

参数说明:prio指定要唤醒任务的优先级。

返回值:

OSTaskResume ()的返回值为下述之一:

●OS_NO_ERR:函数调用成功。

●OS_TASK_RESUME_PRIO:要唤醒的任务不存在。

●OS_TASK_NOT_SUSPENDED:要唤醒的任务不在挂起状态。

●OS_PRIO_INV ALID:参数指定的优先级大于或等于OS_LOWEST_PRIO。

5.3 OSTimeDly()

将调用该函数的任务延时一段特定的时间,延时的长短是由指定的时钟节拍数目来确定的,调用该函数后经进行一次任务调度,从而去执行一个优先级最高的就绪态任务。任务在调用OSTimeDly( )后,一旦规定的时间期满或者有其他任务通过调用OSTimeDlyResume( )取消了延时,任务会立即进入就绪状态。

函数原型:void OSTimeDly(INT16U ticks)

参数说明:ticks 任务延时的时钟节拍数

返回值:无

实验一 进程管理

实验一进程管理 【实验目的】 1)加深对进程概念及进程管理各部分内容的理解。 2)熟悉进程管理中主要数据结构的设计和进程调度算法、进程控制机构、同步机构、通讯机构的实施。 【实验要求】 调试并运行一个允许n 个进程并发运行的进程管理模拟系统。了解该系统的进程控制、同步及通讯机构,每个进程如何用一个PCB 表示、其内容的设置;各进程间的同步关系;系统在运行过程中显示各进程的状态和有关参数变化情况的意义。 【实验环境】 具备Windows或MS-DOS操作系统、带有Turbo C 集成环境的PC机。 【实验重点及难点】 重点:理解进程的概念,进程管理中主要数据结构的设计和进程调度算法、进程控制机构、同步机构、通讯机构的实施。 难点:实验程序的问题描述、实现算法、数据结构。 【实验内容】 一.阅读实验程序 程序代码见【实验例程】。 二.编译实验例程 用Turbo C 编译实验例程。 三.运行程序并对照实验源程序阅读理解实验输出结果的意义。 【实验例程】 #include #define TRUE 1 #define FALSE 0 #define MAXPRI 100 #define NIL -1 struct { int id; char status; int nextwr; int priority; } pcb [3]; struct { int value; int firstwr; } sem[2]; char savearea[3][4],addr; int i,s1,s2,seed, exe=NIL;

init() { int j; for (j=0;j<3;j++) { pcb[j].id=j; pcb[j].status='r'; pcb[j].nextwr=NIL; printf("\n process%d priority?",j+1); scanf("%d",&i); pcb[j].priority=i; } sem[0].value=1; sem[0].firstwr=NIL; sem[1].value=1; sem[1].firstwr=NIL; for(i=1;i<3;i++) for(j=0;j<4;j++) savearea[i] [j]='0'; } float random() { int m; if (seed<0) m=-seed; else m=seed; seed=(25173*seed+13849)%65536; return(m/32767.0); } timeint(ad) char ad; { float x; x=random(); if((x<0.33)&&(exe==0))return(FALSE); if((x<0.66)&&(exe==1))return(FALSE); if((x<1.0)&&(exe==2))return(FALSE); savearea[exe][0]=i; savearea[exe][1]=ad; pcb[exe].status='t'; printf("times silce interrupt'\n process%d enter into ready.\n",exe+1); exe=NIL; return(TRUE); } scheduler()

实验三-进程管理

实验三进程管理 一、实验目的 1.熟悉和理解进程和进程树的概念,掌握有关进程的管理机制 2.通过进程的创建、撤销和运行加深对进程并发执行的理解 3.明确进程与程序、并行与串行执行的区别 4.掌握用C 程序实现进程控制的方法 二、实验学时 2学时 三、实验背景知识 所涉及的系统调用 1、exec( )系列(exec替换进程映像) 系统调用exec( )系列,也可用于新程序的运行。fork( )只是将父进程的用户级上下文拷贝到新进程中,而exec( )系列可以将一个可执行的二进制文件覆盖在新进程的用户级上下文的存储空间上,以更改新进程的用户级上下文。exec( )系列中的系统调用都完成相同的功能,它们把一个新程序装入内存,来改变调用进程的执行代码,从而形成新进程。如果exec( )调用成功,调用进程将被覆盖,然后从新程序的入口开始执行,这样就产生了一个新进程,新进程的进程标识符id 与调用进程相同。 exec( )没有建立一个与调用进程并发的子进程,而是用新进程取代了原来进程。所以exec( )调用成功后,没有任何数据返回,这与fork( )不同。exec( )系列系统调用在UNIX系统库unistd.h中,共有execl、execlp、execle、execv、execvp五个,其基本功能相同,只是以不同的方式来给出参数。 #include int execl(const cha r *pathname, const char *arg, …); int execlp(const char *, const char *arg, …); int execle(const char *pathname, const char *arg, …, const char *envp[ ]); int execv(const char *pathname, char *const argv[ ]); int execvp(const char *, char *const argv[ ]); 参数: path参数表示你要启动程序的名称包括路径名。 arg参数表示启动程序所带的参数,一般第一个参数为要执行命令名,不是带路径且arg必须以NULL结束。 返回值:成功返回0,失败返回-1 注:上述exec系列函数底层都是通过execve系统调用实现. 1)带l 的exec函数:execl,execlp,execle,表示后边的参数以可变参数的形式给出且都以一个空指针结束。 #include

实验三:存储管理

实验三:存储管理 IMB standardization office【IMB 5AB- IMBK 08- IMB 2C】

一、实验名称 实验三:存储管理 [1]Windows Server 2003内存结构 [2] Windows Server 2003虚拟内存 二、 [1]实验目的 1)通过实验了解windows Server 2003内存的使用,学习如何在应用程序中管理内存、体会Windows应用程序内存的简单性和自我防护能力。 2)了解windows Server 2003的内存结构和虚拟内存的管理,进而了解进程堆和windows为使用内存而提供的一些扩展功能。 三、 [1]实验内容 四、 [1]实验步骤 Windows提供了一个API即GetSystemInfo() ,以便用户能检查系统中虚拟内存的一些特性。程序5-1显示了如何调用该函数以及显示系统中当前内存的参数。 步骤1:登录进入Windows Server 2003 。 步骤2:在“开始”菜单中单击“程序”-“Microsoft Visual Studio 6.0”–“Microsoft Visual C++ 6.0”命令,进入Visual C++窗口。 步骤3:在工具栏单击“打开”按钮,在“打开”对话框中找到并打开实验源程序。 程序5-1:获取有关系统的内存设置的信息 步骤4:单击“Build”菜单中的“Compile ”命令,并单击“是”按钮确认。系统对进行编译。 步骤5:编译完成后,单击“Build”菜单中的“Build ”命令,建立可执行文件。 操作能否正常进行如果不行,则可能的原因是什么 答:操作能正常进行。 _____________________________________________________ 步骤6:在工具栏单击“Execute Program” (执行程序) 按钮,执行程序。 运行结果 (分行书写。如果运行不成功,则可能的原因是什么?) : 1) 虚拟内存每页容量为: 2) 最小应用地址: 0x00010000 3) 最大应用地址为: 0x7ffeffff 4) 当前可供应用程序使用的内存空间为: 5) 当前计算机的实际内存大小为: 阅读和分析程序5-1,请回答问题:

windows进程管理实验报告

实验报告 课程名称:操作系统 实验项目:windows进程管理 姓名: 专业:计算机科学与技术 班级: 学号:

计算机科学与技术学院 计算机系 2019 年 4 月 23 日

实验项目名称: windows进程管理 一、实验目的 1. 学习windows系统提供的线程创建、线程撤销、线程同步等系统调用; 2. 利用C++实现线程创建、线程撤销、线程同步程序; 3. 完成思考、设计与练习。 二、实验用设备仪器及材料 1. Windows 7或10, VS2010及以上版本。 三、实验内容 1 线程创建与撤销 写一个windows控制台程序(需要MFC),创建子线程,显示Hello, This is a Thread. 然后撤销该线程。 相关系统调用: 线程创建: CreateThread() 线程撤销: ExitThread() 线程终止: ExitThread(0) 线程挂起: Sleep() 关闭句柄: CloseHandle() 参考代码: ; } 运行结果如图所示。 完成以下设计题目: 1. 向线程对应的函数传递参数,如字符串“hello world!”,在线程中显示。 2. 如何创建3个线程A, B, C,并建立先后序执行关系A→B→C。

实验内容2 线程同步 完成父线程和子线程的同步。父线程创建子线程后进入阻塞状态,子线程运行完毕后再唤醒。 相关系统调用: 等待对象 WaitForSingleObject(), WaitForMultipleObjects(); 信号量对象 CreateSemaphore(), OpenSemaphore(), ReleaseSemaphore(); HANDLE WINAPI CreateSemaphore( _In_opt_ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes _In_ LONG lInitialCount, _In_ LONG lMaximumCount, _In_opt_ LPCTSTR lpName ); 第一个参数:安全属性,如果为NULL则是默认安全属性 第二个参数:信号量的初始值,要>=0且<=第三个参数 第三个参数:信号量的最大值 第四个参数:信号量的名称 返回值:指向信号量的句柄,如果创建的信号量和已有的信号量重名,那么返回已经存在的信号量句柄参考代码: n"); rc=ReleaseSemaphore(hHandle1,1,NULL); err=GetLastError(); printf("Release Semaphore err=%d\n",err); if(rc==0) printf("Semaphore Release Fail.\n"); else printf("Semaphore Release Success. rc=%d\n",rc); } 编译运行,结果如图所示。

实验一 进程管理

实验一进程管理 1. 实验目的 ⑴加深对进程概念的理解,明确进程和程序的区别; ⑵进一步认识并发执行的实质; ⑶分析进程争用资源的现象,学习解决进程互斥的方法; ⑷了解Linux系统中进程通信的基本原理。 2. 实验准备 ⑴阅读Linux的sched.h源码文件,加深对进程管理的理解。 ⑵阅读Linux的fork.h源码文件,分析进程的创建过程。 3. 实验内容 ⑴进程的创建 编写一段程序,使用系统调用fork ( )创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示字符“a”;子进程显示字符“b”和字符“c”。试观察记录屏幕上的显示结果,并分析原因。 ⑵进程的控制 修改已编写的程序,将每个进程输出一个字符改为每个进程输出一句话,再观察程序执行时屏幕上出现的现象,并分析原因。 如果在程序中使用系统调用lockf ( )来给每一个进程加锁,可以实现进程之间的互斥,观察并分析出现的现象。 ⑶软中断通信 编制一段程序实现进程的软中断通信。要求:使用系统调用fork ( )创建两个子进程,再用系统调用signal( )让父进程捕捉键盘上发来的中断信号(既按Del键);当捕捉到中断信号后,父进程系统调用kill( )向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止:Child process 1 is killed by parent! Child process 2 is killed by parent! 父进程等待两个子进程终止后,输出如下的信息后终止: Parent process is killed! 在上面的程序中增加语句signal (SIGINT, SIG_IGN) 和signal (SIGQUIT, SIG_IGN),观察执行结果,并分析原因。 4. 实验指导

操作系统-进程管理实验报告

实验一进程管理 1.实验目的: (1)加深对进程概念的理解,明确进程和程序的区别; (2)进一步认识并发执行的实质; (3)分析进程争用资源的现象,学习解决进程互斥的方法; (4)了解Linux系统中进程通信的基本原理。 2.实验预备内容 (1)阅读Linux的sched.h源码文件,加深对进程管理概念的理解; (2)阅读Linux的fork()源码文件,分析进程的创建过程。 3.实验内容 (1)进程的创建: 编写一段程序,使用系统调用fork() 创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示字符“a”,子进程分别显示字符“b”和“c”。试观察记录屏幕上的显示结果,并分析原因。 源代码如下: #include #include #include #include #include int main(int argc,char* argv[]) { pid_t pid1,pid2; pid1 = fork(); if(pid1<0){ fprintf(stderr,"childprocess1 failed"); exit(-1); } else if(pid1 == 0){ printf("b\n"); } 1/11

else{ pid2 = fork(); if(pid2<0){ fprintf(stderr,"childprocess1 failed"); exit(-1); } else if(pid2 == 0){ printf("c\n"); } else{ printf("a\n"); sleep(2); exit(0); } } return 0; } 结果如下: 分析原因: pid=fork(); 操作系统创建一个新的进程(子进程),并且在进程表中相应为它建立一个新的表项。新进程和原有进程的可执行程序是同一个程序;上下文和数据,绝大部分就是原进程(父进程)的拷贝,但它们是两个相互独立的进程!因此,这三个进程哪个先执行,哪个后执行,完全取决于操作系统的调度,没有固定的顺序。 (2)进程的控制 修改已经编写的程序,将每个进程输出一个字符改为每个进程输出一句话,再观察程序执行时屏幕上出现的现象,并分析原因。 将父进程的输出改为father process completed 2/11

实验三存储管理实验

实验三存储管理实验 Pleasure Group Office【T985AB-B866SYT-B182C-BS682T-STT18】

实验三存储管理实验 一. 目的要求: 1、通过编写和调试存储管理的模拟程序以加深对存储管理方案的理解。熟悉虚存管理的各种页面淘汰算法。 2、通过编写和调试地址转换过程的模拟程序以加强对地址转换过程的了解。二.实验内容: 1、设计一个固定式分区分配的存储管理方案,并模拟实现分区的分配和回收过程。 可以假定每个作业都是批处理作业,并且不允许动态申请内存。为实现分区的分配和回收,可以设定一个分区说明表,按照表中的有关信息进行分配,并根据分区的分配和回收情况修改该表。 算法描述: 本算法将内存的用户区分成大小相等的四个的分区,设一张分区说明表用来记录分区,其中分区的表项有分区的大小、起始地址和分区的状态,当系统为某个作业分配主存空间时,根据所需要的内存容量,在分区表中找到一个足够大的空闲分区分配给它,然后将此作业装入内存。如果找不到足够大的空闲分区,则这个作业暂时无法分配内存空间,系统将调度另一个作业。当一个作业运行结束时,系统将回收改作业所占据的分区并将该分区改为空闲。 算法原程序 #include "" #include "" #include <>

#include <> #define PCB_NUM 5 行程序."); printf("\n\t\t\t0.退出程序."); scanf("%d",&m); switch(m) { case1: break; case0: system("cls"); menu(); break; default: system("cls"); break; } } void paixu(struct MemInf* ComMem,int n) { int i,j,t; for(j=0; jComMem[i+1].size) { t=ComMem[i].size; ComMem[i].size=ComMem[i+1].size; ComMem[i+1].size=t; } } void paixu2() { int i,j,t; for(j=0; j<4; j++) for(i=0; i<4-j; i++) if(pcbList[i].size>pcbList[i+1].size) { t=pcbList[i].size; pcbList[i].size=pcbList[i+1].size; pcbList[i+1].size=t; } } void main() { DD: menu();

进程管理实验报告

实验2过程管理实验报告学生号姓名班级电气工程系过程、过程控制块等基本原理过程的含义:过程是程序运行过程中对数据集的处理,以及由独立单元对系统资源的分配和调度。在不同的数据集上运行程序,甚至在同一数据集上运行多个程序,是一个不同的过程。(2)程序状态:一般来说,一个程序必须有三种基本状态:就绪、执行和阻塞。然而,在许多系统中,过程的状态变化可以更好地描述,并且增加了两种状态:新状态和终端状态。1)就绪状态,当一个进程被分配了除处理器(CPU)以外的所有必要资源时,只要获得了处理器,进程就可以立即执行。此时,进程状态称为就绪状态。在系统中,多个进程可以同时处于就绪状态。通常,这些就绪进程被安排在一个或多个队列中,这些队列称为就绪队列。2)一旦处于就绪状态的进程得到处理器,它就可以运行了。进程的状态称为执行状态。在单处理器系统中,只有一个进程在执行。在多处理器系统中,可能有多个进程在执行中。3)阻塞状态由于某些事件(如请求输入和输出、额外空间等),执行进程被挂起。这称为阻塞状态,也称为等待状态。通常,处于阻塞状态的进程被调度为-?这个队列称为阻塞队列。4)新状态当一个新进程刚刚建立并且还没有放入就绪队列中时,它被称为新状态。5)终止状态是

什么时候-?进程已正常或异常终止,操作系统已将其从系统队列中删除,但尚未取消。这就是所谓的终结状态。(3)过程控制块是过程实体的重要组成部分,是操作系统中最重要的记录数据。控制块PCB记录操作系统描述过程和控制过程操作所需的所有信息。通过PCB,一个不能独立运行的程序可以成为一个可以独立运行的基本单元,并且可以同时执行一个进程。换句话说,在进程的整个生命周期中,操作系统通过进程PCB管理和控制并发进程。过程控制块是系统用于过程控制的数据结构。系统根据进程的PCB来检测进程是否存在。因此,进程控制块是进程存在的唯一标志。当系统创建一个进程时,它需要为它创建一个PCB;当进程结束时,系统回收其PCB,进程结束。过程控制块的内容过程控制块主要包括以下四个方面的信息。过程标识信息过程标识用于对过程进行标识,通常有外部标识和内部标识。外部标识符由流程的创建者命名。通常是一串字母和数字。当用户访问进程时使用。外部标识符很容易记住。内部标识符是为了方便系统而设置的。操作系统为每个进程分配一个唯一的整数作为内部标识符。通常是进程的序列号。描述性信息(process scheduling message)描述性信息是与流程调度相关的一些有关流程状态的信息,包括以下几个方面。流程状态:表

实验一进程管理实验

实验一linux进程的创建与控制 【实验目的】 1、加深对进程概念的理解,明确进程和程序的区别; 2、进一步认识并发执行的实质; 3、分析进程争用资源的现象,学习解决进程互斥的方法; 【实验环境】 编程环境:TC或者VC 操作系统软件:linux 【准备知识】 一.基本概念 1、进程的概念;进程与程序的区别。 2、并发执行的概念。 3、进程互斥的概念。 二.系统调用 系统调用是一种进入系统空间的办法。通常,在OS的核心中都设置了一组用于实现各 种系统功能的子程序,并将它们提供给程序员调用。程序员在需要OS提供某种服务的时候,便可以调用一条系统调用命令,去实现希望的功能,这就是系统调用。因此,系统调用就像 一个黑箱子一样,对用户屏蔽了操作系统的具体动作而只是控制程序的执行速度等。各个不同的操作系统有各自的系统调用,女口windows API,便是windows的系统调用,Linux的系 统调用与之不同的是Linux由于内核代码完全公开,所以可以细致的分析出其系统调用的机制。 三.相关函数。 1 fork()函数 fork()函数创建一个新进程。 其调用格式为:int fork(); 其中返回int取值意义如下: 正确返回:等于0 :创建子进程,从子进程返回的ID值; 大于0 :从父进程返回的子进程的进程ID值。

错误返回:等于一1创建失败。 2 wait()函数 wait()函数常用来控制父进程与子进程的同步。在父进程中调用wait()函数,则父进程被阻塞,进入等待队列,等待子进程结束。当子进程结束时,会产生一个终止状态字,系统会向父进程发出SIGCHLD言号。当接到信号后,父进程提取子进程的终 止状态字,从wait()函数返回继续执行原程序。 其调用格式为:#i nclude #i nclude / (pid_t) wait(i nt *statloc) ; 正确返回:大于0:子进程的进程ID值; / 等于0:其它。 错误返回:等于一1调用失败。 3 exit()函数 exit() 函数是进程结束最常调用的函数,在main()函数中调用return,最终也是调用exit()函数。这些都是进程的正常终止。在正常终止时,exit()函数返回进程 结束状态。 其调用格式为:#in elude <> void exit(i nt status) ; 其中status为进程结束状态。 4 kill()函数 \ kill()函数用于删除执行中的程序或者任务。 其调用格式为:kill(i nt PID,i nt IID) ; 其中:PID是要被杀死的进程号,IID为向将被杀死的进程发送的中断号。 关于Linux下的C语言编程 1 )编辑器可使用vi 2 )编译器使用gee 格式:gee optio n file name 例如:gee -o main 主要的option -o指定输出文件名(不指定则生成默认文件) 其它的参数见帮助(man gee)

进程管理实验报告

进程的控制 1 .实验目的 通过进程的创建、撤消和运行加深对进程概念和进程并发执行的理解,明确进程与程序之间的区别。 【答:进程概念和程序概念最大的不同之处在于: (1)进程是动态的,而程序是静态的。 (2)进程有一定的生命期,而程序是指令的集合,本身无“运动”的含义。没有建立进程的程序不能作为1个独立单位得到操作系统的认可。 (3)1个程序可以对应多个进程,但1个进程只能对应1个程序。进程和程序的关系犹如演出和剧本的关系。 (4)进程和程序的组成不同。从静态角度看,进程由程序、数据和进程控制块(PCB)三部分组成。而程序是一组有序的指令集合。】2 .实验内容 (1) 了解系统调用fork()、execvp()和wait()的功能和实现过程。 (2) 编写一段程序,使用系统调用fork()来创建两个子进程,并由父进程重复显示字符串“parent:”和自己的标识数,而子进程则重复显示字符串“child:”和自己的标识数。 (3) 编写一段程序,使用系统调用fork()来创建一个子进程。子进程通过系统调用execvp()更换自己的执行代码,新的代码显示“new

program.”。而父进程则调用wait()等待子进程结束,并在子进程结束后显示子进程的标识符,然后正常结束。 3 .实验步骤 (1)gedit创建进程1.c (2)使用gcc 1.c -o 1编译并./1运行程序1.c #include #include #include #include void mian(){ int id; if(fork()==0) {printf(“child id is %d\n”,getpid()); } else if(fork()==0) {printf(“child2 id %d\n”,getpid()); } else {id=wait(); printf(“parent id is %d\n”,getpid()); }

(完整word版)操作系统实验报告 实验一 进程管理

实验一进程管理 一、目的 进程调度是处理机管理的核心内容。本实验要求编写和调试一个简单的进程调度程序。通过本实验加深理解有关进程控制块、进程队列的概念,并体会和了解进程调度算法的具体实施办法。 二、实验内容及要求 1、设计进程控制块PCB的结构(PCB结构通常包括以下信息:进程名(进程ID)、进程优先数、轮转时间片、进程所占用的CPU时间、进程的状态、当前队列指针等。可根据实验的不同,PCB结构的内容可以作适当的增删)。为了便于处理,程序中的某进程运行时间以时间片为单位计算。各进程的轮转时间数以及进程需运行的时间片数的初始值均由用户给定。 2、系统资源(r1…r w),共有w类,每类数目为r1…r w。随机产生n进程P i(id,s(j,k),t),0<=i<=n,0<=j<=m,0<=k<=dt为总运行时间,在运行过程中,会随机申请新的资源。 3、每个进程可有三个状态(即就绪状态W、运行状态R、等待或阻塞状态B),并假设初始状态为就绪状态。建立进程就绪队列。 4、编制进程调度算法:时间片轮转调度算法 本程序用该算法对n个进程进行调度,进程每执行一次,CPU时间片数加1,进程还需要的时间片数减1。在调度算法中,采用固定时间片(即:每执行一次进程,该进程的执行时间片数为已执行了1个单位),这时,CPU时间片数加1,进程还需要的时间片数减1,并排列到就绪队列的尾上。 三、实验环境 操作系统环境:Windows系统。 编程语言:C#。 四、实验思路和设计 1、程序流程图

2、主要程序代码 //PCB结构体 struct pcb { public int id; //进程ID public int ra; //所需资源A的数量 public int rb; //所需资源B的数量 public int rc; //所需资源C的数量 public int ntime; //所需的时间片个数 public int rtime; //已经运行的时间片个数 public char state; //进程状态,W(等待)、R(运行)、B(阻塞) //public int next; } ArrayList hready = new ArrayList(); ArrayList hblock = new ArrayList(); Random random = new Random(); //ArrayList p = new ArrayList(); int m, n, r, a,a1, b,b1, c,c1, h = 0, i = 1, time1Inteval;//m为要模拟的进程个数,n为初始化进程个数 //r为可随机产生的进程数(r=m-n) //a,b,c分别为A,B,C三类资源的总量 //i为进城计数,i=1…n //h为运行的时间片次数,time1Inteval为时间片大小(毫秒) //对进程进行初始化,建立就绪数组、阻塞数组。 public void input()//对进程进行初始化,建立就绪队列、阻塞队列 { m = int.Parse(textBox4.Text); n = int.Parse(textBox5.Text); a = int.Parse(textBox6.Text); b = int.Parse(textBox7.Text); c = int.Parse(textBox8.Text); a1 = a; b1 = b; c1 = c; r = m - n; time1Inteval = int.Parse(textBox9.Text); timer1.Interval = time1Inteval; for (i = 1; i <= n; i++) { pcb jincheng = new pcb(); jincheng.id = i; jincheng.ra = (random.Next(a) + 1); jincheng.rb = (random.Next(b) + 1); jincheng.rc = (random.Next(c) + 1); jincheng.ntime = (random.Next(1, 5));

实验三 存储管理指导

实验三存储管理 实验目的 1) 加深对存储管理的理解; 2) 掌握几种页面置换算法; 3) 通过实验比较各种置换算法的优劣。 实验要求 1) 编写程序完成实验内容; 2) 对测试数据进行分析; 3) 撰写实验报告。 实验内容 1) 定义为进程分配的物理块数; 2)定义进程运行所需访问的页面号; 3)定义页的结构; 4)模拟两种页面置换算法; 5)计算页面置换算法的命中率; 6)比较两种算法的优劣。 实验原理 1.虚拟存储 基于局部性原理,应用程序在运行之前,没有必要全部装入内存,仅须将那些当前要运行的少数页面或段先装入内存便可运行,其余部分暂留在盘上。程序在运行时,如果它所要访问的页(段)已调入内存,便可继续执行下去;但如果程序所要访问的页(段)尚未调入内存(称为缺页或缺段),此时程序应利用OS所提供的请求调页(段)功能,将它们调入内存,以使进程能继续执行下去。如果此时内存已满,无法再装入新的页(段),则还须再利用页(段)

的置换功能,将内存中暂时不用的页(段)调至盘上,腾出足够的内存空间后,再将要访问的页(段)调入内存,使程序继续执行下去。 2.页面置换算法 1)最佳(Optimal)置换算法 最佳置换算法是由Belady于1966年提出的一种理论上的算法。其所选择的被淘汰页面,将是以后永不使用的,或许是在最长(未来)时间内不再被访问的页面。采用最佳置换算法,通常可保证获得最低的缺页率。但由于人们目前还无法预知一个进程在内存的若干个页面中,哪一个页面是未来最长时间内不再被访问的,因而该算法是无法实现的,但可以利用该算法去评价其它算法。 2)最近最久未使用(LRU)置换算法 FIFO置换算法性能之所以较差,是因为它所依据的条件是各个页面调入内存的时间,而页面调入的先后并不能反映页面的使用情况。最近最久未使用(LRU)的页面置换算法,是根据页面调入内存后的使用情况进行决策的。由于无法预测各页面将来的使用情况,只能利用“最近的过去”作为“最近的将来”的近似,因此,LRU置换算法是选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间t,当须淘汰一个页面时,选择现有页面中其t值最大的,即最近最久未使用的页面予以淘汰。 LRU置换算法虽然是一种比较好的算法,但要求系统有较多的支持硬件。为了了解一个进程在内存中的各个页面各有多少时间未被进程访问,以及如何快速地知道哪一页是最近最久未使用的页面,须有两类硬件之一的支持:寄存器或栈。 a)寄存器 为了记录某进程在内存中各页的使用情况,须为每个在内存中的页面配置一个移位寄存器,可表示为R=R n-1R n-2R n-3… R2R1R0当进程访问某物理块时,要将相应寄存器的R n-1位置成1。此时,定时信号将每隔一定时间(例如100 ms)将寄存器右移一位。如果我们把n位寄存器的数看做是一个整数,那么,具有最小数值的寄存器所对应的页面,就是最近最久未使用的页面。 b)栈 可利用一个特殊的栈来保存当前使用的各个页面的页面号。每当进程访问某页面时,便将该页面的页面号从栈中移出,将它压入栈顶。因此,栈顶始终是最新被访问页面的编号,而栈底则是最近最久未使用页面的页面号。

实验1 Windows进程管理编程

实验一Windows进程管理和进程编程 实验内容1.1 Windows 任务管理器的进程管理 1、背景知识简介 Windows的任务管理器提供了用户计算机上正在运行的程序和进程的相关信息,也显示了最常用的度量进程性能的单位 使用任务管理器 ?可以打开监视计算机性能的关键指示器,快速查看正在运行的程序的状态,或者终止已停止响应的程序 ?也可以使用多个参数评估正在运行的进程的活动,以及查看CPU 和内存使用情况的图形和数据 任务管理器中 ?“应用程序”选项卡:显示正在运行程序的状态,用户能够结束、切换或者启动程序?“进程”选项卡:显示正在运行的进程信息。例如,可以显示关于CPU 和内存使用情况、页面错误、句柄计数以及许多其他参数的信息 ?“性能”选项卡:显示计算机动态性能,包括CPU 和内存使用情况的图表,正在运行的句柄、线程和进程的总数,物理、核心和认可的内存总数(KB) 等 2、实验目的和要求 通过在Windows 任务管理器中对程序进程进行响应的管理操作 熟悉操作系统进程管理的概念 学习观察操作系统运行的动态性能 3、实验环境 需要准备一台运行Windows XP Professional操作系统的计算机 4、实验内容与步骤 1.启动任务管理器。按Alt+Ctrl+Delete,或右键单击任务栏,选择任务管理器。

在Windows XP的任务管理器中,“进程”选项卡增加了一个“用户名”栏目,其中区分了SYSTEM、NETWORK SERVICE、LOCAL SERVICE和用户的不同进程类别。 2.使用任务管理器终止进程。选择进程名,点击右下角的“结束进程”。终止进程时要小 心,有可能导致不希望发生的结果,包括数据丢失和系统不稳定等。点击进程,右键选择“终止进程树”,会结束该进程以及它直接或间接创建的所有子进程。

操作系统实验二(进程管理)

操作系统进程管理实验 实验题目: (1)进程的创建编写一段程序,使用系统调用fork( )创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示字符“a”;子进程分别显示字符“b”和字符“c”。试观察记录屏幕上的显示结果,并分析原因。 (2)进程的控制修改已编写的程序,将每个进程输出一个字符改为每个进程输出一句话,在观察程序执行时屏幕上出现的现象,并分析原因。 (3)编制一段程序,使其实现进程的软中断通信。要求:使用系统调用fork( )创建两个子进程,再用系统调用signal( )让父进程捕捉键盘上来的中断信号(即按Del键);当捕捉到中断信号后,父进程调用系统调用kill( )向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止:Child process 1 is killed by parent! Child process 2 is killed by parent! 父进程等待两个子进程终止后,输出如下的信息后终止:Parent process is killed! 在上面的程序中增加语句signal(SIGINT, SIG_IGN)和signal(SIGQUIT, SIG_IGN),观察执行结果,并分析原因。 (4)进程的管道通信编制一段程序,实现进程的管道通信。使用系统调用pipe( )建立一条管道线;两个进程P1和P2分别向管道各写一句话:Child 1 is sending a message! Child 2 is sending a message! 而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。要求父进程先接收子进程P1发来的消息,然后再接收子进程P2发来的消息。 实验源程序及报告: (1)、进程的创建 #include int main(int argc, char *argv[]) { int pid1,pid2; /*fork first child process*/ if ( ( pid1=fork() ) < 0 ) { printf( "ProcessCreate Failed!"); exit(-1); }

存储管理实验报告.doc

存储管理实验报告

北方工业大学 《计算机操作系统》实验报告 实验名称存储管理实验序号 2 实验日期2013.11.27实验人 一、实验目的和要求 1.请求页式存储管理是一种常用的虚拟存储管理技术。本实验目的 是通过请求页式存储管理中页面置换算法的模拟设计,了解虚拟存储 技术的特点,掌握请求页式存储管理的页面置换算法。 二、相关背景知识 1.随机数产生办法 关于随机数产生办法, Linux 或 UNIX 系统提供函数 srand() 和 rand() ,分 别进行初始化和产生随机数。 三、实验内容 (1).通过随机数产生一个指令序列,共320条指令。指令的地址按下述原则生成: 1.50% 的指令是顺序执行的; 2.25% 的指令是均匀分布在前地址部分; 3.25% 的指令是均匀分布在后地址部 分;具体的实施方法是: 1.在[0, 319]的指令地址之间随机选取一起点 m; 2.顺序执行一条指令,即执行地址为 m+1 的指令; 3.在前地址[0,m+1]中随机选取一条指令并执行,该指令的地址为m’; 4.顺序执行一条指令,其地址为 m’+1; 5.在后地址 [m ’+2, 319]中随机选取一条指令并执行; 6.重复上述步骤 1~5,直到执行 320 次指令。 (2)将指令序列变换成页地址流,设 1.页面大小为 1K ; 2.用户内存容量为 4 页到 32 页; 3.用户虚存容量为 32K 。 在用户虚存中,按每 K 存放 10 条指令排列虚存地址,即 320 条指令在虚存 中存放的方式为: 第 0 条至第 9 条指令为第 0 页(对应虚存地址为 [0, 9]); 第 10 条至第 19 条指令为第 1 页(对应虚存地址为 [10, 19]); 第 310 条至第 319 条指令为第 31 页(对应虚存地址为 [310,319]); 按以上方式,用户指令可以组成 32 页。 (3)计算并输出下述各种算法在不同内存容量下的命中率。

Linux 进程管理实验

Linux 进程管理实验 一、实验内容: 1. 利用bochs观测linux0.11下的PCB进程控制结构。 2. 利用bochs观测linux0.11下的fork.c源代码文件,简单分析其中的重要函数。 3. 在fork.c适当位置添加代码,以验证fork函数的工作原理。 二、Linux进程管理机制分析 Linux有两类进程:一类是普通用户进程,一类是系统进程,它既可以在用户空间运行,又可以通过系统调用进入内核空间,并在内核空间运行;另一类叫做内核进程,这种进程只能在内核空间运行。在以i386为平台的Linux系统中,进程由进程控制块,系统堆栈,用户堆栈,程序代码及数据段组成。Linux系统中的每一个用户进程有两个堆栈:一个叫做用户堆栈,它是进程运行在用户空间时使用的堆栈;另一个叫做系统堆栈,它是用户进程运行在系统空间时使用的堆栈。 1.Linux进程的状态: Linux进程用进程控制块的state域记录了进程的当前状态,一个Linux 进程在它的生存期中,可以有下面6种状态。 1.就绪状态(TASK_RUNNING):在此状态下,进程已挂入就绪队列,进入准备运行状态。 2.运行状态(TASK_RUNNING):当进程正在运行时,它的state域中的值不改变。但是Linux会用一个专门指针(current)指向当前运行的

任务。 3.可中断等待状态(TASK_INTERRUPTIBLE):进程由于未获得它所申请的资源而处在等待状态。不管是资源有效或者中断唤醒信号都能使等待的进程脱离等待而进入就绪状态。即”浅睡眠状态”。 4.不可中断等待状态(TASK_UNINTERRUPTIBLE):这个等待状态与上面等待状态的区别在于只有当它申请的资源有效时才能被唤醒,而其它信号不能。即“深睡眠状态”。 5.停止状态(TASK_STOPPED):当进程收到一个SIGSTOP信号后就由运行状态进入停止状态,当收到一个SINCONT信号时,又会恢复运行状态。挂起状态。 6.终止状态(TASK_ZOMBIE):进程因某种原因终止运行,但进程控制块尚未注销。即“僵死状态”。 状态图如下所示: 2.Linux进程控制块:

进程管理实验报告

进程管理实验报告 1 .实验目的 通过进程的创建、撤消和运行加深对进程概念和进程并发执行的理解,明确进程与程序之间的区别。 【答:进程概念和程序概念最大的不同之处在于: (1)进程是动态的,而程序是静态的。 (2)进程有一定的生命期,而程序是指令的集合,本身无“运动”的含义。没有建立进程的程序不能作为1个独立单位得到操作系统的认可。 (3)1个程序可以对应多个进程,但1个进程只能对应1个程序。进程和程序的关系犹如演出和剧本的关系。 (4)进程和程序的组成不同。从静态角度看,进程由程序、数据和进程控制块(PCB)三部分组成。而程序是一组有序的指令集合。】2 .实验内容 (1) 了解系统调用fork()、execvp()和wait()的功能和实现过程。 (2) 编写一段程序,使用系统调用fork()来创建两个子进程,并由父进程重复显示字符串“parent:”和自己的标识数,而子进程则重复显示字符串“child:”和自己的标识数。 (3) 编写一段程序,使用系统调用fork()来创建一个子进程。子进程通过系统调用execvp()更换自己的执行代码,新的代码显示“new program.”。而父进程则调用wait()等待子进程结束,并在子进程结束后显示子进程的标识符,然后正常结束。

(3)运行并查看结果 child’s pid=2894 child’s pid=2994 parent’s pid=2849 child’s pid=2897 child’s pid=2897 parent’s pid=2849 child’s pid=2894 child’s pid=2994 parent’s pid=2849 (4)gedit创建进程2.c 使用gcc 2.c -o 2编译并./2运行程序2.c#include #include #include #include #include(6)运行并查看结果 new program ! -rw-r–r--. 1 root root 2456 Apr 14 2019 /etc/passwd child peocess PID:29035 4 .思考 (1) 系统调用fork()是如何创建进程的?

相关主题
文本预览
相关文档 最新文档