文档库 最新最全的文档下载
当前位置:文档库 › 操作系统实验二

操作系统实验二

操作系统实验二
操作系统实验二

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

学号 1215108019 姓名克帆

学院信息学院

班级 12电子2

实验目的

1、理解进程的概念,明确进程和程序的区别。

2、理解并发执行的实质。

3、掌握进程的创建、睡眠、撤销等进程控制方法。

实验容与要求

基本要求:用C语言编写程序,模拟实现创建新的进程;查看运行进程;换出某个进程;杀死进程等功能。

实验报告容

1、进程、进程控制块等的基本原理。

进程是现代操作系统中的一个最基本也是最重要的概念,掌握这个概念对于理解操作系统实质,分析、设计操作系统都有其非常重要的意义。为了强调进程的并发性和动态性,可以给进程作如下定义:进程是可并发执行的程序在一个数据集合上的运行过程,是系统进行资源分配和调度的一个独立单位。

进程又就绪、执行、阻塞三种基本状态,三者的变迁图如下:

由于多个程序并发执行,各程序需要轮流使用CPU,当某程序不在CPU上运行时,必须保留其被中断的程序的现场,包括:断点地址、程序状态字、通用寄存器的容、堆栈容、程序当前状态、程序的大小、运行时间等信息,以便程序再次获得CPU时,能够正确执行。为了保存这些容,需要建立—个专用数据结构,我们称这个数据结构为进程控制块PCB (Process Control Block)。

进程控制块是进程存在的惟一标志,它跟踪程序执行的情况,表明了进程在当前时刻的状态以及与其它进程和资源的关系。当创建一个进程时,实际上就是为其建立一个进程控制块。

在通常的操作系统中,PCB应包含如下一些信息:

①进程标识信息。为了标识系统中的各个进程,每个进程必须有惟一的标识名或标

识数。

②位置信息。指出进程的程序和数据部分在存或外存中的物理位置。

③状态信息。指出进程当前所处的状态,作为进程调度、分配CPU的依据。

④进程的优先级。一般根据进程的轻重缓急其它信息。

这里给出的只是一般操作系统中PCB所应具有的容,不同操作系统的PCB结构是不同的,我们将在2.8节介绍Linux系统的PCB结构。

程度为进程指定一个优先级,优先级用优先数表示。

⑤进程现场保护区。当进程状态变化时(例如一个进程放弃使用CPU),它需要将当时的CPU现场保护到存中,以便再次占用CPU时恢复正常运行,有的系统把要保护的CPU现场放在进程的工作区中,而PCB中仅给出CPU现场保护区起始地址。

⑥资源清单。每个进程在运行时,除了需要存外,还需要其它资源,如I/O设备、外存、数据区等。这一部分指出资源需求、分配和控制信息。

⑦队列指针或字。它用于将处于同一状态的进程成一个队列,在该单元中存放下一进程PCB首址。

⑧其它信息。

这里给出的只是一般操作系统中PCB所应具有的容,不同操作系统的PCB结构是不同的,我们将在2.8节介绍Linux系统的PCB结构。

2、程序流程图。

3、程序及注释。

#include

#include

#include

struct jincheng_type{ // 定义表示进程信息的结构体

int pid; //进程ID

int youxian; //优先级

int daxiao; //大小

int zhuangtai; //进程的状态,这里用0表示没有建立或被杀死,1表示执行,2表示换出

int info; //容

};

struct jincheng_type neicun[20]; //定义20个存单位给进程使用

int shumu=0,guaqi=0,pid,flag=0; //定义正在执行进程数目,被挂起进程数目,进程ID,运行标志位

void create() //函数--创建一个新进程

{

if(shumu>=20) printf("\n存已满,请先换出或杀死进程\n"); //判断存空间是否已满

else{

for(int i=0;i<20;i++)

if(neicun[i].zhuangtai==0) break; //选出空着的存单元给新进程使用

printf("\n请输入新进程pid\n"); //输入新进程ID存至选出的存单元

scanf("%d",&(neicun[i].pid));

for(int j=0;j

if(neicun[i].pid==neicun[j].pid) //当输入的新进程与原有进程ID 相同时,显示"该进程已存在"

{

printf("\n该进程已存在\n");

return;

}

printf("\n请输入新进程优先级\n"); //输入新进程的优先级、大小和容

scanf("%d",&(neicun[i].youxian));

printf("\n请输入新进程大小\n");

scanf("%d",&(neicun[i].daxiao));

printf("\n请输入新进程容\n");

scanf("%s",&(neicun[i].info));

neicun[i].zhuangtai=1; //将新进程的存单元状态(zhuangtai)设成"1",以表示存在且未被换出

shumu++; //正在运行的进程数目加一}

}

void run() //函数--查看正在运行的进程

{

for(int i=0;i<20;i++)

{

if(neicun[i].zhuangtai==1) //将存在且未被挂起(即zhuangtai=1)的进程显示出来,若存在这样的程序,则将flag设成1

{

printf("\n pid=%d--",neicun[i].pid);

printf("youxian=%d--",neicun[i].youxian);

printf("daxiao=%d--",neicun[i].daxiao);

printf("zhuangtai=%d--",neicun[i].zhuangtai);

printf("info=%c",neicun[i].info);

flag=1;

}

}

if(!flag) printf("\n当前没有运行进程\n"); //若当前没有运行进程(即flag=0),则显示"当前没有运行进程"

}

void huanchu() //函数--换出进程

{

if(!shumu) //判断是否无进程存在

{

printf("\n当前没有进程存在\n");

return;

}

printf("\n 输入唤出进程ID值"); //输入需要换出的进程ID,

scanf("%d",&pid);

for(int i=0;i<20;i++)

{

if(pid==neicun[i].pid)

{

if(neicun[i].zhuangtai==1) //若该ID代表的进程正在运行,则将其挂起,即将zhuangyai置成2,并将guaqi加一

{

neicun[i].zhuangtai=2;

guaqi++;

printf("\n已经成功换出进程\n");

}

else if(neicun[i].zhuangtai==2) printf("\n要唤出的进程已被挂起\n");

//若该ID代表的进程已被挂起,即zhuangtai==2,则显示'要唤出的进程已被挂起'

flag=1;

break;

}

}

if(!flag) printf("\n要唤出的进程不存在\n"); //若进程不存在,给出显示

}

void kill() //函数--杀死进程

{

if(!shumu) //判断是否无进程存在

{

printf("\n当前没有进程存在\n");

return;

}

printf("\n 输入杀死进程的ID值"); //读入要杀死的进程ID

scanf("%d",&pid);

for(int i=0;i<20;i++)

{

if(pid==neicun[i].pid)

{

if(neicun[i].zhuangtai==1) //若进程正在运行则再次询问是否要杀死,通过用户的反馈执行不同操作

{

printf("\n该进程正在运行,确定要杀死吗?\n");

printf("\n请输入1:Yes;0:NO \n");

scanf("%d",&flag);

if(flag)

{

neicun[i].zhuangtai=0; //将zhuangtai置为0,表示进程被杀死,并将shumu自减一

shumu--;

printf("\n已经成功杀死进程\n");

}

else printf("\要杀死的进程正在运行\n");

}

else if(neicun[i].zhuangtai==2) //若该进程已经被挂起,则直接杀死

{

neicun[i].zhuangtai=0;

shumu--;

printf("\n已经成功杀死进程\n");

}

flag=1;

break;

}

}

if(flag==0) printf("\n要杀死的进程不存在\n"); //若进程不存在,给出显示

}

void huanxing() //函数--唤醒进程

{

if(!shumu) //判断是否无进程存在

{

printf("\n当前没有运行进程\n");

return;

}

if(!guaqi) //判断是否无进程被挂起

{

printf("\n当前没有挂起进程\n");

return;

}

printf("\n输入pid\n"); //输入需要唤醒进程ID

scanf("%d",&pid);

for(int i=0;i<20;i++)

{

if(pid==neicun[i].pid)

{

flag=false;

if(neicun[i].zhuangtai==2) //判断该进程是否被挂起,若没有则将其唤醒并将guaqi自减一

{

neicun[i].zhuangtai=1;

guaqi--;

printf("\n已经成功唤醒进程\n");

}

else if(neicun[i].zhuangtai==2) printf("\n要唤醒的进程已被挂起\n");

//若目标进程已被挂起,则显示'要唤醒的进程已被挂起'

flag=1;

break;

}

}

if(!flag) printf("\n要唤醒的进程不存在\n"); //若要唤醒的进程不存在,给出显示

}

void viewall() //函数--查看存状态

{

for(int i=0;i<20;i++) //显示所有20个存单元的状态

{

printf("\n pid=%d",neicun[i].pid);

printf("youxian=%d",neicun[i].youxian);

printf("daxiao=%d",neicun[i].daxiao);

printf("zhuangtai=%d",neicun[i].zhuangtai);

printf("info=%c",neicun[i].info);

}

}

void main() //主函数

{

int n=1;

int num;

for(int i=0;i<20;i++) //先将存zhuangtai位清零

neicun[i].zhuangtai=0;

while(n)

{

printf("\n fff \n");

printf("\n*************************************************\n");

printf("\n 1.创建新的进程\n");

printf("\n 2.查看运行进程 \n");

printf("\n 3.唤出某个进程\n");

printf("\n 4.杀死某个进程 \n");

printf("\n 5.唤醒某个进程\n");

printf("\n 6.查看存状态 \n");

printf("\n 7.退出进程\n");

printf("\n*************************************************\n");

printf("\n请选择(1-7)\n");

scanf("%d",&num);

switch(num) //功能选择

{

case 1:create();break;

case 2:run();break;

case 3:huanchu();break;

case 4:kill();break;

case 5:huanxing();break;

case 6:viewall();break;

case 7:exit(0);

default:n=0;

}

flag=0;

}

}

4、程序运行演示与截图

(1)创建新进程,依次建立进程1、2、3,图中为建立进程2。

(2)查看运行的进程与查看存状态

(2)换出进程。图中以换出进程3为例。

(4)此时再次查看运行的进程与查看存状态,可以看到进程3已不在运行的进程中,存状态中其zhuangtai标识等于2,表明进程3确实已被换出。

(5)唤醒进程。图为将进程3唤醒。

(6)此时再次查看运行的进程与查看存状态,可以看到进程3重新出现在运行的进程中,且存状态中其zhuangtai标识等于1,表明进程3已被成功唤醒。

(7)杀死进程。图中以杀死进程3为例,并附以杀死后运行的进程与存状态图,

存状态中进程3的zhuangtai=0,表示进程3已被杀死。

5、实验结论

通过这次实验,我了解到进程控制块在进程管理中的重要作用,它跟踪程序执行的情况,表明了进程在当前时刻的状态以及与其它进程和资源的关系。同时也明白了我们平常使用程序的工作原理。

操作系统第二次作业答案

操作系统第二次作业 一、选择题 1.虚拟存储器的容量是由计算机的地址结构决定的,若CPU有32位地址,则 它的虚拟地址空间为【 A 】。 A.4G B.2G C.64K D.100K 2.在请求分页存储管理方案中,若某用户空间为3个页面,页长1KB,现有页 表如下,则逻辑地址1800】。 A.1052 B.3124 C.1076 D.5896 3.【 A 】用于管理各种不同的真实文件系统,是真实文件系统与服务之间的 接口。 A.VFS B.Ext2 C. vfat D.JFS 4.用磁带作为文件存贮介质时,文件只能组织成【 A 】 A.顺序文件 B.文件 C.索引文件 D.目录文件 5.按数据组织分类,【 B 】是以字节为单位直接读写的设备。 A.块设备 B.字符设备C.网络设备 D.虚拟设备6.在现代操作系统中采用缓冲技术的主要目的是【 C 】。 A.改善用户编程环境 B.提高CPU的处理速度 C.提高CPU和设备之间的并行程度 D.实现与设备无关性 7.【 D 】是将大量计算机通过网络连接在一起,以获得极高的运算能力和数 据共享的系统。 A. 实时系统 B.分时系统 C. 网络系统 D.分布系 统式 8.若一个文件的访问控制权限值为0754,请问同组用户对该文件具有【 C 】 权限。 A. 可读 B.可读可写 C. 可读可执行 D.没有权限 9.操作系统的安全问题中【 D 】是绕过安全性控制、获取对程序或系统访问 权的程序方法。 A.木马B.病毒C.蠕虫D.后门10.虚拟存储器的最大容量是由【B 】决定的。

A.页表长度B.计算机系统的地址结构和外存空间 C.存空间D.逻辑空间 11.在请求分页存储管理方案中,若某用户空间为3个页面,页长1KB,现有页 表如下,则逻辑地址2100】。 A.1052 B.3124 C.1076 D.5296 12.下面的【 B 】不是文件的物理存储结构。 A. 索引文件 B.记录式文件 C. 顺序文件 D.文件 13.从用户的角度看,引入文件系统的主要目的是【C 】。 A. 实现虚拟存储 B.保存文件系统 C. 实现对文件的按名存取 D.保存用户和系统的文档 14.使用SPOOLing系统的目的是为了提高【D 】的使用效率。 A.操作系统B.存C.CPU D.I/O设备 15.在UNIX中,通常把设备作为【 A 】文件来处理。 A.块设备或字符设备 B .普通 C.目录 D. 16.集群是【D 】系统的一种,是目前较热门的领域。 A. 实时 B.分时 C. 嵌入式 D.分布式 17.在终端中用ls –l查看某个文件的详细信息时显示drwxr-xr-x,从中可看出其 他用户对该目录具有【 B 】权限。 A. 可读 B.可读可执行 C. 可读可写可执行 D.可执行 18.操作系统的安全问题中【A 】是一种基于远程控制的黑客工具。 A.木马B.病毒C.后门 D.间谍软件 19.下列关于存地址叙述不正确的是【 A 】 A. 程序员使用的地址是物理地址 B.IA32平台上虚拟地址以“段:偏移量”的形式给出 C.线性地址空间是对CPU寻址能力的一种抽象 D.Linux中虚拟地址等价于线性地址 20.OS为每个文件开辟一个存储区【 C 】,里面记录这该文件的有关信息。 A. PCB B. JCB C. FCB D.DCB 21.从用户的角度看,引入文件系统的主要目的是【 C 】。 A. 实现虚拟存储 B.保存文件系统 C. 实现对文件的按名存取 D.保存用户和系统的文档 22.操作系统采用缓冲技术减少对CPU的【 A 】次数,从而提高资源的利用 率。

操作系统实验报告一

重庆大学 学生实验报告 实验课程名称操作系统原理 开课实验室DS1501 学院软件学院年级2013专业班软件工程2 班学生姓名胡其友学号20131802 开课时间2015至2016学年第一学期 总成绩 教师签名洪明坚 软件学院制

《操作系统原理》实验报告 开课实验室:年月日学院软件学院年级、专业、班2013级软件工 程2班 姓名胡其友成绩 课程名称操作系统原理 实验项目 名称 指导教师洪明坚 教师 评语教师签名:洪明坚年月日 1.实验目的: ?进入实验环境 –双击expenv/setvars.bat ?检出(checkout)EPOS的源代码 –svn checkout https://www.wendangku.net/doc/155107873.html,/svn/epos ?编译及运行 –cd epos/app –make run ?清除所有的临时文件 –make clean ?调试 –make debug ?在“Bochs Enhanced Debugger”中,输入“quit”退出调试 –调试指令,请看附录A 2.实验内容: ?编写系统调用“time_t time(time_t *loc)” –功能描述 ?返回从格林尼治时间1970年1月1日午夜起所经过的秒数。如果指针loc 非NULL,则返回值也被填到loc所指向的内存位置 –数据类型time_t其实就是long ?typedef long time_t; 3.实验步骤: ?Kernel space –K1、在machdep.c中,编写系统调用的实现函数“time_t sys_time()”,计算用户秒数。需要用到 ?变量g_startup_time,它记录了EPOS启动时,距离格林尼治时间1970年1午夜的秒数 ?变量g_timer_ticks

操作系统实验 磁盘调度算法

操作系统 实验报告 哈尔滨工程大学 计算机科学与技术学院

第六讲磁盘调度算法 一、实验概述 1. 实验名称 磁盘调度算法 2. 实验目的 (1)通过学习EOS 实现磁盘调度算法的机制,掌握磁盘调度算法执行的条件和时机; (2)观察 EOS 实现的FCFS、SSTF和 SCAN磁盘调度算法,了解常用的磁盘调度算法; (3)编写 CSCAN和 N-Step-SCAN磁盘调度算法,加深对各种扫描算法的理解。 3. 实验类型 验证性+设计性实验 4. 实验内容 (1)验证先来先服务(FCFS)磁盘调度算法; (2)验证最短寻道时间优先(SSTF)磁盘调度算法; (3)验证SSTF算法造成的线程“饥饿”现象; (4)验证扫描(SCAN)磁盘调度算法; (5)改写SCAN算法。 二、实验环境 在OS Lab实验环境的基础上,利用EOS操作系统,由汇编语言及C语言编写代码,对需要的项目进行生成、调试、查看和修改,并通过EOS应用程序使内核从源代码变为可以在虚拟机上使用。 三、实验过程 1. 设计思路和流程图 (1)改写SCAN算法 在已有 SCAN 算法源代码的基础上进行改写,要求不再使用双重循环,而是只遍历一次请求队列中的请求,就可以选中下一个要处理的请求。算法流程图如下图所示。 图 3.1.1 SCAN算法IopDiskSchedule函数流程图(2)编写循环扫描(CSCAN)磁盘调度算法 在已经完成的SCAN算法源代码的基础上进行改写,不再使用全局变量ScanInside 确定磁头移动的方向,而是规定磁头只能从外向内移动。当磁头移动到最内的被访问磁道时,磁头立即移动到最外的被访问磁道,即将最大磁道号紧接着最小磁道号构成循环,进行扫描。算法流程图如下图所示。

川大2020《计算机控制系统》第二次作业答案

首页 - 我的作业列表 - 《计算机控制系统》第二次作业答案 完成日期:2020年06月08日 14点48分 说明:每道小题选项旁的标识是标准答案。 一、单项选择题。本大题共16个小题,每小题 3.0 分,共48.0分。在每小题给出的选项中,只有一项是符合题目要求的。 1.()是将生产过程工艺参数转换为电参数的装置。 A.传感器 B.A/D转换器 C.D/A转换器 D.互感器 2.在计算机和生产过程之间设置的信息传送和转换的连接通道是()。 A.接口 B.过程通道 C.模拟量输入通道 D.开关量输入通道 3.所谓量化,就是采用一组数码来逼近离散模拟信号的幅值,将其转换为 ()。 A.模拟信号 B.数字信号 C.程序代码 D.量化代码 4.数控系统一般由输入装置、输出装置、控制器和插补器等四大部分组成, 这些功能都由()来完成。 A.人 B.生产过程 C.计算机 D.实时计算 5.外界干扰的扰动频率越低,进行信号采集的采样周期应该越()。 A.长 B.短

C.简单 D.复杂 6.数字PID控制器是控制系统中应用最为广泛的一种控制规律,其中能迅速 反应误差,从而减小误差,但不能消除稳态误差的是()。 A.微分控制 B.积分控制 C.比例控制 D.差分控制 7.在计算机控制系统中,PID控制规律的实现必须采用数值逼近的方法。当 采样周期短时,用求和代替积分、用后向差分代替微分,使模拟PID离散化变为()。 A.微分方程 B.差分方程 C.积分方程 D.离散方程 8.香农采样定理给出了采样周期的上限,采样周期的下限为计算机执行控制 程序和()所耗费的时间,系统的采样周期只能在Tmin和Tmax之间选择。 A.输入输出 B.A/D采样时间 C.D/A转换时间 D.计算时间 9.在有交互作用的多参数控制系统中,振铃现象有可能影响到系统的()。 A.可靠性 B.稳定性 C.经济性 D.通用性 10.在实际生产过程中,因为前馈控制是一个(),因此,很少只采用前馈 控制的方案,常常采用前馈-反馈控制相结合的方案。 A.开环系统

操作系统实验报告-实验二

操作系统实验报告——实验二:C编程环境 实验目的 1.熟悉Linux下C程序设计的环境; 2.对系统调用有初步了解。 实验内容 1.Linux下C语言程序的开发过程 a、在用户主目录下用vi编辑C语言源程序(源程序已附后),如:$vi hello.c。 b、用gcc编译C语言源程序:$gcc ./hello.c -o example 这里gcc是Linux下的C语言程序编译器(GNU C Compiler),./hello.c表示待编译的源文件是当前工作目录下的hello.c,-o example表示编译后产生的目标代码文件名为example。 c、若编译不正确,则进入vi修改源程序,否则,运行目标代码:$./example 。注意: 这只是gcc最基本的用法,其他常用选项有:-c , -S , -O , -O2, -g 等。 2.编辑、调试下面c语言程序,说明该程序的功能。 #include #include int main() { int n,a[200],carry,temp,i,j,digit = 1; printf("Please input n:"); scanf("%d",&n); a[0] = 1; for( i = 2; i <= n; ++i) { for( j = 1, carry = 0; j <= digit; ++j) { temp = a[j-1] * i + carry; a[j-1] = temp % 10; carry = temp / 10; } while(carry) { a[++digit-1] = carry % 10; carry /= 10; } } printf("Result is:\n%d ! = ",n); for( i = digit; i >=1; --i) { printf("%d",a[i-1]); }

操作系统第一次与第二次实验报告

实验报告 实验1 Linux基本环境 1、实验目的 (1)熟悉Linux下的基本操作,学会使用各种Shell命令去操作Linux,对Linux 有一个感性认识。 (2)学会使用vi编辑器编简单的C语言程序,并能对其编译和调试。 2、实验内容 (1)以root用户身份登陆,并使用“ls”,“cat”“cd”等命令来实现基本的文件操作并观察Linux文件系统的特点; (2)使用vi编辑器编写一C程序,并用gcc命令进行编译和链接,并用a.out 来进行输出结果。 3、实验结果 (1) a.输入“ls”后,vi编辑器显示主文件夹下的所有文件及目录名。使用dir 查看当前目录内容。 b.输入“cat”后,会显示文件:cat 文件名建立文件:cat >文件名, ctrl+d结束输入。 c.输入“cd”,改变当前目录,cd ..回到上层目录,cd /回到根目录。(2) a.在命令行键入vi filename.c 然后回车。 b.按一下键盘上的I键(insert),进入编辑模式。(a与i是相同的用法) c.当文件编辑完后,按Esc 键;输入:wq) ,保存退出。 d.对刚才编写的程序进行编译。编译的命令是:gcc filenam e.c e.最后运行程序,命令式:./a.out 4、实验总结 通过做本次实验,我熟悉了Linux环境下的基本操作,学会使用各种命令去操作Linux,也学会使用vi编辑器编辑简单的程序,并能对其编译

和调试。了解并掌握了对vi编辑器的一些基本使用方法等。可能由于初次接触Linux环境,所以刚开始编程时出现了许多错误,但我及时找同学或老师来帮忙,解决我的问题,这些错误能够让我更清楚地了解自己对哪些知识掌握的不够透彻,让自己对知识掌握的更牢固。 实验2 进程管理 1、实验目的 (1)加深对进程概念的理解,明确进程和程序的区别。 (2)进一步认识并发执行的实质。 (3)分析进程竞争资源现象,学习解决进程互斥的方法。 (4)了解Linux系统中进程通信的基本原理。 2、实验内容 (1)进程的创建 编写一段源程序,使系统调用fork()创建两个子进程,当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕 上显示一个字符:父进程显示字符“a”;子进程分别显示字符“b”和 字符“c”。试观察纪录屏幕上的显示结果,并分析原因。 (2)进程的控制 修改已编写的程序,将每个进程输出一个字符改为每个进程输出一句话,在观察程序执行时屏幕出现的现象,并分析原因。 如果在程序中使用调用lockf()来给每一个子进程加锁,可以实现进程 之间的互斥,观察并分析出现的现象。 (3)①编写一段程序,使其现实进程的软中断通信。 要求:使用系统调用fork()创建两个子进程,再用系统调用signal() 让父进程捕捉键盘上来的中断信号(即按DEL键);当捕捉到中断信号 后,父进程用系统调用Kill()向两个子进程发出信号,子进程捕捉到信 号后分别输出下列信息后终止: Child Processll is Killed by Parent!

《操作系统》第二次作业参考答案

习题与参考答案 ? 1.10 什么是用户态和核心态?有何作用? 答:内核态可以无限制访问系统和资源,包括对系统存储、外部设备进行访问。操作系统就工作在内核态模式下。用户态下进程的访问权限受到了限制,可正常执行普通的操作命令外,对关键资源只能通过操作系统接口访问。例如,不能直接访问外部设备,不能直接访问操作系统的内存代码和数据。其作用是保护操作系统不受用户程序的破坏,提高系统的可靠性。 ? 1.11 什么是微内核结构?与单内核结构相比,各有何优势和缺点? 答:微内核结构:1)有足够小的内核2)基于客户/服务器模式 微内核结构优势:1)提高了系统的可扩展性2)增强了系统的可靠性;缺点:在完成一次客户对OS提出的系统服务请求时,需要进行消息内容打包和解包,需要进行消息的多次拷贝,进行多次用户/内核模式及上下文的切换,从而使微内核OS的运行效率降低。 单内核结构优势:系统服务只需要进行两次上下文的切换,效率较高。缺点:可靠性较低,可扩展性较差; ? 1.12 什么是并发?举例说明。 答:并发是指两个或多个事件在同一时间间隔内发生。如:在多道程序环境下,并发性是指在一段时间内宏观上有多个程序在同时运行。可分为三种不同的执行情况,包括顺序执行、交替执行和并行执行。在多道分时操作系统中,如果只有一个CPU,每一时刻仅能有一道程序执行,微观上这些程序分时地交替执行,但在宏观上(一段时间内)是同时执行;在有多个处理机的系统中,多个程序便可被分配到不同处理机上,实现并行执行,是并发执行的一种特殊情况。 ? 1.13 什么是互斥共享?举例说明。 答:互斥访问共享是共享资源的一种形式,要求在一段时间内只允许一个进程可以访问该资源。例如:当一个进程A要访问某资源时,必须先提出请求。如果此时该资源空闲,系统便可将之分配给请求进程A使用。此后若再有其他进程B也要访问该资源时但A未用完时,则必须等待。仅当A进程访问完并释放该资源后,才允许进程B对该资源进行访问。 ? 1.14 什么是系统调用,与程序调用有何不同? 答:系统调用是应用程序请求OS内核完成某种功能的一种过程调用,是应用程序使用操作系统功能的入口。 与程序调用的不同:1)运行在不同的系统状态,调用程序是在用户态,被调用程序是运行在系统态2)状态的转换通过软中断进入3)返回问题,在采用了抢占式调度方式的系统中,在被调用过程执行完后,要对系统中所有要求运行的进程做优先权分

操作系统lab2实验报告

HUNAN UNIVERSITY 操作系统实验报告

目录 一、内容 (3) 二、目的 (3) 三、实验设计思想和练习题 (3) 练习0:填写已有实验 (3) 练习1:实现 first-fit 连续物理内存分配算法(需要编程) (3) 练习2:实现寻找虚拟地址对应的页表项(需要编程) (8) 练习3:释放某虚地址所在的页并取消对应二级页表项的映射(需要编程) (11) 运行结果 (13) 四、实验体会 (13)

一、内容 本次实验包含三个部分。首先了解如何发现系统中的物理内存;然后了解如何建立对物理内存的初步管理,即了解连续物理内存管理;最后了解页表相关的操作,即如何建立页表来实现虚拟内存到物理内存之间的映射,对段页式内存管理机制有一个比较全面的了解。 二、目的 1.理解基于段页式内存地址的转换机制; 2.理解页表的建立和使用方法; 3.理解物理内存的管理方法。 三、实验设计思想和练习题 练习0:填写已有实验 使用eclipse中的diff/merge工具将实验1的代码填入本实验中代码中有“LAB1”的注释相应部分。 练习1:实现 first-fit 连续物理内存分配算法(需要编程) 在实现first fit 内存分配算法的回收函数时,要考虑地址连续的空闲块之间的合并操作。提示:在建立空闲页块链表时,需要按照空闲页块起始地址来排序,形成一个有序的链表。可能会修改default_pmm.c 中的default_init,default_init_memmap,default_alloc_pages, default_free_pages等相关函数。请仔细查看和理解default_pmm.c中的注释。 请在实验报告中简要说明你的设计实现过程。请回答如下问题: 你的first fit算法是否有进一步的改进空间。 解答: 分析思路: (1)数据结构: A.每个物理页利用一个Page结构体表示,查看kern/mm/memlayout.h包括:

操作系统第二次实验first-fit, next-fit

操作系统第二次实验报告 物联网1301 齐亨13516110 一、实验简介 本实验要求建造一个没有虚拟功能的内存管理系统。任务如下: ? 设计一个内存管理器,支持至少两种分配策略, 如first-fit, next-fit, best-fit, worst-fit 等。 ? 对不同分配策略的性能进行评估。 二、实验过程 1、first fit(首次适应) 首次适应策略的思路是,分配时在空闲块列表中搜索,找到第一个能够满足请求的块即停止搜索,然后把搜索到的块分割,一部分返回给请求者,另一部分仍然作为空闲块留在空闲列表的原来位置。首次适应策略的问题在于,链表头部区域的块倾向于被首先分割,经过一段时间后,空闲链表头部可能堆积大量小的空闲块,这会导致搜索时间的增加,因为当请求一个头部区域的小块无法满足的块时,需要顺次检查这些小块。 代码如下: #include #include #include int array[99]; int *array_request(int n) { int count=0; int *p=&array[0]; int *l=&array[99]; while(count

} if(count

上海大学操作系统(二)实验报告(全)

评分: SHANGHAI UNIVERSITY 操作系统实验报告 学院计算机工程与科学 专业计算机科学与技术 学号 学生姓名

《计算机操作系统》实验一报告 实验一题目:操作系统的进程调度 姓名:张佳慧学号 :12122544 实验日期: 2015.1 实验环境: Microsoft Visual Studio 实验目的: 进程是操作系统最重要的概念之一,进程调度又是操作系统核心的主要内容。本实习要求学生独立地用高级语言编写和调试一个简单的进程调度程序。调度算法可任意选择或自行设计。例如,简单轮转法和优先数法等。本实习可加深对于进程调度和各种调度算法的理解。实验内容: 1、设计一个有n个进程工行的进程调度程序。每个进程由一个进程控制块(PCB)表示。进程控制块通常应包含下述信息:进程名、进程优先数、进程需要运行的时间、占用CPU的时间以及进程的状态等,且可按调度算法的不同而增删。 2、调度程序应包含2~3种不同的调度算法,运行时可任意选一种,以利于各种算法的分析比较。 3、系统应能显示或打印各进程状态和参数的变化情况,便于观察诸进程的调度过程。 操作过程: 1、本程序可选用优先数法或简单轮转法对五个进程进行调度。每个进程处于运行R(run)、就绪W(wait)和完成F(finish)三种状态之一,并假设起始状态都是就绪状态W。为了便于处理,程序进程的运行时间以时间片为单位计算。进程控制块结构如下: 进程控制块结构如下: PCB 进程标识数 链指针 优先数/轮转时间片数 占用 CPU 时间片数 进程所需时间片数 进程状态 进程控制块链结构如下:

其中:RUN—当前运行进程指针; HEAD—进程就绪链链首指针; TAID—进程就绪链链尾指针。2、算法与框图 (1) 优先数法。进程就绪链按优先数大小从高到低排列,链首进程首先投入运行。每过一个时间片,运行进程所需运行的时间片数减 1,说明它已运行了一个时间片,优先数也减 3,理由是该进程如果在一个时间片中完成不了,优先级应该降低一级。接着比较现行进程和就绪链链首进程的优先数,如果仍是现行进程高或者相同,就让现行进程继续进行,否则,调度就绪链链首进程投入运行。原运行进程再按其优先数大小插入就绪链,且改变它们对应的进程状态,直至所有进程都运行完各自的时间片数。 (2) 简单轮转法。进程就绪链按各进程进入的先后次序排列,进程每次占用处理机的轮转时间按其重要程度登入进程控制块中的轮转时间片数记录项(相当于优先数法的优先数记录项位置)。每过一个时间片,运行进程占用处理机的时间片数加 1,然后比较占用处理机的时间片数是否与该进程的轮转时间片数相等,若相等说明已到达轮转时间,应将现运行进程排到就绪链末尾,调度链首进程占用处理机,且改变它们的进程状态,直至所有进程完成各自的时间片。 (3) 程序框图

操作系统实验3报告

实验三、进程通讯 ——管道及共享内存姓名:徐洪班级:10电信实验班学号:Q10600109 实验用学号:e06620111 一、实验目的 (1)加深对管道概念的理解。 (2)掌握利用管道进行进程通信的程序设计。 (3)Linux系统的共享内存机制允许在任意进程间大批量地交换数据。本实验的目的是了解和熟悉Linux支持的共享存储区机制。 二、实验预备内容 认真阅读实验材料中管道通信及共享内存部分,加深对管道通信及共享内存机制的理解。 三、实验内容 任务一、 (1)阅读以上父子进程利用管道进行通信的例子(例1),写出程序的运行结果并分析。 (2)编写程序:父进程利用管道将一字符串交给子进程处理。子进程读字符串,将里面的字符反向后再交给父进程,父进程最后读取并打印反向的字符串。 任务二、 (1)阅读例2的程序,运行一次该程序,然后用ipcs命令查看系统中共享存储区的情况,再次执行该程序,再用ipcs命令查看系统中共享内存的情况,对两次的结果进行比较,并分析原因。最后用ipcrm命令删除自己建立的共享存储区。(有关ipcs和ipcrm介绍见后面一页)(2)每个同学登陆两个窗口,先在一个窗口中运行例3程序1(或者只登陆一个窗口,先在该窗口中以后台方式运行程序1),然后在另一个窗口中运行例3程序2,观察程序的运行结果并分析。运行结束后可以用ctrl+c结束程序1的运行。 四、实验结果 运行例1 反向输出

main() { int x,fd[2],n,i,fs[2]; char buf[30],s[30],m[30],b[30]; pipe(fd); pipe(fs); while ((x=fork())==-1); if (x==0) { close(fd[0]); close(fs[1]); printf("Parent Process!\n"); strcpy(buf,"This is an example\n"); write(fd[1],buf,30); read(fs[0],m,30); printf("Parent Process1!\n"); printf("%s\n",m); } else{ close(fd[1]); close(fs[0]); printf("Child Process!\n"); read(fd[0],s,30); n=strlen(s)-1; for( i=0;i

操作系统实验报告

操作系统教程 实 验 指 导 书 姓名: 学号: 班级:软124班 指导老师:郭玉华 2014年12月10日

实验一WINDOWS进程初识 1、实验目的 (1)学会使用VC编写基本的Win32 Consol Application(控制台应用程序)。 (2)掌握WINDOWS API的使用方法。 (3)编写测试程序,理解用户态运行和核心态运行。 2、实验内容和步骤 (1)编写基本的Win32 Consol Application 步骤1:登录进入Windows,启动VC++ 6.0。 步骤2:在“FILE”菜单中单击“NEW”子菜单,在“projects”选项卡中选择“Win32 Consol Application”,然后在“Project name”处输入工程名,在“Location”处输入工程目录。创建一个新的控制台应用程序工程。 步骤3:在“FILE”菜单中单击“NEW”子菜单,在“Files”选项卡中选择“C++ Source File”, 然后在“File”处输入C/C++源程序的文件名。 步骤4:将清单1-1所示的程序清单复制到新创建的C/C++源程序中。编译成可执行文件。 步骤5:在“开始”菜单中单击“程序”-“附件”-“命令提示符”命令,进入Windows“命令提示符”窗口,然后进入工程目录中的debug子目录,执行编译好的可执行程序: E:\课程\os课\os实验\程序\os11\debug>hello.exe 运行结果 (如果运行不成功,则可能的原因是什么?) : 有可能是因为DOS下路径的问题 (2)计算进程在核心态运行和用户态运行的时间 步骤1:按照(1)中的步骤创建一个新的“Win32 Consol Application”工程,然后将清单1-2中的程序拷贝过来,编译成可执行文件。 步骤2:在创建一个新的“Win32 Consol Application”工程,程序的参考程序如清单1-3所示,编译成可执行文件并执行。 步骤3:在“命令提示符”窗口中运行步骤1中生成的可执行文件,测试步骤2中可执行文件在核心态运行和用户态运行的时间。 E:\课程\os课\os实验\程序\os12\debug>time TEST.exe 步骤4:运行结果 (如果运行不成功,则可能的原因是什么?) : 因为程序是个死循环程序 步骤5:分别屏蔽While循环中的两个for循环,或调整两个for循环的次数,写出运行结果。 屏蔽i循环: 屏蔽j循环: _______________________________________________________________________________调整循环变量i的循环次数:

东北大学操作系统第二次实验报告

实验4:进程的管道通信 一、题目:进程的管道通信 二、目的: ●加深对进程概念的理解,明确进程和程序的区别; ●学习进程创建的过程,进一步认识并发执行的实质; ●分析进程争用资源的现象,学习解决进程互斥的方法; ●学习解决进程同步的方法; ●掌握Linux系统进程间通过管道通信的具体实现方法。 三、实验内容 ?使用系统调用pipe()建立一条管道线,两个子进程分别向管道写一句话(写 的内容自己定,但要有该进程的一些信息); ?父进程从管道中读出来自两个子进程的消息,显示在屏幕上; ?要求:父进程首先接收子进程p1发来的消息,然后再接收子进程p2发来的 消息。 四、实验要求 1、这是一个设计型实验,要求自行、独立编制程序; 2、两个子进程要并发执行; 3、实现管道的互斥使用。当一个子进程正在对管道进行写操作时,另一个欲写入管道的子进程必须等待。使用系统调用lockf(fd[1],1,0)实现对管道的加锁操作,用lockf(fd[1],0,0)解除对管道的锁定; 4、实现父子进程的同步,当父进程试图从一空管道中读取数据时,便进入等待状态,直到子进程将数据写入管道返回后,才将其唤醒。 五、程序流程图

图5.1 父进程流程图

图5.2子进程P1流程图图5.3子进程P2流程图 六、源程序 #include #include #include #include #include #include #include #include

操作系统第二次作业

《计算机操作系统》第二次作业 一、填空题 1、对于通用计算机而言,存储层次至少应具有最高层(CPU寄存器)、中间层(主存)、最低层(辅存)三级。 2、在较高档的计算机中,根据具体功能分工将存储器细划为(寄存器)、(高速缓存)、(主存储器)(磁盘缓存)、(固定磁盘)、(可移动存储介质)等六层。 3、在存储层次中,越向上,存储介质的访问速度越(快),价格越(高),相对存储容量越(小)。 4、在计算机系统存储层次中,(主存储器)和(寄存器)又称为可执行存储器,进程对它的访问可通过(机器)或(I/O)指令实现。 5、在I/O设备的接口中,有(数据信号)、(状态信号)、(控制信号)三种类型的信号。 6、设备控制器的基本功能有(数据缓冲)、(差错控制)、(数据交换)、(标识和报告设备的状态)、(接收和识别命令)、(地址识别)六个。 7、设备控制器由(设备控制器与处理机的接口)、(设备控制器与设备的接口)、(I/O 逻辑)三部分组成。 8、I/O通道的类型有(字节多路通道)、(数组选择通道)、(数组多路通道)三种。 9、基于文件系统的概念,可以把数据组成分为(文件)、(记录)、(数据项)三级。 10、在文件系统中,数据项可分为(基本数据项)和(组合数据项)两种类型。 11、文件可分为(有结构文件)和(无结构文件)两种。 12、文件的属性包括(文件类型)、(文件长度)、(文件的物理位置)、(文件的存取控制)四个。(还有一个文件的建立时间) 二、选择题 1、寄存器、高速缓存、主存储器和磁盘缓存均()操作系统管理的管辖范畴,掉电后它们存储的信息()。B A)属于、仍存在 B)属于、不存在 C)不属于、仍存在 D)不属于、不存在 2、固定磁盘和可移动存储介质均()操作系统管理的管辖范畴,掉电后它们存储的信息()。C A)属于,仍存在 B)属于,不存在 C)不属于,仍存在 D)不属于,不存在 3、在计算机系统存储层次中,系统对存放于寄存器和主存储器和存放于辅存中的信息的访问机制是()的,所需耗费的时间是()的。D A)相同,相同 B)相同,不同 C)不同,相同 D)不同,不同 4、单一连续分配方式可用于()的操作系统中。A A)单用户,单任务 B)单用户,多任务 C)多用户,单任务 D)多用户,多任务 5、在(A)中,由于/CPU的高速性和I/O设备的低速性,造成对CPU资源的极大浪费。 A)程序I/O方式 B)中断驱动I/O控制方式

计算机操作系统 实验报告

操作系统实验报告 学院:计算机与通信工程学院 专业:计算机科学与技术 班级: 学号: 姓名: 指导教师: 成绩: 2014年 1 月 1 日

实验一线程的状态和转换(5分) 1 实验目的和要求 目的:熟悉线程的状态及其转换,理解线程状态转换与线程调度的关系。 要求: (1)跟踪调试EOS线程在各种状态间的转换过程,分析EOS中线程状态及其转换的相关源代码; (2)修改EOS的源代码,为线程增加挂起状态。 2 完成的实验内容 2.1 EOS线程状态转换过程的跟踪与源代码分析 (分析EOS中线程状态及其转换的核心源代码,说明EOS定义的线程状态以及状态转换的实现方法;给出在本部分实验过程中完成的主要工作,包括调试、跟踪与思考等) 1.EOS 准备了一个控制台命令“loop ”,这个命令的命令函数是 ke/sysproc.c 文件中的ConsoleCmdLoop 函数(第797行,在此函数中使用 LoopThreadFunction 函数(第755 行)创建了一个优先级为 8 的线程(后面简称为“loop 线程”),该线程会在控制台中不停的(死循环)输出该线程的ID和执行计数,执行计数会不停的增长以表示该线程在不停的运行。loop命令执行的效果可以参见下图: 2. 线程由阻塞状态进入就绪状态 (1)在虚拟机窗口中按下一次空格键。 (2)此时EOS会在PspUnwaitThread函数中的断点处中断。在“调试”菜单中选择“快速监视”,在快速监视对话框的表达式编辑框中输入表达式“*Thread”,然后点击“重新计算”按钮,即可查看线程控制块(TCB)中的信息。其中State域的值为3(Waiting),双向链表项StateListEntry的Next和Prev指针的值都不为0,说明这个线程还处于阻塞状态,并在某个同步对象的等待队列中;StartAddr域的值为IopConsoleDispatchThread,说明这个线程就是控制台派遣线程。 (3)关闭快速监视对话框,激活“调用堆栈”窗口。根据当前的调用堆栈,可以看到是由键盘中断服务程序(KdbIsr)进入的。当按下空格键后,就会发生键盘中断,从而触发键盘中断服务程序。在该服务程序的最后中会唤醒控制台派遣线程,将键盘事件派遣到活动的控制台。 (4)在“调用堆栈”窗口中双击PspWakeThread函数对应的堆栈项。可以看到在此函数中连续调用了PspUnwaitThread函数和PspReadyThread函数,从而使处于阻塞状态的控制台派遣线程进入就绪状态。 (5)在“调用堆栈”窗口中双击PspUnwaitThread函数对应的堆栈项,先来看看此函数是如何改变线程状态的。按F10单步调试直到此函数的最后,然后再从快速监视对

操作系统实验报告.实验一_WINDOWS进程初识

操作系统教程 实验指导书

实验一WINDOWS进程初识 1、实验目的 (1)学会使用VC编写基本的Win32 Consol Application(控制台应用程序)。 (2)掌握WINDOWS API的使用方法。 (3)编写测试程序,理解用户态运行和核心态运行。 2、实验内容和步骤 (1)编写基本的Win32 Consol Application 步骤1:登录进入Windows,启动VC++ 6.0。 步骤2:在“FILE”菜单中单击“NEW”子菜单,在“projects”选项卡中选择“Win32 Consol Application”,然后在“Project name”处输入工程名,在“Location”处输入工程目录。创建一个新的控制台应用程序工程。 步骤3:在“FILE”菜单中单击“NEW”子菜单,在“Files”选项卡中选择“C++ Source File”, 然后在“File”处输入C/C++源程序的文件名。 步骤4:将清单1-1所示的程序清单复制到新创建的C/C++源程序中。编译成可执行文件。 步骤5:在“开始”菜单中单击“程序”-“附件”-“命令提示符”命令,进入Windows “命令提示符”窗口,然后进入工程目录中的debug子目录,执行编译好的可执行程序:E:\课程\os课\os实验\程序\os11\debug>hello.exe 运行结果 (如果运行不成功,则可能的原因是什么?) : 答:运行成功,结果: (2)计算进程在核心态运行和用户态运行的时间 步骤1:按照(1)中的步骤创建一个新的“Win32 Consol Application”工程,然后将清单1-2中的程序拷贝过来,编译成可执行文件。 步骤2:在创建一个新的“Win32 Consol Application”工程,程序的参考程序如清单1-3所示,编译成可执行文件并执行。 步骤3:在“命令提示符”窗口中运行步骤1中生成的可执行文件,测试步骤2中可执行文件在核心态运行和用户态运行的时间。 E:\课程\os课\os实验\程序\os12\debug>time TEST.exe 步骤4:运行结果 (如果运行不成功,则可能的原因是什么?) 因为此程序是个死循环,所以运行时间为无穷大。_______________________________________________________________________________ _______________________________________________________________________________ _______________________________________________________________________________ _______________________________________________________________________________ __________________________________________________________________________

操作系统第二次作业题

操作系统第二次作业 要求:题目可打印,答案需手写!交给小课老师! 一、单项选择题 1.死锁产生的原因之一是__D____。 A.系统中没有采用SPOOLing技术 B.使用的P、V操作过多 C.有共享资源存在 D.资源分配不当 2.某计算机系统中有8台打印机,有K个进程竞争使用,每个进程最多需要3台打印机。该系统可能会发生死锁的K的最小值是__C____。 A.2 B.3 C.4 D.5 题解:当每个都获得了2台打印机而且系统中剩余打印机不少于1台时,系统不会发生死锁,即8>=2K+1,k=3.5,去整为4。 提示:有银行家算法可以推导出,要使系统安全,对于系统中有m个资源,有n个并发进程共享使用时,每个进程可以提出的最大资源请求数量为x,则n (x-1)+1<=m,即 X=1 当m=n X=(m-1)/n+1 当m>n 3.某时刻进程的资源使用情况如表2.20所示,此时的安全序列是____D__。 表2.20 某时刻进程的资源使用情况表 进程已经分配资源尚需资源可用资源 R1 R2 R3 R1 R2 R3 R1 R2 R3 P1 P2 P3 P4 2 0 0 1 2 0 0 1 1 0 0 1 00 1 1 3 2 1 3 1 2 0 0 0 2 1 A.P1,P2,P3,P4 B.P1,P3,P2,P4 C. P1,P4,P3,P2 D.不存在 题解: 表2.21 选项A的安全性检测表 进程Work Need Allocation Work+Allocation Finish 0 2 1 2 2 1 0 0 1 1 3 2 1 3 1 2 0 0 2 0 0 1 2 0 0 1 1 0 0 1 2 2 1 True False 表2.22 选项B的安全性检测表 进程Work Need Allocation Work+Allocation Finish 0 2 1 2 2 1 0 0 1 1 3 1 1 3 2 2 0 0 2 0 0 1 2 0 0 1 1 0 0 1 2 2 1 True False

操作系统实验报告

操作系统教程实验报告 专业班级 学号 姓名 指导教师

实验一WINDOWS进程初识 1、实验目的 (1)学会使用VC编写基本的Win32 Consol Application(控制台应用程序)。 (2)掌握WINDOWS API的使用方法。 (3)编写测试程序,理解用户态运行和核心态运行。 2、实验内容和步骤 (1)编写基本的Win32 Consol Application 步骤1:登录进入Windows,启动VC++ 6.0。 步骤2:在“FILE”菜单中单击“NEW”子菜单,在“projects”选项卡中选择“Win32 Consol Application”,然后在“Project name”处输入工程名,在“Location”处输入工程目录。创建一个新的控制台应用程序工程。 步骤3:在“FILE”菜单中单击“NEW”子菜单,在“Files”选项卡中选择“C++ Source File”, 然后在“File”处输入C/C++源程序的文件名。 步骤4:将清单1-1所示的程序清单复制到新创建的C/C++源程序中。编译成可执行文件。 步骤5:在“开始”菜单中单击“程序”-“附件”-“命令提示符”命令,进入Windows “命令提示符”窗口,然后进入工程目录中的debug子目录,执行编译好的可执行程序:E:\课程\os课\os实验\程序\os11\debug>hello.exe 运行结果 (如果运行不成功,则可能的原因是什么?) : (2)计算进程在核心态运行和用户态运行的时间 步骤1:按照(1)中的步骤创建一个新的“Win32 Consol Application”工程,然后将清单1-2中的程序拷贝过来,编译成可执行文件。 步骤2:在创建一个新的“Win32 Consol Application”工程,程序的参考程序如清单1-3所示,编译成可执行文件并执行。 步骤3:在“命令提示符”窗口中运行步骤1中生成的可执行文件,测试步骤2中可执行文件在核心态运行和用户态运行的时间。 E:\课程\os课\os实验\程序\os12\debug>time TEST.exe 步骤4:运行结果 (如果运行不成功,则可能的原因是什么?) : 步骤5:分别屏蔽While循环中的两个for循环,或调整两个for循环的次数,写出运行结果。 屏蔽i循环:

相关文档