操作系统课程设计完整

2022-11-17 版权声明 我要投稿

第1篇:操作系统课程设计完整

教务管理系统功能需求及系统课程数据完整性问题的探讨

摘要:本文主要针对教务管理系统的功能需求展开了分析,从信息管理、课程管理、成绩管理、教学计划四个方面入手并做出各自的模块设计,此外还对系统中最难攻克的数据完整性有关问题诠释了课程数据完整性的基本内涵,探究了课程数据完整性受到破坏的主要原因,并提出了保证课程数据完整性的一些对策。

关键词:教务管理系统 课程 数据管理 数据完整性

0 引言

当今的科技迅速发展,管理系统已经完全通过计算机实现,因此需要根据外界的不断变化来完善管理系统,设计适应其发展的数据库管理系统,提高其性能,完善其功能。通过计算机进行教务管理是现代化管理的必然趋势,现通过课程设计来实现一个较小的较为简单的教务管理系统,使得学校的教务管理人员可以更加高效地进行诸如制定教学计划、安排课表和教室及考试管理等活动。

1 教务管理系统功能需求

1.1 需求分析 为了高效率的教务教学的管理,满足对学生教师信息、学生成绩等的查询及其他相关操作的实现,决定开发设计教务管理系统,使教务管理工作系统化、规范化、自动化,从而达到提高管理效率的目的。使办公人员可以轻松快捷地完成教务管理的任务。具体分析如下:

学院包括理学院、人文学院、电信学院、计算机系、外语系等若干二级院系。首先,由各二级院系制定教学计划,由此得出开课计划,这样就有了排课的基本信息,即可生成课表;一个学期结束后,教师从网上录入成绩,系统自动对此数据进行统计和处理。辅助学生的评优工作。系统包括学生学籍管理、教师基本信息管理、Web成绩录入和查询、选课、考试信息发布等。

1.2 系统功能分析 教务管理系统是一个能够管理教师及学生信息的系统,除此之外,它还应该能够对学生及教师提供一定的查询功能,如:成绩查询、获奖情况查询、课程查询、毕业情况查询等。教务系统还应该对学生每学期的选课进行管理。具体功能可归纳为以下几点:①教务处以及各二级院系可以对在籍的每个学生的学籍,包括对学生的成绩、毕业、学生奖励及处分情况进行动态管理。②系统提供Web成绩录入和查询。③系统对学生选课进行管理。④对教师信息、教学计划进行管理、维护和调整。⑤通过此系统,进行考务管理。

1.3 系统相关图

图1 用例图

图1说明:UML的用例图较详细和确切地描述了用户的功能需求,使系统责任明确到位,奠定UML对系统建模的基础,这样,其他模型图的构造和发展依赖于用例图中所描述的内容,直至系统能够实现用例图中描述的功能。

图2 类图

图2说明:将该系统分为六个类:成绩管理、信息管理、教学计划管理(这三个类完成系统管理的三个主要功能,是三个管理模块)、二级学院、教师、学生。

图3 顺序图

图3说明:学院首先制定教学计划自动排课生成课表,学生可以登录系统进行选课;每次进行考试先由成绩管理系统进行安排,考试完毕教师将成绩录入系统,学生登录系统便可以进行成绩的查询;信息管理系统对学生信息的管理主要在学籍、奖励处分情况和毕业情况方面进行管理。

图4说明:活动图是UML中描述系统动态行为的图之一,它用于展现参与行为的类的活动和动作。图中的活动用圆角矩形表示。该图反映了各个类在不同时刻完成的操作。

2 数据完整性问题

2.1 问题的提出

高校在课程数据管理中存在着诸多数据异常错误或问题,主要表现在:

一是重复设课。在课程库中对实属同一门课程设置了多个课程号,造成在分年级、分专业教学计划中对同一课程引用了不同的课程号,导致教学运行环节中课程安排、学生选课、课程重修、考试安排、毕业审查等管理工作经常出现重复课程,需要进行课程替换或合并等杂乱情况。

二是课程信息维护不完全或不准确。对课程数据的一些关键属性,比如课程类型、学分、学时等,没有全面维护或维护不准确,导致其它子系统对课程引用发生偏差或错误。

三是成绩库中出现一课多学分并存或已修学分发生变化。课程管理员随意修改课程库中的课程学分,而成绩子系统对课程学分刷新或记载存在不同步的差异,导致成绩库中一门课程出现多学分并存或已修学分发生变化的学分不一致的情况。

四是数据表中出现无课程号数据。在教学计划、成绩、教学任务书等数据表中莫名出现有数据但无课程号的情况,这种情况是由于对课程库删除了被引用的课程导致,造成其它数据表中产生垃圾数据或异常错误。

种种问题的出现,造成教务管理系统中课程数据混乱或异常错误,严重影响着教务管理系统数据的准确性和系统运行效果。笔者认为,产生这些问题的主要根源在于高校对课程数据管理存在一定程度的随意性、盲目性,无论是系统控制还是业务规则都缺乏对课程数据完整性的约束。

2.2 课程数据完整性的涵义与约束

数据完整性约束一般包括三类:

2.2.1 实体完整性

实体完整性约束的目的是确保数据库中所有实体的唯一性,也就是不应使用完全相同的数据记录。实体完整性要求一个关系或表中主码的属性不能取空值,也不能有重复值,即一个元组(关系表中的一行或一条记录)表示唯一的实体对象。

2.2.2 引用完整性

引用完整性是用来维护相关数据表之间数据一致性的手段,通过实现引用完整性,可以避免因一个数据表的记录改变而使另一个数据表内的数据变成无效的值。

保证课程数据引用完整性要注意几个问题:

一是外码是否可以接受空值。外码能否为空是依赖于应用环境的,如上述成绩关系中的外码“课程号”。

二是删除课程元组时的考虑。有时想要删除课程库中一个元组,但存在引用关系中(计划、成绩等)若干元组的外码值与被删除的被引用关系中的元组主码值相对应,这时要进行级联删除,如果引用关系同时又是另一个关系的被引用关系则这种级联删除应该级联下去。

三是修改课程属性时的考虑。有时需要修改课程元组的某些属性,应注意的是,级联删除、级联修改是很危险的,可能涉及不同的业务管理范围,需经各方面的确认。

2.2.3 用户自定义完整性

任何关系数据库系统都应该支持实体完整性和引用完整性。除此之外,不同的关系数据库系统根据其应用环境的不同,往往还需要一些特殊的约束条件。

2.3 课程数据完整性受到破坏的原因

通过分析课程数据管理中存在的问题可以发现,造成课程数据完整性受到破坏,既存在系统功能不完善的原因,也存在人为操作不当的因素。

2.3.1 在客观上存在系统功能性的欠缺

该教务管理系统已提供了一些数据完整性的约束机制,但仍然存在严重缺陷,不能有效保障课程数据的完整性、可靠性。潜在的功能缺陷有:

一是缺少数据录入时的完整性检验。目前,系统除了对课程号录入时具有“不能为空”的检验外,并未对课程其它必要属性做出“不能为空”的定义。在添加数据时系统应通过程序控制确定课程必填项目,比如学时、学分、开课单位、课程类型等。

二是缺少对数据修改、删除操作的检验和级联处理。根据引用完整性的要求,课程数据一经被其它表引用,有些属性就是“不可变”的,而该教务系统在进行课程数据修改和删除时没有对该数据进行引用检验,更没有级联修改和删除的功能。有时系统缺乏对用户操作的规范控制,就可能造成非法数据进入数据库,这样数据完整性受到破坏就在所难免。

2.3.2 在主观上存在人为操作的随意性、盲目性

课程管理员在进行课程数据处理时,操作随意性大,对数据维护可能造成错误的“风险”意识不足,比如随意修改课程数据的学分、学时等关键属性;或随意删除课程数据;或数据信息维护不完整;或数据库管理员不经过应用程序,而通过数据库后台直接对数据库进行删除、修改和插入等操作,使得一些不符合缺省规则的数据进入数据库,破坏了数据的完整性。

2.4 保证课程数据完整性的对策

在绝大多数情况下可以利用系统提供的数据完整性技术来保证数据的一致性,使得数据处于正确的状态,然而它并不是解决问题的全部方法,也难以避免人为因素,还需要通过业务规则和操作规范进行控制。

2.4.1 强化应用系统对数据完整性的控制是保障数据完整性最有效的手段

强化课程数据完整性可以利用Oracle数据库系统自身提供的完整性约束与触发器功能和应用程序执行完整性检验等方法来实现。应用系统应提供一些限制规则,这些规则规定用户在对数据库进行更新操作时,系统按照制定的规则检验操作的合法性,若不符合规则需进行相应的错误校验处理。限制规则可以分为三类:①完整性约束。②触发条件。③违约响应。

2.4.2 建立业务规则是保证数据完整性的最重要保障

如果软件功能不能从源头上对数据质量进行控制,那么建立业务规则来强制数据完整性就成为最后的屏障。

首先,要科学设置课程编码。课程是以课程代码进行标识的,课程代码必须保证同一门课程仅有一个唯一的代码,遵循同一性原则。

其次,要提高管理人员的责任意识,遵守操作规范。由于系统未做到或不能完全做到对数据进行完整性约束,因此,必须通过强化操作规范进行行为控制,避免随意性、盲目性人为错误的发生。

3 结论

为了保证教务管理系统切实有效地工作,在需求分析阶段必须做到充分了解学校的工作实情和具体需求,对于教务管理的每一个环节都必须做到了解透彻,特别是基础数据的采集与准备。这样在做系统设计时才能使得后期的课程数据等得到有效的保障,从而从根本上解决系统存在的问题,达到充分提高教务管理工作效率的目的。

参考文献:

[1]方纪旋.高校教务系统(课程管理)的开发与使用中的若干问题[J].教育信息化,2002(7).

[2]汤娟等.数据库应用系统中数据完整性的研究[J].交通与计算机,2002(1).

[3]王能斌.数据库系统原理[M].北京:电子工业出版社,2000.

作者:王申,赵正德,陈盼

第2篇:完整课程:职业教育课程方向

摘 要 在职业教育领域,学科型课程被“颠覆”之后,工作导向型课程着实在提升岗位胜任力方面颇具成效,但由于拘囿于教育“二元论”的视阈,知识“不完整”、组织“不完整”与取向“不完整”问题持存。基于此,在揭示职业教育现有“课程三弊”基础之上,以联合国教科文组织提出的“培养完人”为目标,以现象学、哲学一元论等为依据,通过对普通教育、职业教育两个领域现有课程模式进行比较,并通过描述完整性、校本性与建构性特征,提出“完整课程”方向。其中,完整技术、完整师资、完整资源等构成其实现条件系列。

关键词 完整课程;课程范式;职业教育

学科型课程招致批判之后,俄罗斯制、国际劳工组织MES课程、北美CBE课程、德国学习领域课程等工作导向型课程逐一登陆中国,学科型课程在职业教育领域的主体地位逐步被替代。并且,这一态势渐从中、高职渗透至应用型本科人才培养体系之中。但是,现有工作导向型课程所培养的学生既未达到教育界自身的满意,也远未达到企业界的满意。事实上,该类课程虽然在一定程度上认识到工作知识的特殊性,深化了对职业教育基本问题的理解,并由此缩短了“学校—工作”之间的距离,但并未解决知识“不完整”、组织“不完整”与取向“不完整”三个课程维度的核心问题。由此,本研究提出“完整课程”的概念,以期回归职业教育课程改革的根本方向。

一、课程“三弊”

拉尔夫·泰勒于1949年出版的《课程与教学的基本原理》被誉为“课程编制的圣经”,围绕课程目标,选择课程内容、实施组织与评价构成了泰勒课程原理的四个核心环节[1]。即使之后施瓦布“实践模式”、斯腾豪斯“过程模式”、多尔“后现代模式”出现之后,泰勒所开创的“目标模式”在课程开发领域依然居于主导地位。职业教育DACUM与BAG课程开发技术即属于该范畴。但是,基于泰勒“目标模式”的职业教育现行课程内容、组织与取向上的“不完整”,直接消解了职业人才培养的“完整性”。

(一)知识“不完整”——三维分离

人类童年时期,教育一直镶嵌于生产生活的母体之中,知识以“具象”形式存在。经历漫长岁月的积淀,于奴隶社会早期,教育与母体分离,学校诞生并逐步成为与社会隔离的“象牙之塔”,知识则由学者群体从生产生活的母体中被“抽象”出来。该事件在人类发展史上从“正、反”两个方面都显得尤为重要。从正向看,“抽象”体现出“人之为人”的思维特质与智慧发展水平,尤其揭示出人类认识并改造自然的智力潜能。但思维“抽象”的结果遮蔽了人类本身固有的直觉能力,“身体”的认识功能在很大程度上遭致破坏,尤为可怕的是人类沿着这条道路越走越远。不难发现,从柏拉图“理念”至笛卡尔的“理性”路线对于人类理性精神的高扬,以及培根在《新工具》一书中提出的“科学归纳法”等对于思维“抽象”起到推波助澜的作用,甚至可以视之为知识“不完整”在哲学维度的宗脉源头。

事实上,培根“知识就是力量”中的“知识”已经完全不是“完整”知识,借科学家之手,知识在自然界与人类社会的整体“情境”中被“析出”之后,逐一被学科专家编撰在教科书之中,但知识经过系统化处理后,遂而变得更加“支离破碎”,主要体现在三维分离:其一,知性与物性分离。当“符号”本身以知识相命名时,本来嵌入生产生活之中的知识被“剥离”开来,知识“知性”与“物性”彼此割裂。在认识论上,尤其导致了人类拘囿于“知性”与“物性”的二元对立之中,自然无法逼近知识的本来面目,近代以主体和客体、内在心灵与外部世界相分离为特征的表征主义认识论危机主要源于此[2]。另一方面,“知性”与“物性”分离消解了“完整知识”本身的“完整”力量,这即是因何卡拉赫和斯屈理曼所描述的“巴西男孩”在街头兜售物品时可以自如地运用数学,而离开市场同样简单的数学却一无所知之故[3]。其二,命题之知与能力之知分离。“知性”与“物性”分离迁移至认识主体“人”身上,遂演变为命题之知(Knowing That)与能力之知(Knowing How)分离。在认识论领域,威廉姆森与赖尔早在20世纪中期即就此命题展开了“理智主义”与“反理智主义”的热辩[4],引人关注的事实是,脱离“物性”的“知性”部分即“命题之知”直接传输至受体,无法自然转化为“能力之知”,换句话说,习得命题性知识之后,并无职业胜任力。正如一位棋手棋谱背得娴熟但棋艺可能拙劣,一位厨师熟记菜谱甚至不会烹饪一样。其三,明言部分与默会部分分离。1958年,波兰尼在《人的研究》一书中指出,人类有两种知识,其中,以口头、书面或地图、数学公式来表达的部分为明言知识,不能如此系统表述的部分为默会知识[5]。二者比较,明言知识符合语言逻辑,默会知识则是前逻辑、前语言的知识。由于默会知识一般内化于“行动”之中,所以学校本位职业教育更多关注了知识的明言部分,而在工作本位职业教育中,对于明言部分则出现了部分疏漏与缺失。

知识“不完整”在课程中通常表征为:重视知性,疏略物性;重视命题之知,疏略能力之知;重视明言部分,疏略默会部分。另外,还有伯恩斯坦指出的:重视“垂直话语”,轻视“水平话语”等。甚至可以说,在学校形式的职业教育中,一直在传播知识的“一半”,可想而知,一个掌握“不完整”知识的主体不可能适应这个完整的世界,也不可能成为一个“完整”的人。

(二)组织“不完整”——三类碎片

现实中,错误在知识“不完整”处并没有就此止步,这些“不完整”的知识继续以“不完整”的组织方式“堆积”起来。“结构决定功能”,知识组织方式甚至比知识本身更为重要。只有按照知识之间内在逻辑构建的知识体系,才可使知识元素活化,从而挥发出知识固有之力。“不完整”知识以“不完整”组织的直接结果是对于结构力量的消解。事实上,以学科逻辑编制的课程体系一直重复着“不完整”的组织方式,最终使知识深度“碎片化”。

组织“不完整”主要表现为三类碎片。其一,科目碎片。科目碎片指组成课程体系的单科课程之间因关联度低,彼此成“碎片”之状。尽管主知主义代表人物赫尔巴特已为课程体系设置了“相关”与“集中”原则[6],事实上,单科置课已将完整的生活割裂为许多“片段”,如杜威所批判的:“世界是整体的,而每门课程只是把积聚的知识片段教给学生。”[7]CBE课程、学习领域课程、项目课程只是推进了“专业课程”的系统化设计,通识课程、专业基础课程则尚未触及。其二,模块碎片。模块碎片,即模块内部课程之间、模块之间因关联度低,彼此呈“碎片”之状。事实上,模块源自一物理学概念,指能够单独命名并独立完成一定功能的程序语句的集合。与之比较,课程体系虽有“模块”划分之名,却无“模块”特性之实。如应用型本科通识模块中的德育课、信息技术基础、英语、体育等课程之间,并无内在的、知识组织层面的关系。再有,“通识课程、专业基础课程、专业核心课程、专业方向课程”四个模块之间既不是学科逻辑,也不是工作逻辑。如果是学科逻辑,各模块之间在知识组织上需有严密的衔接,事实上显然没有,距离工作逻辑则更远。其三,体系碎片。即“学科”与“技术”两个体系之间的彼此分离。单科课程组成模块,模块聚合成整个课程体系。课程体系主要是学科知识“碎片”的松散聚集,而知识“碎片”只适合于存储与记忆。但是,职业教育与岗位胜任力相对应,“学会工作”是其本质诉求,以知识“碎片”组成的课程体系与实际工作体系之间存在着一道很深的鸿沟。职业教育传授的是技术知识,因此,如何组织技术知识成为职业教育课程开发的首要问题。另外,显性课程与隐性课程分离问题也十分严重,如校园文化中丝毫没有职业文化的渗透等。

或许是由于难度所致,与知识“不完整”比较,组织“不完整”问题的研究与解决甚为缓慢。的确,完整的组织方式是对学科体系的彻底颠覆,代之以技术体系梳理各种类型的知识,并且这种组织方式直接对师资与课程资源提出特殊的条件,但是,回避难点恰恰可能偏离课程改革的根本方向。

(三)取向“不完整”——三种偏失

课程蕴藏的信息是丰富的,除知识问题、组织问题之外,课程取向也甚为重要。美国课程专家派纳在《理解课程》一书中曾将课程比作政治、种族、传记等各类文本,就此诠释出课程所折射的功能要旨。就职业教育课程而言,由于过分适应产业界需求,或重点关注了岗位胜任力的培养,直接导致课程模式变革中“人”的偏失,从而背离了教育的本质需求。

取向“不完整”主要体现为三种偏失。其一,主体性、个人性偏失。自有学校教育以来,课程权利从来不属于学生,即使有选修模块,也是由学科专家假想而成。课程目标、课程内容、课程组织与课程评价四个环节,都是施教者既定的,处于受体位置的学生只得被动进入该课程框架。问题在于,课程不是一个静态的内容拼凑,而是学生积极参与建构的活动,没有学生嵌入其中的“既定课程”甚至不是“真正”的课程;另一方面,学生个体不同,应有各自适切的课程内容,即“个人课程”。孔子曾提出的“因材施教”原则不仅是教法问题,其中还有内容的元素,在现实中至今远未达到。其二,发展性偏失。当前盛行的课程模式,只是提升了技能习得的效率而已。少量的数学、文学内容既没有体现与专业的整合,又没有体现该类学科固有之“美”,“哲学”“史学(职业史)”类内容则基本从未进入过职业教育课程范畴。学界惯常以课时局限、学生基础差、技能至上等诸多理由将其拒之门外,但无论做何解释,在成长历程中,青年学生因此失去了一次在“发展意识”层面被“激活”的机会,因为哲学使学生得以“启蒙”,史学(职业史)使学生走向“自觉”。如此职业教育很可能成为杜威所忧虑的,即“维护既定的生产方式,重复惯常的秩序,顺应现有工业制度的工具”[8]。由此看来,因“发展性”而占用学时是值得的,只是“发展性”内容以何种方式呈现,以及教师能否将该类课程讲好是关键。其三,本土性偏失。由于近代中国走向“被现代化”的历程,包括职业教育在内诸多的学科出现“横向借鉴过多,纵向传承过少”的严峻问题,就课程而言,目前盛行的课程模式皆舶自西方。职业教育本土元素越来越少,“职业教育的中国话语”严重缺失,甚至可以说,中国传统职业教育范式中所彰显的原创力即将消失殆尽。

“主体性、个人性”偏失旨在回归学生在课程系统中的“应然”地位,显然,泰勒“目标模式”在职业教育课程领域的“霸权”时代已经过去,“个人课程”有待进入课程专家的视阈。而“发展性”偏失已被各国职业教育界在不同程度上进行修正,美国STC运动(从学校到生涯运动)即是典型一例,只是该问题尚未进入职业教育实践界的“焦点视域”。比较而言,“本土性”偏失尤为严峻。必须“割断”照搬西方的惯性,把回归职业教育本土原创的轨道,创制与中国本土相契合的课程模式视为重要使命。或许,在知识“不完整”、组织“不完整”问题未解之前,学界无力去深入探究取向“不完整”问题,但作为课程的重要元素,“取向”是不可或缺的。这也是职业教育是否具备“教育自觉”的重要标志。

二、“完整课程”释义

“完整课程”是针对“不完整”现实而提出的。事实上,在另外维度上也多有“不完整”之处,如课程目标“不完整”、课程资源“不完整”等,课程“三弊”只是其中三个根本痼疾而已。通过特征剖析与课程比较,可以进一步理解“完整课程”要旨。

(一)特征视角

1.完整性

1861年,斯宾塞在名著《教育论》中将“完满生活做准备”视为教育目的,并由此演绎出由五类科目组成的课程体系[9]。时隔百年,联合国教科文组织于1972年编著《学会生存——教育世界的今天和明天》一书,基于“人”的分裂困境,提出“培养完人”的教育理想,即“把一个人在体力、智力、情绪、伦理各方面的因素综合起来,使他成为一个完善的人,这就是对教育基本目的的一个广义界说”[10]。目标决定内容,培养“完人”自然需要“完整性”课程,职业教育如是。

“完整性”包括三个核心词语,即“完整”“整体”“一体化”。其一,“完整”主旨要素层面,即没有“核心元素”缺失,以及核心要素中没有“核心部分”缺失的“完整”。基于教育学原理中“完人”目标要求,重点补充知识、组织与取向三个维度“不完整”部分,使“完整课程”成为职业教育课程开发的主导理念,超越以要素、组织、取向等单一维度为起点的课程开发范式。其二,“整体”主旨结构层面,即消除“二元”对立的“整体”。基于对教育“二元论”批判,消除身与心、理论与实践、具象与抽象、知性与物性等传统“二元”对立的教育哲学。以杜威教育“一元论”为依据,使“完整”元素得以“整体”重构。以知识为例,即由知性与物性、明言部分与默会部分、命题之知与能力之知等“半体知识”达至“整体知识”。其中,范例、叙事、行动等为其提供了框架。其三,“一体化”主旨课程组织的“一体化”。尤须消除科目碎片、模块碎片与体系碎片问题,使“完整”的课程要素形成“整体”的课程结构,最终构建出内在关联的“一体化”课程体系。

比较而言,“完整”主旨要素指范畴是否亏缺,“整体”指向要素存在状态,“一体化”则指向课程组织。需要指出的是,“完整”以“完人”为前提,“整体”以教育“一元论”为基础,这些看似是教育的“乌托邦”,但或许恰恰是教育存在的合理性之所在。

2.校本性

在“完整课程”理念之下,课程方案应呈现“多样性”。换句话说,课程不是既定的,也不是一成不变的。其中,校本性是达至“多样性”的自然选择。但是校本性须服从“完整课程”理念,不是一种“任意”或“偶然”的文本编撰。

校本性通过三个维度予以体现。其一,物本层面。可以说,“完整课程”一定是校本的。任何一个给定的课程体系对于一个在资金、资源、环境、需求等方面具有特殊性的学校而言都具有不“适切性”,所以皆是“不完整”的。“校本”蕴含着独特、开发之意,即因为“独特”所以“开发”。因此,“完整课程”一定不是照搬的结果,而是围绕学校现实状况“开发”的结果。其二,师本层面。如果没有师资团队的二度开发,“完整课程”文本依然是“惰性的”,该层面开发是专业师资团队与“完整课程”文本互动的过程,其间,可有内容增删,也可有部分重组,之后,原有课程文本被“激活”并被“重构”。其三,生本层次。以“学生为本”是关乎是否为“完整课程”的重要标志。由师资团队再度开发的“完整课程”文本依然不是“完整课程”的终结。学生接受的不是教师“抛给”的既定内容与形式,而应以主体身份参与至课程开发甚至实施过程之中,而后决定自己学什么、怎么学等教育的基本问题。

惯常看来,物本层面、师本层面课程开发可以理解和接受,但对于学生参与其中有颇多疑问,在一定意义上,一个学生能决定自己学什么,并且知道自己学什么时,教育才真正开始。学生深度参与是一个繁难的过程,但确是一个不可回避的过程。否则,课程将成为一个“没有主体”的课程,培养自觉意识、学习能力、创造精神与发展品格等只能是空中楼阁。另外,校本性既是本土性的实现路径,也是本土性本身。

3.建构性

“完整课程”不是通过灌输而是通过建构完成的。比较而言,学科型课程所恪守的“客观知识”成为“施者—受者”之间直接灌输的知识论前提,在此无需谈论波兰尼等“个人知识”论者对于“客观知识”的质疑,有一点已在学界取得共识:即便抽象出来的“客观知识”是正确的,也属于“惰性”知识范畴,赖尔将其比作“博物馆式的拥有”(museum poossession)。如果转向“工作坊式的拥有”(workshop possession) [11],定然不能脱离主体在情境中进行自我建构。

“建构性”需满足三项条件:其一,“现象学”课程载体。破解“知性与物性、命题之知与能力之知、明言部分与默会部分”分离问题,必须提供范例、叙事、行动、情境等“现象学”意义上的课程载体。其中,项目最为典型。但是,项目不能做一般意义的理解。借助“现象学”原理,将在生产实践中具有代表性的项目,通过“现象学还原”,成为一个虚拟的“真实”项目,如此,则在该类“现象学”项目中实现“抽象”与“具象”、“知性”与“物性”、“要素”与“情境”、“主体”与“客体”的统一,而不是通过归纳探究一般性规律,进而解决特殊性问题,而是追求“特殊性”与“一般性”的同一。其二,新手—专家逻辑。打破学科型课程单科置课并按知识难易逻辑组织课程的范式,依据“德莱弗斯模型”中从新手到专家秩序规则,将“现象学”取向的案例、叙事、项目等序化,使主体在自我建构中推进课程完成。其三,课程共同体。平等性是自主性的前提,自主性是实施成功建构的条件。因此,变革了传统师生“施者—受者”线性关系,师生课程共同体得以形成。在共同实践、共同感受、共同对话过程中完成课程。

建构性与完整性、校本性是相互关联的,完整性是前提,校本性是途径,建构性则是完整性、校本性的核心体现。需要注意的是,不是有一个由校本开发的、满足完整性的既定的“完整课程”拿给学生去“建构”,相反,“建构”本身即是“完整课程”的有机组成部分。

(二)比较视角

在普、职两个教育领域,有一些课程模式与“完整课程”名称、内容或特征有相似之处,如包括整体课程、综合课程等在内的学科变革型课程、包括CBE课程、学习领域课程等在内的工作导向型课程,都在不同程度上缓解了“课程之弊”,但与“完整课程”比较,从理念到内容皆不尽相同,否则就没有提出“完整课程”概念的必要。

1.与学科变革型课程比较

在学科变革型课程中,综合课程、广域课程、整体课程等最易与“完整课程”相混淆。研究表明,解决单科置课与世界整体性之间的矛盾冲突,成为该类课程的逻辑起点。其中,综合课程(comprehensive curriculum)打破了学科课程的知识界限,经过学科融合而成科际课程、多学科课程和跨学科课程等。广域课程(broad curriculum)、一体化课程(integrated curriculum)等20世纪中期之后出现的课程与综合课程异曲同工。事实上,这三类课程在一定程度上缓解了课程组织“不完整”的问题。但是,对于知识“不完整”与取向“不完整”问题尚未提及。

20世纪80年代末期,整体课程(holistic curriculum)逐步兴起。该课程范式超越了综合课程、广域课程与一体化课程关注课程组织是否完整的单一维度,基于整体主义观,凸显联接、转化与超越的整体思维,从而消解传统学科课程中的“二元”对立问题。比较而言,整体课程在消解“二元”对立维度上与“完整课程”基本一致,如二者都反对理实分离、身心分离、主体与内容分离等。但不同之处在于,“完整课程”不仅揭示出课程结构的“整体”取向,尤其对于现有课程组成元素“不完整”之处具有自觉意识,换句话说,“完整课程”首先解决内容“缺什么”,然后再解决结构的“整体化”,“整体课程”则主要指向后者,并且主要是在基础教育领域进行探究的成果。

事实上,从综合课程到整体课程尚未改变学科型课程之根本属性,因此,与职业教育相对应的岗位工作任务分析方法、与培养职业能力相关的技术知识等内容并未囊括其中。与之不同,“完整课程”沿袭了工作导向类课程对于学科型课程变革的路线,只是CBE课程、学习领域课程变革中的逻辑起点、内容、目标等方面已被超越。

2.与工作导向型课程比较

在职业教育领域,对于学科型课程批判的结果是工作导向型课程纷纷出台。在一定意义上,CBE课程、MES课程、学习领域课程、项目课程等推进了知识“不完整”、组织“不完整”等问题的解决。但与“完整课程”相比,知识“完整”与组织“完整”的目标尚未达到,尤其在逻辑起点与取向方面尚存差异。

CBE(Competence-based Education)课程在职业教育课程史上具有里程碑的意义,该课程模式最早可以追溯到“一战”时期,由“美国职业教育之父”普洛瑟与其亲密战友、职业教育专家查尔斯·艾伦领导的“工长会议计划”中的“工作任务分析”方法[12]。“二战”时期的美国,这种方式同样用于对技术工人进行再培训,使之掌握枪弹制造等技能[13]。自此,“工作任务分析”成为职业教育课程开发的核心技术环节。20世纪中期,美国师范教育遭致批判,该领域遂而吸收并深化了传统“工作任务分析”方法,按照岗位能力标准设计课程始在师范教育中实施。之后该思想传至加拿大,并逐步形成了以DACUM为核心的CBE课程。值得一提的是,该课程范式中“能力”概念综合了知识、技能、态度等多种要素,打破了学科体系中知识、技能、态度分离之状。遗憾之处在于,与学科课程比较,CBE课程使课程要素趋向整合,但职业能力分析已经“破坏”了工作本身的完整性,而工作过程知识、整体性思维等元素“缺失”最终使CBE课程呈现出“不完整”状态。另外,CBE课程虽然在一定程度上考虑了学生学习的自由度,但距离“个人课程”、“发展课程”要求还有较远的距离。

项目课程(project curriculum)源于美国教育家克伯屈设计教学法,目前在职、普两个教育领域,初、中、高多个教育层次盛行。与整体课程相比,二者都受到杜威的影响,都是教育“一元论”在课程上的演绎。简而言之,“项目课程”是“整体课程”中的一种形式。与“项目教学”不同,项目课程是包括项目理念、开发技术、项目选择、项目序化、项目教学等在内的逻辑清晰的整体。尤需指出,徐国庆教授在对项目课程进行深度研究过程中,使之注入了本土元素,融合了技术哲学、学习心理学、认识论思想,并形成了完整的课程开发技术和课程模式。但是,中国本土项目课程有将原初项目课程“窄化”的迹象。与“完整课程”相比,职业教育领域中的项目课程是基于对工作任务课程的批判,主要为解决“理实分离”问题提供了框架。项目课程中“抽象”与“具象”知识融合体现了“完整课程”特点,这也是CBE课程、学习领域课程未曾探究的。但是课程是否“完整”尚未提及,尤其是,对于项目在超越“表征主义认识论”的“现象学”意义上并未挖掘。

学习领域课程(learning field curriculum)是德国职业教育课程改革的结果。事实上,德国职业教育也受到了杜威的影响,20世纪初期,在德国职业教育史上举足轻重的教育家凯兴斯坦纳访美,之后在《劳作学校要义》一书中对于杜威“把实践兴趣尽可能作为课堂活动中心”等命题即有明确的阐述[14]。自此,技术课程开始成为德国职业教育的重要内容,并注意到操作技能与心智技能的融合。20世纪90年代末期,针对德国本土课程学科化倾向越来越严重的现实,基于对国际劳工组织MES课程、北美CBE课程对于职业能力精细划分的扬弃,学习领域课程被提出,并着实考虑了典型工作任务的“整体性”,以“对象、工具、方法、组织、要求”等要素还原真实生产情境,并且,课程理念从操作导向转至设计导向,知识“完整”、组织“完整”在一定程度上有所体现,课程“完整性”得以提升,但“学习情境”设计停留于一般意义的描述,并未体现出对象、工具、方法等课程要素“具象”与“抽象”的融合,而该细节恰恰是课程难点之所在。另外,学习领域课程在注重综合职业能力培养的同时,对于课程的“个人性”“发展性”等问题探究不足。与项目课程类似,在“现象学”意义上,本应有更为丰富内涵的“学习情境”尚未被自觉认识到。

再有,盛行于美国的职业群集课程对于相关职业领域共通的基本知识、技能进行了系统化设计,乍一看来有利于学生未来的职业迁移,但这种推断只是以官能心理学与领域一般性理论作为理论依据的,如果基于习惯心理学和领域特殊性理论,职业群集课程的合理性当招致质疑。

通过比较旨在理解“完整课程”,不是否定时下盛行的课程模式,尤其不能否认各个课程模式在职业教育课程史上的特殊意义。但作为历史的产物,每一个课程模式定然存在着某种程度的局限性,这也是职业教育课程改革“一直在路上”的原因。提出“完整课程”理念,一方面旨在表明职业教育课程已到“全面改革”的历史阶段,另一方面需汲取已有课程模式的合理内核,创制出契合中国本土的新模式。

三、“完整课程”条件

“完整课程”是一种课程理念,更是一种课程实践。自然,与学科型课程、现有工作导向型课程相匹配的条件已无法适应“完整课程”的要求,其中,课程开发技术、课程资源与课程制度等方面尤需变革。

(一)完整技术

“完整课程”需“完整技术”。目前,职业教育领域盛行两种课程开发技术,即北美DACUM与德国BAG技术。二者皆属于泰勒“目标模式”范畴,DACUM与BAG技术相同之处即二者都起于岗位工作任务与职业能力分析,不同之处在于DACUM将完整任务“切割”成支撑其的“知识、技能与态度”模块;BAG则将典型工作任务“析化”出包括“对象、工具、组织、方法、要求”等在内的“学习情境”。在汲取二者合理内核基础之上,提出“完整技术”并对其进行一般性的描述。

“完整技术”主要包括以下三个步骤:其一,校本层次—项目还原。以课程专家为指导,融合学校与企业实践专家,通过“实践专家研讨会”形式,实施典型工作任务与职业能力分析,与传统课程开发不同,实践专家研讨会就此没有停止,适当延长会议时间,继续将“典型工作任务—职业能力—知识、技能、态度”还原成“现象学项目—职业能力—知识、技能、态度”,还原结果是,“典型工作任务”成为“现象学项目”,“知识、技能与态度”则完全“具体化”了,即“嵌入”典型工作任务之中的“知识、技能与态度”。除此之外,还包括与之相关的范例、叙事文本、情境等其他“现象学”课程载体的开发。其二,师本层次—集体审议课程—认知学徒范式。借鉴施瓦布“课程审议”方法,以一个“现象学项目—职业能力—知识、技能、态度”为单位,由以往分别担任通识课、专业基础课与专业课教师组建“共同体”实施“集体审议”,最终形成“集体审议课程”[15]。该课程包括两个要点:一是融合必需的教育“元素”,换句话说,即将“真实”项目设计成为具有教育学意义的“虚拟”项目;二是各位教师明晰各自的课程任务,并明确与整体课程之关系,如何与其他成员配合,尤其是基于从新手到专家次序,编制出符合“认知学徒范式”的课程与教学框架等[16]。其三,生本层次—个人课程。将集体审议课程与学生“见面”,在师资团队与学生个体“平等对话”中,根据学生特长、取向、兴趣等元素,“商议”学生个体课程部分,最终形成初步的“个人课程”。诚如必修不仅是教师的权力一样,选修也不仅是学生的权力,基于二者各自的局限性,应以“平等对话”的形式决定。

事实上,“完整技术”在扬弃DACUNM与BAG两种技术基础之上,融合了现象学、教育“一元论”、认知学徒制等理论要旨,其间尤其彰显了“设计性”, 校本层次、师本层次与生本层次都需要主体参与设计,甚至可以说,没有设计即没有课程,或言没有设计即没有教学。

(二)完整师资

职业教育组织方式的变革直接影响了师资的规格,显然,学徒制被学校制替代之后,现代“教师”与传统“师傅”之间已经出现甚多差异。在传统学徒制中,学徒所学一般皆来自师傅一人,师傅即该行业的“全才”,但学校制中“单科置课”使传统学徒制中“全才”式师资难以出现,而这恰恰是“完整课程”所不可或缺的,即“完整课程”需“完整师资”。

“完整师资”有两层涵义:其一,针对于个体而言的“完整师资”。师资一般以科目划分,即一门课程一名教师。试想,既然教师自身无法谙熟专业必备的“所有知识、技能”,而试图通过学生个体将来自不同教师的学科知识、技能予以整合、转化,“效果如何”在教育实践中已经明了。与之不同,“完整师资”则要求教师个体需掌握完成工作的所有知识、技能与态度,否则以此标准要求学生是苛刻的,并有悖于教学规律。其二,针对于团队而言的“完整师资”。一般而言,虽然必要,但要求教师个体掌握一个专业的所有知识、技能的确存有困难,所以提出团队型“完整师资”,即在具有教育学意义的“项目”序列中,一个项目对应一名教师,“完整师资”难度则从专业水平降至项目水平,要求教师需尤擅该项目。甚至,一个项目由一个师资团队共同完成。尽管并未达到“完整师资”要求,但已超越了以学科划分师资任务的传统框架。

目前,个体型“完整师资”甚少。但是培养个体型“完整师资”既有必要性也有可行性,传统“师傅”角色已经为现代职业教育师资培养提供了范例。尽管现有知识、技能在难度、总量上皆与手工时代不可同日而语,但职业工作的“整体性”对于职业教育“完整师资”要求的总体原则是不可偏离的。换句话说,与“团队型”相比,“个体型”的“完整师资”才是职教师资“专业化”的方向。

(三)完整资源

依据“完整技术”所开发出的“完整课程”是单维的,除“完整师资”参与之外,课程实施还须以“完整资源”做支撑。完整空间、设施、材料等是其中的核心组成。

与传统教室比较,目前“理实一体化”的实训室、实验室与教室已经大大进步,但传统师资被“完整师资”替代之后,传统教学被“认知学徒范式”覆盖之后,满足知识完整、组织完整与取向完整的教育资源还尚存差距。建设原则如下:其一,依据“完整资源”理念,构建包括空间、设施与材料等要素在内的资源体系,并实施系统化设计。其二,满足该专业所覆盖的所有项目要求,即利用该资源完成专业所涵盖的所有项目实施。其三,与“完整课程”配套的资源体系(包括培养方案、课程标准、校本教材、教学方案、考评方案等文本及软件)需与现实生产方式变革、生产力要求相呼应,并持续提升水平。

除此之外,还有一些资源也需注意,如完整文化问题,如何在校园文化中使学府文化与职业文化融合是目前一个重要课题,事实上,作为“隐性课程”的组成部分,完整文化是“完整课程”的重要体现。

(四)完整制度

单有实体层面的“完整资源”还无法支撑“完整课程”的顺畅运行,“完整课程”需“完整制度”,其中,政策与机制保障尤为重要。

“完整制度”主要包括三个层面,其一,课程开发制度。由于课程的重要地位,课程开发自然举足轻重。一直以来,中国职业教育界课程开发只是少数学者所为,近期甚至演变为由教育公司承担的商业行为。尽管由少数课程专家指导的课程开发推进了职业学校课程改革,但整体上没有一个完善的制度,更无国家标准。在没有制度约束情况下,没有权威课程专家团队“集体参与”的课程开发参差不齐,从国家层面制定课程开发制度,并组建课程开发团队实属必要。其二,校企合作机制。“校企合作”是职业教育成功与否的核心条件,没有深度“校企合作”,或没有“校企一体”作为支撑,“完整课程”将难以实现,这是职业教育“跨界”属性所提出的必然要求。其三,课程政策导向。政策对于课程模式推行至关重要。如,北美CBE课程、德国学习领域课程与项目课程在中国“三分天下”,一方面是学者群体的影响,但主要是政策背后之力的推动。“完整课程”推行如是。

“完整制度”是对于“完整课程”的呼应,尤其要从“完整课程”理念去构建制度体系,但是对其不要做机械的理解。事实上,制度总是在完整过程之中。

四、“完整课程”思考

(一)必要性中的复杂性

彻底解决课程“三弊”,推行“完整课程”是必要的,但是该工程尤为复杂。首先,需熟练掌握与之相关的理论,尤其要将现象学理论、复杂性理论、哲学“一元论”、知识论等繁难理论迁移至职业教育课程领域,并融合其中更非易事。第二,需要探索并掌握与之切合的“完整技术”。目前严格掌握DACUM与BAG技术的学者在国内尚且不多,以二者为基础,探究并使更多人掌握超越传统方法的“完整技术”则需更长时间。第三,需要与之匹配的“完整资源”与“完整制度”。并且,这些并非职业教育一己之力可为,难度可想而知。试想,如果一件事情确实必要,但十分复杂是否就此停止呢?选择止步是一种惯常化思维,关键要看复杂性中蕴含的价值有多大。

(二)复杂性中的合理性

传统教育似乎是简单的,甚至一本书、一根粉笔、一个黑板或一个PPT即可。但无时无刻不在招致批判。所以,教育史成了教育批判的历史。在普通教育领域,美国作家丹尼尔·科顿姆在《教育为何是无用的》一书中列举的“因为它打破了我们的常识,它让我们丧失了人性以外的东西,它让我们的心变得麻木……”等虽有偏狭之嫌的确又引人之思[17]。在职业教育领域,20世纪中期经济学家福斯特《职业学校之谬误》一文中“企业本位在职培训优于正规职业学校”的著名论述,最终引发了世界银行从支持南非职业学校转向支持企业培训[18]。职业教育本不是一个简单的事情,“简单化操作”尤其可使其失去存在的合理性。即便如此,教育界都不肯向“复杂性”方向迈上一步,或稍一复杂即质疑其可行性。事实上,“复杂性”当属教育的“新常态”。或许,“完整课程”的复杂性中恰恰蕴含着其存在的合理性,这也是职业教育接受批判之后自觉反思的结果。

(三)合理性中的可行性

具有合理性的事物一般具有可行性,只是二者之间不是简单的“线性”对应关系,技术、资源、师资、适应等条件成为可行性的保障。如何理解“可行性”也尤为必要。就“完整课程”而言,在此强调三点:其一,“完整课程”理念刚刚提出,与之相关的文本、实体、制度等诸多维度的事宜尚待深度研究,系列成果尚需时间;其二,根据“完整课程”校本性,尤其是难度问题,可以将“完整课程”分层开发实施,如此使之成为一个持续研究的过程,也是一个在不同水平持续实现的过程;其三,在实践中鉴别优劣。对于“完整课程”理念可以有论争,但是要允许有研究的空间、有实践的探索,而不只是止于理念层面。

提出“完整课程”概念,既是职业教育遭致批判之后的一种自觉,又是中国本土课程理论与模式创制的使命使然。需要注意的是,“完整课程”作为一种理念甚至比作为一种课程模式更为重要。作为一己之见,或由于篇幅所限,其间思想可能尚未论述清晰,也不乏疏漏之处。“完整课程”框架或许会招致更多批评,但是研究在汲取批评者的有益元素之时,依然会朝向“完整课程”的理想。

参 考 文 献

[1][美]威廉F.派纳,威廉M.雷诺兹,等.理解课程[M].张华,译.北京:教育科学出版社,1999:32-33.

[2][4]郁振华.人类知识的默会维度[M].北京:北京大学出版社,2012:69-71.

[3]Anderson,J.R.,Reder,L.M. and Simon,H.A. Situated Learning and Education. In Smith,P.K.and Pellegrini,A.D. Psychology of Education[M]. London and New York: Routledge Falmer, 2000,Vol.Ⅱ,255.

[5]邓线平. 波兰尼与胡塞尔认识论思想比较研究[M].广东:知识产权出版社,2008:49.

[6][9]吴式颖.外国教育史教程[M].北京:人民教育出版社,2009:325,384-385.

[7]Dewey, J. Democracy and Education[M].New York: Macmillan, 1916:195-196.

[8]Marvin Lazerson, Norton Grubb. American Education and Vocationalism: A Documentary History: 1870-1970[M].New York: Teacher College Press, Columbia University,1974:37.

[10]联合国教科文组织,编著.学会生存——教育世界的今天和明天[M].陈科美,金冬日,等译,北京:教育科学出版社,2009:192-193.

[11]Gilbert Rlye, Knowing How and Knowing That[J].Proceedings of the Aristotelian Society, Vol.46,1946:4-16.

[12]王川.西方近代职业教育史稿[M].广州:广东教育出版社,2011:451.

[13]沈勤.能力本位教育适用性问题[J].外国教育资料,1996(3):36-41.

[14][德]凯兴斯坦纳.劳作学校要义[M].郑惠卿,选译.北京:人民教育出版社,2004:22.

[15]施良方.课程理论——课程的基础、原理与问题[M].北京:教育科学出版社,1996:198.

[16]Collins,A.,Brown,J.S.,and Holum,A. Cognitive Apprenticeship: Making Thinking Visible[J].American Educator.1991,15(3):38-46.

[17][美]丹尼尔·科顿姆. 教育为何是无用的[M].仇蓓琳,卫鑫,译.南京:江苏人民出版社,2005:1-15.

[18]石伟平.比较职业技术教育[M].上海:华东师范大学出版社,2000:244.

Full Course: Reform Direction of Vocational Education Course

Lu Baoli

Key words full course; curriculum paradigm; vocational education

Author Lu Baoli, researcher of Hebei Normal College of Science and Technology (Qinhuangdao 066004)

作者:路宝利

第3篇:中小学应进行完整系统的交通知识教育

交通法规和交通安全知识,是社会生活中我们必须掌握的常识。而当今社会,在义务教育阶段进行交通法规和交通安全知识的系统教育是十分必要,也是十分可能的。

一、在中小学进行完整系统的交通法规和交通安全知识教育的必要性

1.交通事故发生的主要原因

据新华网记者姚玉洁2008年5月25日报道,目前,中国约拥有全世界2.5%的汽车,然而引发的交通死亡事故却占了全球的15%,已成为交通事故多发国家。据不完全统计,2007年中国共发生交通事故32.7万起,造成8.2万人死亡,38万人受伤,直接财产损失高达12亿元。按发生事故的原因分析,驾驶员违章占70%-80%,机动车机械故障原因小于5%,道路及相关设施占1%,行人违章占15%。可见,驾驶员和行人违章是导致交通事故的最主要原因。

这就表明,中国因驾驶员和行人违章导致的交通事故约占总数的九成。因此,普及交通法规知识,让机动车驾驶员、非机动车驾驶员、行人懂得并掌握这些常识、遵循这些常识是非常必要的。这不仅仅是交通管理部门的事,更是整个社会的事,也是教育部门应该担当起的主要教育职责和教育任务。

2.在中小学进行完整系统的交通法规和交通安全知识教育的必要性

人教版小学四年级上册《品德与社会》教材第24页告诉我们:“国家少年儿童安康计划公布的数据显示,我国少年儿童因安全事故、食物中毒、溺水等死亡的,平均每天有40多人。”取40至50的中间值45,也就是每年约有1.6万名少年儿童(绝大部分为中小学生)非正常死亡,其中在交通事故中死亡的人数占的比例相当大。通过对这些事故的全面、深入的分析,专家们认为,通过安全教育,提高中小学生的自我防护能力,80%的意外事故是可以避免的。也就是说,每年因缺乏安全常识,缺乏自我保护能力无辜死亡的人数达1.28万人。不客气地说,每年1.28万少年儿童是被社会的无知、教育的无为害死的。这说明,在中小学进行完整系统的交通安全、交通法规知识教育是多么必要和迫切啊!

交通安全知识教育是生命教育的一部分,注意交通安全不仅仅是驾驶员的事,更是全体公民的事。全体公民,特别是少年儿童都有接受这种教育的必要,都有了解、掌握这些知识的权力。每个人都有权关注自己的安全,有权珍惜自己的生命,而且应该具备让自己受伤害的可能性降至最小的能力。了解掌握了这些知识,并严格遵守这些规则,我们的安全就多了一分保障,我们的健康就多了一分呵护,我们的生命就多了一分尊严。交通规则、交通安全知识教育是公民教育的一个重要组成部分,国家应当把这项内容列入义务教育必修的教学内容之中。

当全体公民都理解、掌握了交通规则和交通安全知识,并自觉地遵守这些规则,中国的交通形势就一定能有一个根本性的好转,交通事故就一定会大幅降低,因此而造成的人员伤亡的数量和财产损失的额度也一定会大幅减少。

要让人们遵守某种规则,必须先让人们了解这些规则,掌握这些规则,认同这些规则。同时,还要让人们知道遵守这些规则的必要性,清楚不遵守规则可能会给自己或别人造成的危害并应承担的相应责任(或可能受到的处罚)。只有这样,人们才有可能在思想上、意识上高度认同这些规则,在行为习惯上自觉遵守这些规则。

所以说,在中小学校进行交通法规和交通安全知识教育是非常必要的,是完全应该的,更是非常迫切的。

二、在中小学进行完整系统的交通法规和交通安全知识教育的可能性

交通法规的相关知识并不高深,都是一些常识,是每个正常社会人都能掌握的常识。

比如,“绿灯行,红灯停”“靠右行”“过马路要走斑马线”等知识,连幼儿园的小朋友都懂得。“雨雪天要减速缓行,雾霾天除要减速缓行外,还要打开相应的灯光”,像这样的知识(规定),只要稍提醒一下,人们就能理解。至于那些画成图形的标志,就更加形象、简洁、易懂了。当然也有一些较难记、较难理解的内容和标志,但并不是什么艰深、复杂的难题,只要花点时间去学、去理解,还是比较容易掌握的。

交通安全知识和道路交通信号(及含义)的条款内容虽然比较多,但绝大部分都简单易懂,非常容易理解和掌握,不需要什么逻辑推理和繁杂的演算。只要有初中的文化水平,甚至只要有小学毕业的水平,就能理解、掌握这些常识。所以,在义务教育阶段进行全面、系统的交通法规、交通安全教育是完全可能的。

三、我国中小学交通法规和交通安全知识教育的现状

1.目前,我国中小学交通知识的教育非常零散,不全面、不系统,内容非常少,且“东一榔头,西一板斧”,不能形成一个整体,不能使学生形成一个完整的知识体系。

2.内容的设置针对性不强,可操作性很差,发散得太宽泛,具体的规则和安全知识的篇幅很少。

小学的交通安全知识主要集中在《品德与社会》(一、二年级为《品德与生活》下同)科目中。我查阅了我校一至六年级2011-2012学年使用的《品德与社会》教材(其中一至四年级为人教版,五、六年级为科教版),这方面的内容实在少得可怜,在12册书里只有3册教材有这方面的内容。(1)一年级上册第一单元第4小节(18页至21页):《放学了》《平安回家》《我会看标志》。这个单元算是小学阶段针对性最强的教学内容了。(2)三年级下册第四单元《寻路和行路》中只有第3、第4小节是有关交通安全方面的知识的(66页至76页)。(3)四年级下册第三单元《交通与生活》,虽然教学内容与交通有关,但并不属于交通安全和交通规则方面的知识。也就是说,在小学阶段,严格地讲,只有两个单元,共14页的教学内容与交通安全、交通规则有关。

3.初中阶段能与交通知识挂上钩的科目应该只有《思想品德》(又称《政治》)这一科,但是不管是课标还是课文,都找不到一丝一毫关于交通知识方面的内容。人教版七年级上册第三课《珍爱生命》,虽然涉及了生命,但也没有交通安全方面的内容。七年级上册第九课《保护自我》也没有讲如何在交通方面保护自我。有关法律方面的几篇课文,同样没有涉及交通法规方面的内容。

这怎么能让学生全面系统地掌握交通法规,遵守交通法规呢?又怎么能让学生在交通安全中多一分保障呢?

四、在中小学进行完整系统的交通法规和交通安全知识教育的简要实施方案

我们有必要从小学一年级到初中三年级,完整、系统、有计划、循序渐进地实施这项教育内容。

1.教学目标

(1)使学生在初中毕业以前,全面、完整、系统地掌握、理解交通法规和交通安全知识的全部内容(包括现在驾驶学员考驾照所学的理论知识的全部内容)。

(2)使学生了解一些重要的交通法规的立法原则,如以责论处的原则、过(罪)罚相当的原则、人的生命至上的原则、各行其道的原则等。了解了这些原则能帮助学生更透彻地理解交通法规,也更有利于学生的记忆、理解、背诵。

(3)使每个学生都树立起自觉遵守交通规则的意识,养成自觉遵守交通规则的良好习惯。遵守规则比什么都重要,如果虽然有规则,但大家都不遵守,这就跟没有规则一个样。只有人人讲规则,人人遵守规则,才会有良好的秩序,才能最大限度地减少交通事故的发生,最大限度地保障公民的生命财产安全。

(4)使学生懂得违法违规的后果,形成敬畏法律、遵守法律的意识,做一个守法公民。违反交通法规,最容易受到伤害的是自己。不论你是驾驶机动车,还是骑非机动车,还是步行,如果你违反了交通规则,结果就可能很悲惨,轻则受点伤,财产受到损失,重则有残废甚至死亡的危险。同时还极有可能伤害他人。伤害他人的后果也是很严重的,不但要向受害方赔偿,承担相应的民事责任,严重的还要负刑事责任。

2.教学要求

编排教材时,小学和中学要统筹安排,使之成为一个完整、系统的整体,并由易到难、循序渐进地进行这项教育。

(1)小学低年级,虽然大部分学生在上学和放学时有家长接送,但他们已经比较经常的在马路上独立行走了。这一阶段的教育,以按交通规则和按信号灯的指示安全行走的内容为主。比如,懂得“红黄绿”三种信号灯的不同含义,懂得过马路要走“斑马线”,在没有信号灯的路口过马路时,懂得如何安全过马路等。

(2)中高年级的教学内容以识别各种交通标志和按交通规则安全步行和安全骑自行车为主。

小学阶段的教学,特别是中低年级的教学,要突出趣味性,除了在课堂上进行比较系统的教学外,还可以让学生在玩中体验,在游戏中体验,在各种不同的活动中体验。这样,不但能提高学生的学习兴趣、学习热情,还能极大地提高学习效果,同时可以发展学生的智力。建议每个年级至少用一个单元的课时进行交通规则、交通安全知识教育,把这方面的教学当做《品德与社会》课程的教学重点内容之一。

(3)初中阶段要渐次提高理论性,突出系统性,教学的内容要涵盖交通法规和交通安全知识的全部,在初三毕业前要把这些知识、法规、理论全部学完,把这个科目当做初中毕业考的必考科目。

建议在毕业考时参照汽车驾驶学员理论考试的模式进行统一的、正式的免费考试。考试时,可由交警或交通部门派人(当然也可委托教师)监考。凡达到90分及以上的(参照驾照考试合格标准),发给驾照理论考试合格证书(可同时输入个人相关的电子档案)。交通管理部门应认可这个成绩,应与驾驶员“理论考试合格证”具有同样的法律效应。凡取得这个合格证(即成绩在90分及以上)的学生,在以后考驾照时不需要再参加理论考试。相信几年以后,大部分的年轻人都可能会去考驾照,这样,他们在学校学习的这方面知识,不但使他们更早、更及时地了解、掌握了他们应该掌握的生活常识,不但没有加重他们的学业负担,还减少了他们以后参加此类考试可能遇到的麻烦,也减少了一些不必要的费用。

(4)为防止加重学生的课业负担,建议在小学的《品德与社会》(或《品德与生活》)和中学的《思想品德》(或《政治》)课里,减少与增加的交通法规和交通安全知识这方面教学内容相同的教学时数(甚至更多一点)的篇幅,保证课程总量不增加或略有减少,总教学时数不增加或略有减少。

(责编 刘宇帆)

作者:丘宝昌

第4篇:单片机课程设计-电子钟-完整

单片机课程设计

题目

专业 通信工程 班级 11级1班 学号 姓名

电 子 钟 设 计

单片机原理与应用课程设计

电子钟设计

功能要求:

1、设计一个电子时钟,要求可以显示时、分、秒,用户可以设置时间。

2、实现秒表功能。

功能描述

(1)

时钟。初始界面是时钟显示,按键S1是调时选位,按键S2是加数。根据不同的闪烁位置进行调节。

(2)

年与日,星期。在初始状态下,按下S2,则跳转,显示年月日,5S后跳回初始界面。若在年月日界面再次按下S2,则再次跳转,显示星期,几秒后跳转回初始界面。

(3)

秒表。在初始界面下,按下S3,则跳转,进入秒表。秒表功能键如下:S1 退出秒表;S2 停止开始计时;S3 秒表清零。

(4)

闹钟。在设置中设置好时间,最高位设为“1”则打开闹钟。最高位设为“0”则关闭闹钟。在闹钟响是,按S3进行关闹钟。

工作原理 硬件

采用80C51系列单片机作为CPU,P0口作为数据线,通过锁存器进行段选和位选,是数码管不断地显示数字。数码管的显示是扫描式。 (1)

本电子钟用的单片机型号是STC89C516RD+ 。P0口作为段选和位选的数据线。P10口为段选寄存器的使能端。P11口为位选寄存器的使能端。晶振采用的12MHz晶振。要求频率稳定。

(2)

本电子钟用的是共阴极数码管。从左到右,第1,2位是秒位;第4,5位是分位;第7,8位是时位。第3,6位是“--”。

(3)

通过单片机的P0口,先对数码管进行位选,即在位锁存器使能是将P0口数据进行锁存。再通过段锁存器将P0口送来的段数据进行锁存。此时数码管的第一位显示数字。同样的步骤进行第二位显示。以非常快的速度进行,由于人眼的余辉效应,会看到8位数码管一起亮。即可以显示时间。通过单片机的内部TO,T1的计数。即可以实现时钟,秒表等功能。 (4) 电路图如下:

软件

程序代码包括三部分:1.bujian(部件库) 2.main(主函数) 3.H(头文件库)。 一 .bujian(部件库) (1) xianshi.c #include #include #define m 2 Unsigned char code t[]={0x3f,0x30,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; void led_s(unsigned int s) { p10=1; p10=0; p11=1; P0=0x7f;

//数码管秒个位

P0=t[s%10]; p11=0; P0=0xff; delay(m); p10=1; p10=0; p11=1; P0=0xbf; p11=0;

//消隐

P0=t[s/10];

//消隐 //数码管秒十位

P0=0xff; delay(m); } void led_f(unsigned int s) { p10=1; // P0=t[s%10]; p10=0; p11=1; P0=0xef;

p11=0;

P0=0xff; delay(m); p10=1;

P0=t[s/10]; p10=0; p11=1; P0=0xf7; p11=0;

P0=0xff; delay(m); } void led_h(unsigned int s) {

// p10=1; P0=t[s%10]; p10=0; p11=1; P0=0xfd;

p11=0; // P0=0xff; delay(m); p10=1;

P0=t[s/10]; p10=0; p11=1; P0=0xfe; p11=0;

数码管分个位 //消隐

//数码管分十位

//消隐

数码管时个位

消隐

//数码管时十位

//消隐

P0=0xff; delay(m); }

void line(void) { p10=1; P0=0x40; p10=0; p11=1; P0=0xfb; delay(m); p11=0;

p10=1; P0=0x40; p10=0; p11=1; P0=0xdf; p11=0; delay(m); }

//消隐

P0=0xff;

//数码管"---"

//消隐

P0=0xff;

//数码管“---”

(2) miaobiao.c #include #include

#include extern mms,ms,mf,ss; void miaobiao(void) { TR1=1; while(1) { led_s(mms);led_f(ms);line();led_h(mf); if(s2==0) { while(!s2) {led_s(mms);led_f(ms);line();led_h(mf); } if(ss==1){TR1=0;ss=!ss;}else {TR1=1;ss=!ss;} } if(s1==0) { while(!s1) {led_s(mms);led_f(ms);line();led_h(mf); } TR1=0;break; } if(s3==0)

{ while(!s3) {led_s(mms);led_f(ms);line();led_h(mf); } TR1=0;mms=0;ms=0;mf=0; } } }

(3) Delay.c #include

void delay(unsigned int a)

{ unsigned char l;

while (a--)

{for(l=0;l<100;l++);} }

(4)gongneng.c #include

#include #include extern h,f,s,n,y,r,nian,xing; extern ns,nf,nh; void gongneng() { unsigned int aa=0,shanshuo=0,x=1,bb;

if(s2==0) { delay(3); if(s2==0) while(!s2) { led_s(s);delay(1); line();led_f(f);delay(1); led_h(h); delay(1); }

// while(1) { led_s(r); delay(2); led_f(y); delay(2); line(); led_h(nian); delay(2); aa++; if(s2==0)

{ while(!s2)

{

led_s(r);delay(1); line();led_f(y);delay(1); led_h(nian); delay(1); }

//星期显示

while(1)

{led_f(xing);delay(2);

bb++;

if(bb==100){bb=0; break;}

日期显示 }

}

if(aa==100)

line();led_f(y);delay(1); led_h(nian); delay(1);

} } if(s1==0) { delay(3); if(s1==0) {

switch(x) { case 1 : if(shanshuo==1){led_s(s);} line(); led_f(f);delay(2);led_h(h); delay(2); break; case 2 :led_s(s); if(shanshuo==1){led_f(f);} delay(2);line();led_h(h); delay(2); break; case 3 : led_s(s);led_f(f);delay(2);line(); if(shanshuo==1){led_h(h);} delay(2); break; case 4 : if(shanshuo==1){led_s(r);} led_f(y);delay(2);line();led_h(nian); delay(2); break; case 5 : led_s(r); if(shanshuo==1){led_f(y);} delay(2);line();led_h(nian); delay(2); break; case 6 :led_s(r);led_f(y);delay(2); line();if(shanshuo==1){led_h(nian);} delay(2); break; case 7 :if(shanshuo==1){led_f(xing);delay(5);} break; case 8 :if(shanshuo==1){led_s(nf);} line(); led_f(nh);delay(2);led_h(ns); delay(2); break; case 9 :led_s(nf); if(shanshuo==1){led_f(nh);} delay(2);line();led_h(ns); delay(2); break; case 10:led_s(nf);led_f(nh);delay(2);line(); if(shanshuo==1){led_h(ns);} delay(2); break; default : break; }

aa++; if(s2==0) { while(!s2) {if(x==1||x==2||x==3) { led_s(s);delay(1);line();led_f(f);delay(1);led_h(h); delay(1);} if(x==4||x==5||x==6) { led_s(r);delay(1);line();led_f(y);delay(1);led_h(nian); delay(1); } if(x==7){ led_f(xing); } if(x==8||x==9||x==10) {led_s(nf);led_f(nh); delay(2);line();led_h(ns); delay(2);} }

switch(x)

{ case 1 : s++;if(s>59)s=0; break;

while(!s1); while(1)

{ if(x==1||x==2||x==3) TR0=0; else TR0=1; if(aa==20) {shanshuo=!shanshuo;aa=0;}

{ break; } { led_s(r);delay(1);

} if(s1==0)

case 2 :

}

f++; if(f>59)f=0;break;

case 3 : h++;if(h>23)h=0;break; case 4 : r++;if(r>31)r=1; break; case 5 : y++;if(y>12)y=1; break; case 6 : case 7 :

nian++; if(nian>20)nian=10; break; xing++; if(xing>7)xing=1; break;

case 8 : nf++; if(nf>59)nf=0;break; case 9 : nh++;if(nh>23)nh=0;break; case 10: ns=!ns; break;

default: break; {while(!s1) {if(x==1||x==2||x==3) { led_s(s);delay(1);line();led_f(f);delay(1);led_h(h); delay(1);} if(x==4||x==5||x==6) { led_s(r);delay(1);line();led_f(y);delay(1);led_h(nian); delay(1); } if(x==7){ led_f(xing); } if(x==8||x==9||x==10) {led_s(nf);led_f(nh); delay(2);line();led_h(ns); delay(2);} }

x++; if(x>10) { x=0;TR0=1; break; } } } } } } } 二 .H(头文件库) (1)Delay.h #ifndef _DELAY_H__

void led_s(unsigned int s) ; void led_h(unsigned int s); #define _DELAY_H__ void delay(unsigned int a); #endif (2)xianshi.h #ifndef _XIANSHI_H__ #define _XIANSHI_H__

void led_f(unsigned int s); void line(void); #endif (3)gongneng.h

#ifndef _DONGNENG_H__ #define _GONGNENG_H__ void gongneng(void); #endif (4)miaobiao.h

#ifndef _MIAOBIAO_H__ #define _MIAOBIAO_H__ void miaobiao(void); #endif (5)dingyi.h #ifndef _DINGYI_H__ #define _DINGYI_H__ sbit s1=P2^4;

sbit s2=P2^5;

sbit s3=P2^6; sbit p10=P1^0; sbit p11=P1^1; sbit p12=P1^2; #endif

//流水灯使能端 //按键1 //按键2 //按键3 sbit p37=P3^7; //蜂鸣器时能

三. Main(主函数) (1)main.c #include #include #include #include #include unsigned int h,m,f,s,n,y=10,r=12,nian=13,xing=2,mms,ms,mf; unsigned int ns=0,nf,nh,ll=0; unsigned int ss=1; void main() { P0=0xff; p12=0; TMOD=0x12; EA=1;

ET0=1; TH0=6; TR0=1;

//关闭流水灯

ET1=1; TH1=(65535-5000)/256; TL1=(65535-5000)%256; TR1=0; while(1) { if((s3==0)&&(ns==0)) {while(!s3); miaobiao();} if(s1==0||s2==0) gongneng(); else { led_s(s); line(); led_f(f); line(); led_h(h); } if((f==nf)&&(h==nh)&&(ns==1)) ll=1; else ll=0; } } void zhongduan(void) interrupt 1 {

if((ll==1)&&(ns==1))

{ p37=!p37; if((s3==0)&&(ns==1)) { while(!s3) ns=0; p37=1; } } n++; if(n==5000) {n=0; s++; if(s==60) { s=0; f++; } if(f==60) { f=0; h++; }

if(h==24) { h=0; r++; xing++; } switch(r) { case 29 : if(nian/4==0){if(y==2) r=0;} y++; case 31 : if(y==4||y==6||y==9||y==11){ } if(xing>7) xing=1; if(y==13) { y=1; nian++; } } } default : break;

break; case 30 : if((nian/4)!=0){if(y==2){ r=0; y++;}} break;

r=0; y++;} break; case 32 : if(y==1||y==3||y==5||y==7||y==8||y==10||y==12) {r=0;y++;} break; void zhongduan1(void) interrupt 3

{

TH1=(65535-5000)/256;

m++; TL1=(65535-5000)%256; if(m==2) {mms++; m=0; if(mms>=100) { mms=0; ms++; } if(ms==60) { ms=0; mf++; } if(mf==60) { mf=0; } } }

参考文献:

单片机中级教程(第2版)、单片机语言C51程序设计(赵文博) 感想: 这次课程设计整体来说是成功的,但我也发现了自己许多错漏和不足之处。譬如,最简单的程序没写好就想着写更复杂的程序,做事还是缺乏耐性和细心,当有时遇到问题时,总觉得无从下手,对于课本上的知识不能很好的组织起来。在编写各功能程序时,特别是后来增添的比较复杂的程序

第5篇:操作系统课程设计

湖北民族学院信息工程学院11级计算机专业操作系统课程设计

(操作系统课程设计)

连续动态分区内存

管理模拟实现

学生姓名: 韩 慧 学生学号: 031140312 班 级: 031140--3

031140

1、0

2、0

3、04班制

二〇一三年十二月

1 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

目录

《操作系统》课程设计....................................................... 1 引言......................................................................3 课程设计目的和内容 ...................................................... 3 需求分析.........................................................................3 概要设计...................................................................3 开发环境........................................................................ 4 系统分析设计..................................................................... 4 有关了解内存管理的相关理论.................................................. 4 内存管理概念........................................................................4 内存管理的必要性..............................................................4 内存的物理组织.............................................................4 什么是虚拟内存.................................................................5 连续动态分区内存管理方式................................................... 5 单一连续分配(单个分区)................................................... 5

固定分区存储管理...............................................................5 可变分区存储管理(动态分区).............................................. 5 可重定位分区存储管理........................................................5 问题描述和分析....................................................................6 程序流程图........................................................................6 数据结构体分析..................................................................8 主要程序代码分析...............................................................9 分析并实现四种内存分配算法 ................................................. 11 最先适应算.....................................................................11 下次适应分配算法..........................................................13 最优适应算法...............................................................16 最坏适应算法......................................................... ......18 回收内存算法................................................................20 调试与操作说明.................................................................22

初始界面.......................................................................22 模拟内存分配...............................................................23

已分配分区说明表面............................................................24 空闲区说明表界面.............................................................24 回收内存界面.....................................................................25 重新申请内存界面..........................................................26. 总结与体会...................................................................... 28

2 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

参考文献......................................................................... 28

引言

操作系统是最重要的系统软件,同时也是最活跃的学科之一。我们通过操作系统可以理解计算机系统的资源如何组织,操作系统如何有效地管理这些系统资源,用户如何通过操作系统与计算机系统打交道。

存储器是计算机系统的重要组成部分,近年来,存储器容量虽然一直在不断扩大,但仍不能满足现代软件发展的需要,因此,存储器仍然是一种宝贵而又紧俏的资源。如何对它加以有效的管理,不仅直接影响到存储器的利用率,而且还对系统性能有重大影响。而动态分区分配属于连续分配的一种方式,它至今仍在内存分配方式中占有一席之地。

课程设计目的和内容:

理解内存管理的相关理论,掌握连续动态分区内存管理的理论;通过对实际问题的编程实现,获得实际应用和编程能力。

编写程序实现连续动态分区内存管理方式,该程序管理一块虚拟内存,实现内存分配和回收功能。 分析并实现四种内存分配算法,即最先适应算法,下次最先适应算法,最优适应算法,最坏适应算法。内存分配算法和回收算法的实现。

需求分析

动态分区分配是根据进程的实际需要,动态地为之分配内存空间。在实现动态分区分配时,将涉及到分区分配中所用的数据结构、分区分配算法和分区的分配和回收操作这样三个问题。常用的数据结构有动态分区表和动态分区链。在对数据结构有一定掌握程度的情况下设计合理的数据结构来描述存储空间,实现分区存储管理的内存分配功能,应该选择最合适的适应算法(首次适应算法,最佳适应算法,最后适应算法,最坏适应算法),在动态分区存储管理方式中主要实现内存分配和内存回收算法,在这些存储管理中间必然会有碎片的产生,当碎片产生时,进行碎片的拼接等相关的内容

概要设计

本程序采用机构化模块化的设计方法,共分为四大模块。 ⑴最先适应算法实现

从空闲分区表的第一个表目起查找该表,把最先能够满足要求的空闲区分配给作业,这种方法目的在于减少查找时间。为适应这种算法,空闲分区表(空闲区链)中的空闲分区要按地址由低到高进行排序。该算法优先使用低址部分空闲区,在低址空间造成许多小的空闲区,在高地址空间保留大的空闲区。 ⑵下次适应分配算法实现

3 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

该算法是最先适应算法的变种。在分配内存空间时,不再每次从表头(链首)开始查找,而是从上次找到空闲区的下一个空闲开始查找,直到找到第一个能满足要求的的空闲区为止,并从中划出一块与请求大小相等的内存空间分配给作业。该算法能使内存中的空闲区分布得较均匀。 ⑶最优适应算法实现

它从全部空闲区中找出能满足作业要求的、且大小最小的空闲分区,这种方法能使碎片尽量小。为适应此算法,空闲分区表(空闲区链)中的空闲分区要按从小到大进行排序,自表头开始查找到第一个满足要求的自由分区分配。 ⑷最坏算法实现

最坏适应分配算法要扫描整个空闲分区或链表,总是挑选一个最大的空闲分区分割给作业使用。该算法要求将所有的空闲分区按其容量从大到小的顺序形成一空闲分区链,查找时只要看第一个分区能否满足作业要求。

开发环境:

win7 下 VC++6.0 系统分析设计:

相关算法原理,算法流程图,涉及的数据结构内容都相应包含在各章节中

有关了解内存管理的相关理论

内存管理概念:

内存管理,是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。内存不是预先划分好的,而是在系统运行的过程中建立分区.当作业装入主存时,根据作业所需要的主存容量查看是否有足够的主存空间,若有则按需要分割一个分区给该作业;否则令该作业等待.分区长度不固定分区个数不固定。这种存储管理的方法克服了固定分区严重浪费主存的问题,提高了主存资源的利用率。

内存管理的必要性:

内存管理对于编写出高效率的 Windows 程序是非常重要的,这是因为Windows 是多任务系统,它的内存管理和单任务的 DOS 相比有很大的差异。DOS是单任务操作系统,应用程序分配到内存后,如果它不主动释放,系统是不会对它作任何改变的;但 Windows 却不然,它在同一时刻可能有多个应用程序共享内存,有时为了使某个任务更好地执行,Windows 系统可能会对其它任务分配的内存进行移动,甚至删除。因此,我们在 Windows 应用程序中使用内存时,要遵循Windows 内存管理的一些约定,以尽量提高 Windows 内存的利用率。

4 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

1.3 内存的物理组织:

物理地址:

把内存分成若干个大小相等的存储单元,每个存储单元占 8 位,称作字节(byte)。每个单元给一个编号,这个编号称为物理地址(内存地址、绝对地址、实地址)。

二、物理地址空间: 物理地址的集合称为物理地址空间(主存地址空间),它是一个一维空间。

什么是虚拟内存:

虚拟内存是内存管理技术的一个极其实用的创新。它是一段程序(由操作系统调度),持续监控着所有物理内存中的代码段、数据段,并保证他们在运行中的效率以及可靠性,对于每个用户层(user-level)的进程分配一段虚拟内存空间。当进程建立时,不需要在物理内存件之间搬移数据,数据储存于磁盘内的虚拟内存空间,也不需要为该进程去配置主内存空间,只有当该进程被被调用的时候才会被加载到主内存。

连续动态分区内存管理方式的实现

在早期的操作系统中,主存分配广泛采用连续分配方式。 连续分配方式,是指为一个用户程序分配一个连续的内存空间,该连续内存空间指的的是物理内存。下面介绍连续分配的四种方式。

单一连续分配(单个分区)

最简单的存储管理方式,用于多道程序设计技术之前。 内存分为系统区和用户区,系统区由操作系统使用。用户区作为一个连续的分区分配给一个作业。 分区存储管理是满足多道程序设计的最简单的一种存储管理方法,它允许多 4个用户程序同时存在系统内存中,即共享内存空间。 按分区划分方式可分为固定分区和可变分区。

固定分区存储管理

把内存的用户区预先划分成多个分区,每个分区大小可以相同,也可以不同。(分区的划分由计算机的操作员或者由操作系统给出,并给出主存分配表) 分区个数固定,分区的大小固定。 一个分区中可装入一个作业,作业执行过程中不会改变存放区域。 早期的 IBM 的 OS/MFT(具有固定任务数的多道程序系统)采用了这种固定分区的方法。

可变分区存储管理(动态分区)

内存不是预先划分好的,而是在系统运行的过程中建立分区.当作业装入主存时,根据作业所需要的主存容量查看是否有足够的主存空间,若有则按需要分割一个分区给该作业;否则令该作业等待。 分区长度不固定分区个数不固定。 这种存储管理的方法克服了固定分区严重浪费主存的问题,提高了主存资源的利用率。 IBM操作系统OS/MVT采用可变分区存储管理。

5 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

可重定位分区存储管理

解决碎片问题的一种简单方法是采用可重定位分区分配.。 其中心思想是,把不同程序,且在内存中地址不连续的想法让他们连续。

例:内存中现有 3 个空闲区,现有一作业到达,要求获得 30k 内存空间,没有分区满足容量要求,若想把作业装入,可将内存中所有作业进行移动,这样把原来分散的空闲区汇集成一个大的空闲区。 将内存中的作业进行移动使它们连接在一起把原来分散的多个小分区拼接成一个大的空闲区.这个过程称为”紧凑”或”移动”。 需解决的问题:每次”紧凑”后程序或数据装入的物理地址变化采用动态重定位。

问题描述和分析

系统应利用某种分配算法,从空闲分区链表中找到所需大小的分区,如果空闲分区大小大于请求分区大小,则从该分区中按改请求的大小划分出一块内存空间大小划分出一块内存空间分配出去,余下的部分仍留在空闲链表中。然后,将分配区的首址返回给调用者。

当进程运行完毕师范内存时,系统根据回收区的首址,从空闲区中找到相应的插入点,此时可能出现以下四种情况之一:

⑴该空闲区的上下两相邻分区都是空闲区:将三个空闲区合并为一个空闲区。新空闲区的起始地址为上空闲区的起始地址,大小为三个空闲区之和。空闲区合并后,取消可用表或自由链中下空闲区的表目项或链指针,修改上空闲区的对应项。

⑵该空闲区的上相邻区是空闲区:将释放区与上空闲区合并为一个空闲区,其起始地址为上空闲区的起始地址,大小为上空闲区与释放区之和。合并后,修改上空闲区对应的可用表的表目项或自由链指针。

⑶该空闲区的下相邻区是空闲区:将释放区与下空闲区合并,并将释放区的起始地址作为合并区的起始地址。合并区的长度为释放区与下空闲区之和。同理,合并后修改可用表或自由链中相应的表目项或链指针。

⑷两相邻区都不是空闲区:释放区作为一个新空闲可用区插入可用表或自由链。

程序流程图

内存分配流程图,如图

6 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

从头开始查表检索完否?NY返回分区大小>所需大小N继续检索下一个表项Y分区大小-所需大小<=不可再分割大小N从该分区中划出所需大小的新分区Y将该分区从链中移出将该分区分配给请求者修改有关数据结构返回

内存回收流程图,如图

7 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

开始判断空闲区上下内存情况上为空下为空上下都为空上下都不为空将上面的空闲区合并,并回收将下面的空闲区合并,并回收将上下的空闲区合并,并回收直接将其回收结束 数据结构体分析

⑴进程属性结构体 typedef struct readyque { char name[10]; int size; }readyque,*readyqueue; ⑵空闲链表结构体 typedef struct idlyspace { int from; int size; idlyspace * next; }idlyspace,*idly; ⑶已分配链表结构体 typedef struct busyspace { int from; readyque r;

8 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

busyspace * next; }busyspace,*busy

主要程序代码分析

⑴主函数//代码请添加适当的注释。 int main() { Is=(idly)malloc(sizeof(idlyspace)); Is->from=0; Is->size=256; Is->next=NULL; Is2=Is; Bs=(busy)malloc(sizeof(busyspace)); Bs->next=NULL; int t,t1; printf(" .......................欢迎来到动态分区存储管理系统.................. "); printf("...........................请选择要执行的算法:........................... "); printf("......................... 1.最先适应算法

............................... "); printf("......................... 2.下次适应算法 ............................ "); printf("..........................3.最优适应算法

............................... "); printf("......................... 4.最坏适应算法 ................................ "); printf("........................................................................ "); printf("请输入您的选择:"); scanf("%d",&t); int i; while(i!=5) {

printf("........................................................................ ");

printf(".........................操作菜单如下:(请选择).......................n");

printf("..........................1.输入进程分配空间 ...........................n");

printf("......................... 2.进程撤销回收空间 ........................... ");

printf("......................... 3.输出所有空闲分区

.......................... ");

printf("..........................4.输出所有已分配分区.......................... ");

printf(".......................... 5.退

出 .......................... ");

printf("........................................................................ ");

scanf("%d",&i);

switch(i)

{

case 1:

switch(t)

{

case 1:

t1=FF();

9 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

break;

case 2:

t1=NF();

break;

case 3:

t1=BF();

break;

case 4:

t1=WF();

break;

default:

printf("选择算法错误 ");

return 1;

}

if(t1)

printf("分配空间成功 ");

else

printf("分配空间失败 ");

break;

case 2:

t1=recover();

if(t1)

printf("回收成功 ");

else

printf("回收失败 ");

break;

case 3:

Isprint();

break;

case 4:

Bsprint();

break;

} } return 0; }

第三章 :分析并实现四种内存分配算法

最先适应算法

空闲区按地址从小到大的次序排列。

分配:当进程申请大小为 SIZE 的内存时,系统顺序查找空闲区表(链),直到找到容量满足要求(≥SIZE)的空闲区为止。从该空闲区中划出大小为 SIZE的分区分配给进程,余下的部分仍作为一个空闲区,但要修改其首址和大小。

10 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

优点:这种算法是尽可能地利用低地址部分的空闲区,而尽量地保证高地址 6部分的大空闲区,有利于大作业的装入。

缺点:主存低地址和高地址分区利用不均衡。在低地址部分集中了许多非常小的空闲区碎片降低了主存的利用率。 最先适应算法 int FF() { int t=0; readyque D; printf“"请输入进程名:”"); scanf“"%”",D.name);

printf“"输入进程申请空间大小:”"); scanf“"%”",&D.size);

idly l=Is; int mt=256; busy b=Bs; idly min=NULL; while(l)

//寻找空闲表中大小满足申请进程所需大小并且起址最小的空闲结点

{

if(D.size<=l->size)

{

if(l->from

{ mt=l->from; min=l; t=1;

}

}

l=l->next; } if(mt!=256)

{

busy j;

j=(busy)malloc(sizeof(busyspace));

//如果找到则为进程分配空间

11 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

j->from=min->from;

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

{

j->r.name[i]=D.name[i];

}

j->r.size=D.size;

while(b->next)

{ if(b->next->fromfrom)

b=b->next; else

break;

}

j->next=b->next;

b->next=j;

min->from=min->from+D.size;

min->size=min->size-D.size; } return t; }

下次适应分配算法

最先适应算法的变种。

总是从空闲区上次扫描结束处顺序查找空闲区表(链),直到找到第一个满足容量要求的空闲区为止,分割一部分给作业,剩余部分仍作为空闲区。 下次适应分配算法 int NF() { int t=0; readyque D; printf“"请输入进程名:”"); scanf“"%”",D.name);

12 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

printf“"输入进程申请空间大小:”"); scanf“"%”",&D.size);

int mt=256; idly l=Is2; idly min=NULL; busy b=Bs; while(l) //寻找空闲表中大小满足申请进程所需大小并且起址最小的空闲结点

{

if(D.size<=l->size)

{

if(l->from

{ mt=l->from; min=l; t=1;

}

}

l=l->next; } if(mt!=256)

{

busy j;

j=(busy)malloc(sizeof(busyspace));

j->from=min->from;

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

{

j->r.name[i]=D.name[i];

}

j->r.size=D.size;

while(b->next)

{ if(b->next->fromfrom)

b=b->next; else

break;

//如果找到则为进程分配空间

13 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

}

//将申请空间进程插入到已分配链表中

j->next=b->next;

b->next=j;

//修改相应空闲节点的起址和大小

min->from=min->from+D.size;

min->size=min->size-D.size;

Is2=min->next;

结点

t=1;

return t; }

l=Is;//l指向空闲表的头

while(l!=Is2)

{

if(D.size<=l->size)

{

if(l->from

{ mt=l->from; min=l; t=1;

}

}

l=l->next; } if(mt!=256) {

busy j;

j=(busy)malloc(sizeof(busyspace));

j->from=min->from;

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

{

//ls2指向修改结点的下一个

//循环查找

14 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

j->r.name[i]=D.name[i];

}

j->r.size=D.size;

while(b->next)

{ if(b->next->fromfrom)

b=b->next; else

break;

}

j->next=b->next;

b->next=j;

min->from=min->from+D.size;

min->size=min->size-D.size;

Is2=min->next;

t=1;

return t; } return t; }

最优适应算法

空闲区按容量递增的次序排列。

分配:当进程申请存储空间,系统顺序查找空闲区表(链),直到找到第一个满足容量要求的空闲区为止。 采用最优适应算法选中的空闲区是满足容量要求的最小空闲区。 优点:选中的空闲区是满足容量要求的最小空闲区,而不致于毁掉较大的空闲区。

缺点:空闲区的大小一般与申请分区大小不相等,因此将其一分为二,留下来的空闲区一般情况下是很小的,以致无法使用。随着时间的推移,系统中的小空闲区会越来越多,从而造成存储空间的浪费。 最优适应算法 int BF() { int t=0;

15 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

readyque D; printf“"请输入进程名:”"); scanf“"%”",D.name);

printf“"输入进程申请空间大小:”"); scanf“"%”",&D.size);

idly l=Is; idly min=NULL; int mt=256; busy b=Bs; while(l) //在空闲链中寻找第一个大于所输入的进程大小的空闲块

{

if(D.size<=l->size)

{

if(l->size

{

mt=l->size; min=l; t=1;

}

}

l=l->next; } if(mt!=256)

{

busy j;

j=(busy)malloc(sizeof(busyspace)); 空间

j->from=min->from;

//申请分配用于存放进程的内存

//找到第一个满足要求的空闲块

//将第一个满足要求的空闲块(min)的首地址赋给j

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

{

j->r.name[i]=D.name[i]; 16 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

}

j->r.size=D.size;

while(b->next)

//按从小到大的顺序查找新进程在已分配区中的位置

{ if(b->next->fromfrom)

b=b->next; else

break;

}

j->next=b->next;

b->next=j;

min->from=min->from+D.size;

min->size=min->size-D.size;

} return t; }

最坏适应算法

为了克服最佳适应算法把空闲区切割得太小的缺点,人们提出了一种最坏适应算法,即每次分配时,总是将最大的空闲区切去一部分分配给请求者,剩余的部分仍是一个较大的空闲区。避免了空闲区越分越小的问题。 要求空闲区按容量递减的顺序排列。

分配:进程申请存储区时,检查空闲区表(链)的第一个空闲区的大小是否满足要求,若不满足则令进程等待;若满足则从该空闲区中分配一部分存储区给用户,剩下的部分仍作为空闲区。 最坏适应算法 int WF() { int t=0; readyque D; printf“"请输入进程名:”"); scanf“"%”",D.name);

printf“"输入进程申请空间大小:”");

//将所输入的进程插入进程链

//改变该空闲块的起始地址 //改变该空闲块的剩余大小 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

scanf“"%”",&D.size);

//输入进程申请的空间大小

idly l=Is;//l指向空闲链表ls头

idly min=NULL; int mt=0; busy b=Bs;

//b指向已分配链表Bs头

//找到空闲分区中大小满足进程的请求且尺寸最大的结点

while(l) {

if(D.size<=l->size) //判断进程所申请的大小是否小于空闲区的各结点大小

{

if(l->size>mt)

{ mt=l->size; min=l;//min指向空闲区中尺寸最大的结点

t=1;

}

}

l=l->next; } if(mt!=0) 点

{

busy j;

j=(busy)malloc(sizeof(busyspace));

j->from=min->from;

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

{

j->r.name[i]=D.name[i];

}

j->r.size=D.size;

//判断是否找到了空闲区的满足结

//l指向空闲链表下一个结点

18 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

while(b->next) 置

//寻找插入到已分配链表中的位

{ if(b->next->fromfrom)

b=b->next; else

break;

}

//把此进程结点j插入到已分配链表中

j->next=b->next;

b->next=j;

//修改空闲链表的相应结点的参数

min->from=min->from+D.size;

min->size=min->size-D.size; } return t; }

可变分区的回收

当某个进程释放某存储区时,系统首先检查释放区是否与系统中的空闲区相邻若相邻则把释放区合并到相邻的空闲区去,否则把释放区作为一个空闲区插入到空闲表的适当位置。

释放区与空闲区相邻的四种情况。

(1) 释放区与前空闲区相邻:把释放区与前空闲区合并到一个空闲区。其首址仍为前空闲区首址,大小为释放区大小与空闲区大小之和。

(2) 释放区与后空闲区相邻:则把释放区合并到后空闲区,其首地址为释放区首地址,大小为二者之和。

(3) 释放区与前后两空闲区相邻:这三个区合为一个空闲区,首地址为前空闲区首址,大小为这三个空闲区之和,并取消后空闲区表目。

(4) 释放区不与任何空闲区相邻:将释放区作为一个空闲区,将其大小和首址插入到空闲区表的适当位置。

19 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

回收内存算法

int recover() { readyque D; printf“"请输入想要回收的进程名”");

scanf“"%”",D.name);

busy b=Bs; idly l=Is; while(b->next) 链表中

{

bool yo=1;

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

{

if(b->next->r.name[i]==D.name[i]) yo=yo*1;

else yo=0;

}

//如果在已分配链表中则释放该结点所占空间

if(yo)

{

int t=b->next->from;

int ts=b->next->r.size;

//查找输入的进程名是否在已分配湖北民族学院信息工程学院11级计算机专业操作系统课程设计

while(l)

{ if(l->from>t+ts) 不邻接

{ idly tl; tl=(idly)malloc(sizeof(idlyspace)); tl->from=t; tl->size=ts; tl->next=l; Is=tl; break; } if(l->from==t+ts)

l->from=t;

l->size=l->size+ts;

busy tb=b->next;

b->next=b->next->next;

free(tb);

return 1; }

if(l->from+l->size

idly tl;

tl=(idly)malloc(sizeof(idlyspace));

tl->from=t;

tl->size=ts;

tl->next=l->next;

l->next=tl;

break; }

else if(l->from+l->size==t)

//所回收进程与空闲结点上邻接 {

//所回收进程与空闲结点上下都不邻接

//所回收进程与空闲结点下邻接 {

//所回收进程与空闲结点上下都 21 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

l->size=l->size+ts;

if(l->from+l->size==l->next->from) 接

{

l->size=l->size+l->next->size;

idly tm=l->next;

l->next=l->next->next;

freI);

}

br

l=l->next;

}

//从已分配链表中释放所回收进程

busy tb=b->next;

b->next=b->next->next;

free(tb);

return 1;

}

b=b->next; } printf("没找到这”进程 "); return 0; }

//所回收进程与空闲结点上下都邻调试与操作说明

初始界面

程序初始界面,有四个块选择,选择要执行的算法,调试以最坏算法为例,如图

22 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

选择最坏适应算法,如图

模拟内存分配

给进程a分配内存20,如图

23 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

已分配分区说明表界面

同理,给进程b分配内存30,给进程c分配内存40,给进程d分配50,给进程e分配60,如图

空闲分区说明表界面

24 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

查看空闲分区,如图

回收内存界面

回收进程b和d所占内存,如图

已分配分区说明表和空闲分区说明表 如图

25 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

重新申请内存界面

再为新进程i分配内存30,如图

26 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

根据最坏适应算法结合图所示可知,该算法将会从空闲分区表中选择一块最大的内存空间分配给进程i,从图也可看出该模拟算法实现了最坏适应算法

27 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

总结与体会

本次做的课题是动态分区分配算法实现,此次课程设计成功实现了内存分配和内存回收,内存分配中包含了四种算法,分别是首次适应算法,循环首次适应算法,最佳适应算法和最坏适应算法。经编码调试,表明该程序模块是有效可行的。

通过这门课程的学习让我充分了解了内存管理的机制实现,从而更深一步的的对计算机

有了很多了解,这对于以后我们的研究和学习计算机系统起到了很重要的作用。

对于本次论文制作,自己的编程能力有所提高,对操作系统内存分配,存储空间的回收都有全新的认识。

在这次操作系统课程设计中,我使用了c++编写系统软件,对os中可变分区存储管理有了深刻的理解,但是过程中遇到了很多困难,一边做一边学,对c++有了比较多的理解。

实验中遇到很多问题,浪费了很多时间,总而言之是自己学习还不够好,不扎实,希望在以后学习中加以改善,学到更多知识。

参考文献

【1】 汤子瀛,哲凤屏,汤小丹.计算机操作系统.西安:西安电子科技大学出版社,2001.。

28 湖北民族学院信息工程学院11级计算机专业操作系统课程设计

【2】 任爱华.操作系统实用教程.北京:清华大学出版社,2001。

29

第6篇:操作系统课程设计

注意事项:

0. 请每位同学必须按时提交课程设计报告(包括电子版和纸质版),算入期末成绩

1. 在三个题目中选择一个

2. 如果选择题目

(一)进程调度算法,要求实现其中2个以上(包括2个)进程调度算法 3. 如果选择题目

(二)银行家算法,要求能够判断系统的安全状态

4. 如果选择题目

(三)页面调度算法,要求实现其中2个以上(包含2个)进程调度算法 5. 报告应包含算法分析、实验截图、核心算法源代码,请各位同学认真对待,独立完成 6. 提交要求:电子版(包括实验程序)请发至ropeal@163.com,纸质版请班长收齐,由班长统一在课堂上提交(并提交未交人员名单),截止时间第16周周三(2014.1.31) 7. 格式要求:

7.1 A4纸10页左右

7.2 封面请注明班级、姓名、学号、所选题目

7.3 电子版发送时,请打包成一个文件,将文件名设置为:学号+姓名+题目名称(如20130000张三进程调度算法课程设计),邮件主题同文件名

一、 进程调度算法

1.1 实验目的: a、设计进程控制块PCB表结构,模拟实现进程调度算法:FIFO,静态优先级调度,时间片轮转调度,多级反馈队列调度。(实现其中之二)。* b、建立进程就绪队列。对不同算法编制入链子程序。 c、编写一进程调度程序模拟程序。模拟程序只对PCB进行相应的调度模拟操作,不需要实际程序。 * 由用户输入进程名和进程长度,然后按照短进程优先的进程处理顺序给出进程的排序。

1.2 实验原理 调度算法是指:根据系统的资源分配策略所规定的资源分配算法。 1.2.1 先来先服务和短作业(进程)优先调度算法

1. 先来先服务调度算法。先来先服务(FCFS)调度算法是一种最简单的调度算法,该算法既可用于作业调度, 也可用于进程调度。FCFS算法比较有利于长作业(进程),而不利于短作业(进程)。由此可知,本算法适合于CPU繁忙型作业, 而不利于I/O繁忙型的作业(进程)。

2. 短作业(进程)优先调度算法。短作业(进程)优先调度算法(SJ/PF)是指对短作业或短进程优先调度的算法,该算法既可用于作业调度, 也可用于进程调度。但其对长作业不利;不能保证紧迫性作业(进程)被及时处理;作业的长短只是被估算出来的。 1.2.2 高优先权优先调度算法

1. 优先权调度算法的类型。为了照顾紧迫性作业,使之进入系统后便获得优先处理,引入了最高优先权优先(FPF)调度算法。 此算法常被用在批处理系统中,作为作业调度算法,也作为多种操作系统中的进程调度,还可以用于实时系统中。当其用于作业调度, 将后备队列中若干个优先权最高的作业装入内存。当其用于进程调度时,把处理机分配给就绪队列中优先权最高的进程,此时, 又可以进一步把该算法分成以下两种: 1)非抢占式优先权算法

2)抢占式优先权调度算法(高性能计算机操作系统)

2. 优先权类型 。对于最高优先权优先调度算法,其核心在于:它是使用静态优先权还是动态优先权, 以及如何确定进程的优先权。 3.高响应比优先调度算法

为了弥补短作业优先算法的不足,我们引入动态优先权,使作业的优先等级随着等待时间的增加而以速率a提高。 该优先权变化规律可描述为:优先权=(等待时间+要求服务时间)/要求服务时间;即 =(响应时间)/要求服务时间 1.2.3 基于时间片的轮转调度算法

1. 时间片轮转法。时间片轮转法一般用于进程调度,每次调度,把CPU分配队首进程,并令其执行一个时间片。 当执行的时间片用完时,由一个记时器发出一个时钟中断请求,该进程被停止,并被送往就绪队列末尾;依次循环。 2. 多级反馈队列调度算法 多级反馈队列调度算法多级反馈队列调度算法,不必事先知道各种进程所需要执行的时间,它是目前被公认的一种较好的进程调度算法。 其实施过程如下:

1) 设置多个就绪队列,并为各个队列赋予不同的优先级。在优先权越高的队列中, 为每个进程所规定的执行时间片就越小。

2) 当一个新进程进入内存后,首先放入第一队列的末尾,按FCFS原则排队等候调度。 如果他能在一个时间片中完成,便可撤离;如果未完成,就转入第二队列的末尾,在同样等待调度„„ 如此下去,当一个长作业(进程)从第一队列依次将到第n队列(最后队列)后,便按第n队列时间片轮转运行。 3) 仅当第一队列空闲时,调度程序才调度第二队列中的进程运行;仅当第1到第(i-1)队列空时, 才会调度第i队列中的进程运行,并执行相应的时间片轮转。 4) 如果处理机正在处理第i队列中某进程,又有新进程进入优先权较高的队列, 则此新队列抢占正在运行的处理机,并把正在运行的进程放在第i队列的队尾。

1.3 实验要求

a、使用模块化设计思想来设计; b、给出算法的流程图或伪码说明。 c、学生可按照自身条件,随意选择采用的算法,(例如:采用冒泡法编写程序,实现短进程优先调度的算法)

d、进程调度程序模拟程序只对PCB进行相应的调度模拟操作,不需要实际程序。

1.4 算法简析 a、每个进程可有三个状态,并假设初始状态为就绪状态。 b、为了便于处理,程序中的某进程运行时间以时间片为单位计算。 各进程的优先数或轮转时间数以及进程需运行的时间片数的初始值均由用户给定。 c、在优先数算法中,优先数可以先取值为(50-该进程所需时间),进程每执行一次,优先数减3,CPU时间片数(CPUtime)加1, * 进程还需要的时间片数(needtime)减1。在时间片轮转算法中,采用固定时间片

(即:每执行一次进程,该进程的执行时间片数为已执行了2个单位),这时,CPU时间片(CPUtime)数加2, * 进程还需要的时间片数(needtime)减2,并排列到就绪队列的尾上。

d、对于遇到优先数一致的情况,采用FIFO策略解决。

二、 银行家算法

2.1 概述

2.1.1 设计目的

1、了解多道程序系统中,多个进程并发执行的资源分配。

2、掌握死锁的产生的原因、产生死锁的必要条件和处理死锁的基本方法。

3、掌握预防死锁的方法,系统安全状态的基本概念。

4、掌握银行家算法,了解资源在进程并发执行中的资源分配策略。

5、理解死锁避免在当前计算机系统不常使用的原因

2.2 关于死锁

2.2.1 死锁概念:

在多道程序系统中,虽可借助于多个进程的并发执行,来改善系统的资源利用率,提高系统的吞吐量,但可能发生一种危险━━死锁。所谓死锁(Deadlock),是指多个进程在运行中因争夺资源而造成的一种僵局(Deadly_Embrace),当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。一组进程中,每个进程都无限等待被该组进程中另一进程所占有的资源,因而永远无法得到的资源,这种现象称为进程死锁,这一组进程就称为死锁进程。

2.2.2 关于死锁的一些结论:

参与死锁的进程最少是两个(两个以上进程才会出现死锁)

参与死锁的进程至少有两个已经占有资源

参与死锁的所有进程都在等待资源

参与死锁的进程是当前系统中所有进程的子集

注:如果死锁发生,会浪费大量系统资源,甚至导致系统崩溃。

2.2.3 资源分类:

永久性资源: 可以被多个进程多次使用(可再用资源),分为:可抢占资源与不可抢占资源

临时性资源:只可使用一次的资源;如信号量,中断信号,同步信号等(可消耗性资源)

“申请--分配--使用--释放”模式

2.2.4 产生死锁的四个必要条件:

1、互斥使用(资源独占)

一个资源每次只能给一个进程使用

2、不可强占(不可剥夺)

资源申请者不能强行的从资源占有者手中夺取资源,资源只能由占有者自愿释放

3、请求和保持(部分分配,占有申请)

一个进程在申请新的资源的同时保持对原有资源的占有(只有这样才是动态申请,动态分配)

4、循环等待

存在一个进程等待队列

{P1 , P2 , „ , Pn},

其中P1等待P2占有的资源,P2等待P3占有的资源,„,Pn等待P1占有的资源,形成一个进程等待环路

2.2.5 死锁的解决方案 1 产生死锁的例子

申请不同类型资源产生死锁

P1: „

申请打印机 申请扫描仪 使用

释放打印机 释放扫描仪 „ P2: „

申请扫描仪 申请打印机 使用

释放打印机 释放扫描仪 „

申请同类资源产生死锁(如内存)

设有资源R,R有m个分配单位,由n个进程P1,P2,„,Pn(n > m)共享。假设每个进程对R的申请和释放符合下列原则: * 一次只能申请一个单位 * 满足总申请后才能使用 * 使用完后一次性释放

m=2,n=3 资源分配不当导致死锁产生

2死锁预防: 定义:在系统设计时确定资源分配算法,保证不发生死锁。具体的做法是破坏产生死锁的四个必要条件之一

①破坏“不可剥夺”条件

在允许进程动态申请资源前提下规定,一个进程在申请新的资源不能立即得到满足而变为等待状态之前,必须释放已占有的全部资源,若需要再重新申请 ②破坏“请求和保持”条件

要求每个进程在运行前必须一次性申请它所要求的所有资源,且仅当该进程所要资源均可满足时才给予一次性分配 ③破坏“循环等待”条件 采用资源有序分配法:

把系统中所有资源编号,进程在申请资源时必须严格按资源编号的递增次序进行,否则操作系统不予分配。

2.2.6 安全状态与不安全状态

安全状态: 如果存在一个由系统中所有进程构成的安全序列P1,„Pn,则系统处于安全状态。一个进程序列{P1,„,Pn}是安全的,如果对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和,系统处于安全状态 (安全状态一定是没有死锁发生的) 。

不安全状态:不存在一个安全序列,不安全状态一定导致死锁。

2.3 数据结构设计

1.可利用资源向量矩阵AVAILABLE。这是一个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态地改变。如果AVAILABLE [j]= K,则表示系统中现有R类资源K个

2.最大需求矩阵MAX。这是一个n*m的矩阵,用以表示每一个进程对m类资源的最大需求。如果MAX [i,j]=K,则表示进程i需要R类资源的数目为K。

3.分配矩阵ALLOCATION。这也是一个n*m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果ALLOCATION [i,j]=K,则表示进程i当前已分得R类资源的数目为K。

4.需求矩阵NEED。这也是一个n*m的矩阵,用以表示每一个进程尚需的各类资源数。如果NEED [i,j]=K,则表示进程i还需要R类资源K个,才能完成其任务。 上述矩阵存在下述关系:

NEED [i,j]= MAX[i,j]﹣ ALLOCATION[i,j]

2.4 算法的实现 2.4.1 初始化 由用户输入数据,分别对可利用资源向量矩阵AVAILABLE、最大需求矩阵MAX、分配矩阵ALLOCATION、需求矩阵NEED赋值。 2.4.2 银行家算法

在避免死锁的方法中,所施加的限制条件较弱,有可能获得令人满意的系统性能。在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可以避免发生死锁。

银行家算法的基本思想是分配资源之前,判断系统是否是安全的;若是,才分配。它是最具有代表性的避免死锁的算法。

设进程cusneed提出请求REQUEST [i],则银行家算法按如下规则进行判断。 (1)如果REQUEST [cusneed] [i]<= NEED[cusneed][i],则转(2);否则,出错。

(2)如果REQUEST [cusneed] [i]<= AVAILABLE[cusneed][i],则转(3);否则,出错。 (3)系统试探分配资源,修改相关数据: AVAILABLE[i]-=REQUEST[cusneed][i]; ALLOCATION[cusneed][i]+=REQUEST[cusneed][i]; NEED[cusneed][i]-=REQUEST[cusneed][i]; (4)系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,进程等待。

2.4.3 安全性检查算法

(1)设置两个工作向量Work=AVAILABLE;FINISH (2)从进程集合中找到一个满足下述条件的进程,

FINISH==false; NEED<=Work; 如找到,执行(3);否则,执行(4) (3)设进程获得资源,可顺利执行,直至完成,从而释放资源。

Work+=ALLOCATION; Finish=true; GOTO 2 (4)如所有的进程Finish= true,则表示安全;否则系统不安全。

三、 页面调度算法 3.1 实验名称

页式虚拟存储管理:页面调度算法 3.2 实验目的

页式虚拟存储器实现的一个难点是设计页面调度(置换)算法,即将新页面调入内存时,如果内存中所有的物理页都已经分配出去,就要按某种策略来废弃某个页面,将其所占据的物理页释放出来,供新页面使用。本实验的目的是通过编程实现几种常见的页面调度(置换)算法,加深读者对页面思想的理解。 3.3 实验原理

页面调度算法

目前有许多页面调度算法,本实验主要涉及先进先出调度算法、最近最少调度算法、最近最不常用调度算法。本实验使用页面调度算法时作如下假设,进程在创建时由操作系统为之分配一个固定数目物理页,执行过程中物理页的数目和位置不会改变。也即进程进行页面调度时只能在分到的几个物理页中进行。

下面对各调度算法的思想作一介绍。

<1> 先进先出调度算法

先进先出调度算法根据页面进入内存的时间先后选择淘汰页面,先进入内存的页面先淘汰,后进入内存的后淘汰。本算法实现时需要将页面按进入内存的时间先后组成一个队列,每次调度队首页面予以淘汰。

<2>最近最少调度算法

先进先出调度算法没有考虑页面的使用情况,大多数情况下性能不佳。根据程序执行的局部性特点,程序一旦访问了某些代码和数据,则在一段时间内会经常访问他们,因此最近最少用调度在选择淘汰页面时会考虑页面最近的使用,总是选择在最近一段时间以来最少使用的页面予以淘汰。算法实现时需要为每个页面设置数据结构记录页面自上次访问以来所经历的时间。

<3>最近最不常用调度算法

由于程序设计中经常使用循环结构,根据程序执行的局部性特点,可以设想在一段时间内经常被访问的代码和数据在将来也会经常被访问,显然这样的页面不应该被淘汰。最近最不常用调度算法总是根据一段时间内页面的访问次数来选择淘汰页面,每次淘汰访问次数最少的页面。算法实现时需要为每个页面设置计数器,记录访问次数。计数器由硬件或操作系统自动定时清零。

缺页调度次数和缺页中断率、缺页置换率计算

缺页中断次数是缺页时发出缺页中断的次数。

缺页中断率=缺页中断次数/总的页面引用次数*100%

缺页调度次数是调入新页时需要进行页面调度的次数

缺页置换率=缺页调度次数/总的页面引用次数*100% 3.4 实验内容

(1)设计程序实现以上三种页面调度算法,要求:

①.可以选择页面调度算法类型;

②.可以为进程设置分到物理页的数目,设置进程的页面引用情况,可以从键盘输入页面序列,也可从文件中读取;

③.随时计算当前的页面调度次数的缺页中断率;

④.使用敲键盘或响应WM-TIMER的形式模仿时间的流逝;

⑤.以直观的的形式将程序的执行情况显示在计算机屏幕上;

⑥.存盘及读盘功能,可以随时将数据存入磁盘文件,供以后重复实验时使用。

(2)假定进程分配到3个物理块,对于下面的页面引用序列: (test.txt)

7-0-1-2-0-3-0-4-2-3-0-3-2-1-2-0-1-7-0-1

请分别用先进和先出调度算法,最近最少用调度算法,最近最不常用调度算法计算缺页中断次数,缺页中断率和缺页调度次数、缺页置换率。

再假定进程分配到

4、5个物理块,重复本实验。

(3)假定进程分配到3个物理块,对于下面的页面引用序列: (test2.txt)

4-3-2-1-4-3-5-4-3-2-1-5-0-7-3-8-9-0-2-1-4-7-3-9

请分别用先进先出调度算法、最近最少用调度算法,最近最不常用调度算法计算缺页中断次数,缺页中断率和缺页调度次数、缺页置换率。

再假定进程分配到

4、5个物理块,重复本实验。

(4)假定进程分配到3个物理块,使用程序的动态页面序列生成算法,生成一个页面序列,将此序列存入磁盘文件。再从磁盘文件读入该序列,用程序分别计算三种算法下的缺页中断次数、缺页中断率和缺页调度次数、缺页置换率。

第7篇:操作系统课程设计3

操作系统课程设计3 一. 银行家算法代码

package sheji;

import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;

import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.JTextField;

public class Banker extends JFrame implements ActionListener{

JTable table1; Object[][] data; JPanel p0,p1,p11,p12,p13,p14,p2,p3,p31,p32,p33,p34,p4; JLabel t1,t2,t3,t4,t5,t6,t7,t8,t9;//t10输出安全序列省去

JButton b1,b2,b3,b6,b5; TextField text01,text02,text03,text5,text6; JTextField[] text1,text2,text3,text4; JTextArea text7;

String s1,s2 = new String(); int M,N,i,j,count = 0,flag = 0; int[][]Max,Need,Allocation; int[] Available,Work,Request,Temp;

public Banker(){ super("211213067 秦瑛 银行家算法模拟系统"); p0 = new JPanel(); p1 = new JPanel(); p11 = new JPanel(); p12 = new JPanel(); p13 = new JPanel(); p14 = new JPanel(); p2 = new JPanel(); p3 = new JPanel(); p31 = new JPanel(); p32 = new JPanel(); p33 = new JPanel(); p34 = new JPanel(); p4 = new JPanel();

p0.setLayout(new GridLayout(4,1)); p1.setLayout(new GridLayout(4,1)); p3.setLayout(new GridLayout(4,1));

p1.add(p11); p1.add(p12); p1.add(p13); p1.add(p14);

p3.add(p31); p3.add(p32); p3.add(p33); p3.add(p34);

p0.add(p1); p0.add(p2); p0.add(p3); p0.add(p4);

t1=new JLabel("进程数"); t2=new JLabel("资源数"); t3=new JLabel("进程号"); t4=new JLabel("已分配资源"); t5=new JLabel("资源最大需求"); t6=new JLabel("可用资源"); t7=new JLabel("请求资源进程号"); t8=new JLabel("请求资源为"); t9=new JLabel("安全检测");

b1=new JButton("确定"); b2=new JButton("添加"); b3=new JButton("确定"); b5=new JButton("请求"); b6=new JButton("安全检测");

text1 = new JTextField[6]; text2 = new JTextField[6]; text3 = new JTextField[6]; text4 = new JTextField[6];

for(int i=0;i<6;i++){

text1[i] = new JTextField(4);

text2[i] = new JTextField(4);

text3[i] = new JTextField(4);

text4[i] = new JTextField(4); }

text01 = new TextField(4); text02 = new TextField(4); text03 = new TextField(4); text5 = new TextField(4); text6 = new TextField(50);

String[] columnNames1 = {"进程号","资源最大需求Max","已分配的资源Allocation","需要的资源Need","可利用的资源Available"}; data = new Object[100][5]; table1 = new JTable (data, columnNames1); table1.setPreferredScrollableViewportSize(new Dimension(550, 100)); table1.setRowHeight (20); table1.doLayout(); JScrollPane pane1 = new JScrollPane (table1);

text7 = new JTextArea(" ",6,40); JScrollPane pane2 = new JScrollPane(text7); text7.setEditable(false);

p11.add(t1); p11.add(text01); p11.add(t2); p11.add(text02); p11.add(b1); p12.add(t3); p12.add(text03); p12.add(b2); p13.add(t4); for(int i=0;i<6;i++)

p13.add(text1[i]); p14.add(t5); for(int i=0;i<6;i++)

p14.add(text2[i]); p2.add(pane1);

p31.add(t6); for(int i=0;i<6;i++)

p31.add(text3[i]); p31.add(b3); p32.add(t7); p32.add(text5); p32.add(t8); for(int i=0;i<6;i++)

p32.add(text4[i]); p33.add(b6); p33.add(b5); p34.add(t9); p34.add(text6); p4.add(pane2);

b1.addActionListener(this); b2.addActionListener(this); b3.addActionListener(this); b5.addActionListener(this); b6.addActionListener(this);

p0.setBackground(Color.lightGray);

setContentPane (p0); this.setVisible(true); this.pack();

}

public void Diguisafe(int k,int n) {//递归求解安全序列函数

int m,a; if(k==n){

for(int j=0;j

Work[j] = Available[j];

if(Safe()==1){

for(a=0;a

s1 += Temp[a]+"->";

s1 +=Temp[a]+""+" ";

count++;

for(int j=0;j

Work[j] = Available[j];

} } else

for(i=k;i<=n;i++){//n全排列

m=Temp[k];

Temp[k]=Temp[i];

Temp[i]=m;

Diguisafe(k+1,n);

m=Temp[k];

Temp[k]=Temp[i];

Temp[i]=m;

} }

public int Safe(){//求是否安全序列

int i; for(i=0;i

if(Small(Temp[i]-1)==1){

CountWork(Temp[i]-1);

continue;

}

else break;

} if(i==M)return 1; else return 0;

}

public void CountWork(int i){//计算工作向量函数

for(int j=0;j

Work[j] = Work[j]+Allocation[i][j];

}

public int Small(int i){//判断是否满足需求函数

int flag = 0; for(int j=0;j

if(Need[i][j]<=Work[j])flag=1;

else{

flag =0;

break;

} } return flag;

} public int Req_need(){//判断是否满足需求资源函数

int flag = 0; for(int i=0;i

if(Need[j-1][i]>=Request[i])flag = 1;

else{

flag=0 ;break;

} } return flag; }

public int Req_ava(){//判断是否满足可用资源数

int flag=0; for(int i=0;i

if(Available[i]>=Request[i]) flag=1;

else

{

flag=0;break;

} } return flag; }

public void Changedata(){//预分配函数

String s_available = new String(); for(int i=0;i

Available[i] = Available[i]-Request[i];

Allocation[j-1][i] = Allocation[j-1][i]+Request[i];

Need[j-1][i] = Need[j-1][i]-Request[i];

s_available += Available[j]+" "; } data[0][4] = s_available; table1.repaint(); text6.setText(" "); text7.setText(" "); }

public void Qingqiu(){//资源请求函数 count = 0; if(Req_need()==1&&Req_ava()==1){//不满足需求

Changedata(); //预分配

} else{

s2 ="不能分配";

text6.setText(s2); } }

public void actionPerformed(ActionEvent e){ if(e.getSource()==b1){

M = Integer.parseInt(text01.getText());

N = Integer.parseInt(text02.getText());

Max = new int[M][N];

Allocation = new int[M][N];

Need = new int[M][N];

Available = new int[N];

Request = new int[N];

Work = new int[N];

Temp = new int[M]; }

if(e.getSource()==b2){ i = Integer.parseInt(text03.getText()); int max,allocation; String s_max,s_need,s_allocation; s_max = new String(); s_need = new String(); s_allocation = new String();

for(int j=0;j

for(int j=0;j

if(e.getSource()==b3){ int available; String s_available=new String(); for(int j=0;j

available = Integer.parseInt(text3[j].getText());

Available[j] = available;

s_available += Available[j]+" "; } data[0][4] = s_available; table1.repaint(); }

if(e.getSource()==b5) { flag =1; //请求

int request; text6.setText(" "); text7.setText(" "); j = Integer.parseInt(text5.getText()); for(int i=0;i

request = Integer.parseInt(text4[i].getText());

Request[i] = request; } Qingqiu(); }

if(e.getSource()==b6){//安全序列

s1=new String();

count=0; Diguisafe(0,M-1); if(count==0&&flag==0){

s2 ="系统处于不安全状态,不能请求"; } else if(count==0&&flag==1){

s2 ="系统处于不安全状态,不能分配"; } else

s2="有"+count+"个安全序列,"; text7.setText(s1); text6.setText(s2); flag = 0; } } public static void main(String[] args){

new Banker(); } } 二. 运行界面

进入界面:

数据填充检测:

第8篇:操作系统课程设计文件管理

#include "stdio.h" #include "string.h" #include "malloc.h"

#include "stdlib.h"

#define MAX 1000 struct file/*普通文件的结构体*/ { //int type;//0无作用,当做一个空节点存在;1为记录型文件;2为执行文件

//前两个变量为文件的权限设置,1为允许操作,0为不允许操作

int write;//可写

int read;//可读

int length;//文件的长度

char ch[MAX]; }; typedef struct file File;

typedef struct ffile/*定义文件类型的结构体*/ { int type;//1为文件夹; 2为文件;

char name[20];//文件(夹)名字

int open;//文件打开标志,0为关,1为开

File iffile;//如果为文件时有的信息

struct ffile *parent;//指向上一级文件的指针

struct ffile *brother;//指向同级兄弟文件(夹)的指针

struct ffile *child;//指向下一级文件(夹)的指针 }Ffile; typedef Ffile *FFile;

/*typedef struct Open/*记录打开文件的结构体 { char name[20];//记录打开文件(夹)的名字

FFile* add;//记录打开文件上一级文件地址的指针 }Open;*/

//全局变量

FFile user1;//用户1 FFile user2;//用户2 FFile copyf;//记录被复制文件(夹)的上一级文件地址 //Open openf[20];//记录打开文件的队列

FFile init(void)/*初始化,创建根结点*/ { FFile c; c=(Ffile*)malloc(sizeof(Ffile));

c->type=2; c->open=0; //c->iffile.type=2; c->iffile.write=1; c->iffile.read=1; c->iffile.length=0; strcpy(c->name,"file1"); c->parent=NULL; c->child=NULL; c->brother=NULL; strcpy(c->iffile.ch,"NULL"); return(c); }

/*void initopen() { int a,b; a=20; for(b=1;b<=a;b++) {

openf[b].add=NULL; } }*/

//传递要显示文件的parent的地址

void show(FFile user)/*显示当前界面存在的文件*/ { user=user->child; if(user==NULL) {

printf("该文件内没有任何文件(夹)。 "); return; } printf(" "); for(;user!=NULL;){ printf("<%s",user->name); if(user->type==2) {

/*if(user->iffile.type==1)

printf("/记录型文件/");

else

printf("/执行文件/");*/

printf("/%dk",user->iffile.length); } else {

printf("/文件夹");

}

printf("> ");

user=user->brother; } }

void creatf(FFile user)/*创建文件 || 文件夹*/ { FFile parent; char ch[20]; //FFile user0; //parent=(Ffile*)malloc(sizeof(Ffile)); parent=user; printf("输入要创建文件(夹)的名字: ");

scanf("%s",ch); if(user->child==NULL) {

user->child=(Ffile*)malloc(sizeof(Ffile));

user=user->child; }else {

user=user->child;

for(;;)

{

if(user->type==0)//开端的空结点,用新结点覆盖

break;

if(!strcmp(user->name,ch))

{

printf("错误:该文件名已经存在,文件(夹)创建失败! ");

return;

}

if(user->brother==NULL)

{

user->brother=(Ffile*)malloc(sizeof(Ffile));

user=user->brother;

break;

}

user=user->brother;

}

} }

//设置新文件(夹)的信息 strcpy(user->name,ch); printf("选择创建对象:1文件夹; 2文件; "); scanf("%d",&user->type); user->open=0; if(user->type==2)//添加文件信息 {

//printf("选择文件类型:1记录型文件;2执行文件; "); //scanf("%d",&user->iffile.type); printf("能否对文件进行读:0禁止;1允许; "); scanf("%d",&user->iffile.read); printf("能否对文件进行写:0禁止;1允许; "); scanf("%d",&user->iffile.write); //printf("设置文件大小(单位:K): "); //scanf("%d",&user->iffile.length); user->iffile.length=0; strcpy(user->iffile.ch,"NULL"); } user->brother=NULL; user->child=NULL; user->parent=parent; printf("文件创建成功! "); void deletechildtree(FFile user)/*删除子树--结合deletefile();使用*/ { if (user->brother!=NULL)//从下到上,从右到左删除

{

deletechildtree(user->brother); } if (user->child!=NULL) {

deletechildtree(user->child); } if(user!=NULL) {

free(user); } }

void deletefile(FFile user,char ch[20])/*删除文件 || 文件夹*/ { FFile p,parent;

int a; parent=user; if(user->child==NULL) { printf("错误:删除失败,该目录下没有可删除的文件(夹)! "); return; } user=user->child; p=user; for(a=1;;a++)//找出要删除文件的所在位置 { if(!strcmp(user->name,ch))

break; if(user->brother==NULL) {

printf("错误:删除失败,当前位置没有该文件! ");

return; }

if(a>1)

p=user; user=user->brother; } if(user->open==1)//判断文件的开关情况 {

} printf("错误:删除失败,选择文件处于打开状态! "); return; if(p==user)//被删文件在文件队列的开头 { if(user->brother==NULL)//该文件队列只有有一个文件

{

parent->child=NULL;

if(user->child!=NULL)//删除的是文件(夹)子树

{

deletechildtree(user); }else {

free(user);//删除的是文件(夹)结点

} printf("删除成功! "); return; } //文件队列有多个文件 p=user->brother;

} parent->child=p; p->parent=parent; if(user->child!=NULL) { deletechildtree(user); }else { free(user); } printf("删除成功! "); return; else//被删文件不在队列开头 {

if(user->brother==NULL)//被删文件在文件队列最末尾 { p->brother=NULL; if(user->child!=NULL) {

deletechildtree(user); }else {

free(user); }

} printf("删除成功! "); return;

//被删文件在文件队列中间

p->brother=user->brother;

if(user->child!=NULL)

{

deletechildtree(user);

}

else

{

free(user);

} } printf("删除成功! "); }

FFile openfolder(FFile user)/*打开文件夹*/ {

} //int a,b; //a=0; /*if(user->child==NULL) { user->child=(Ffile*)malloc(sizeof(Ffile)); user->child->type=0; user->child->brother=NULL; user->child->parent=user; user->child->child=NULL;

} /*for(b=1;b<=20;b++) { if(openf[b].add!=NULL)

a++; } if(a==20) { printf("错误:打开列表溢出!"); return(user); } for(b=1;;b++) { if(openf[b].add==NULL)

break; }*/

user->open=1;//设置文件为打开 //strcpy(openf[b].name,user->name); //openf[b].add=user; printf("文件夹打开成功。 "); return(user);//返回被打开的文件夹的地址

void openfile(FFile user)/*打开普通文件*/ { if(user->open==1) {

printf("错误:打开失败,此文件已经被打开! ");

return; } user->open=1; printf("普通文件打开成功! "); }

FFile openff(FFile user)/*打开文件(夹)*/ {

char ch[20]; FFile parent;

int a; printf("选择要打开的文件名: "); scanf("%s",ch);

parent=user; if(user->child==NULL) {

printf("错误:打开失败,该目录下没有可打开的文件(夹)! "); return(parent); } user=user->child; for(a=1;;a++)//找出要打开文件的所在位置 { if(!strcmp(user->name,ch))

break; if(user->brother==NULL) {

printf("错误:打开失败,当前位置没有该文件! ");

return(parent); }

user=user->brother; } if(user->type==1) {

printf("开始打开文件夹。。。 "); user=openfolder(user); } else if(user->type==2) {

printf("开始打开普通文件。。。 ");

openfile(user);

user=user->parent; } return(user); }

void closefile(FFile user)/*关闭普通文件*/ {

char ch[20]; int a; printf("选择要打开的文件名: "); scanf("%s",ch); if(user->child==NULL) { printf("错误:关闭失败,该目录下没有可关闭的文件! "); return; } user=user->child; for(a=1;;a++)//找出要关闭文件的所在位置 { if(!strcmp(user->name,ch))

break; if(user->brother==NULL) {

printf("错误:关闭失败,当前位置没有该文件! ");

return; }

user=user->brother; } if(user->open==0) {

printf("错误:关闭失败,该文件已经是关闭状态! ");

return; } user->open=0; printf("文件已经成功关闭!"); } /*没有文件夹关闭原因:

文件夹一打开就会跳向打开的新文件里 而文件夹关闭就会直接返回上一级的目录, 若想整个文件夹都关闭,直接退出就可以了 因此不会直接关闭某个特定的文件*/

FFile backf(FFile user)/*返回上一层目录*/ { if(user->parent==NULL) {

printf("错误:返回失败,此处是最顶层目录! ");

return(user); }

} user->open=0; user=user->parent; return(user); void readfile(FFile user)/*读文件*/ { char ch[20]; int a;

printf("选择要读取的文件名: "); scanf("%s",ch); if(user->child==NULL) { printf("错误:读取失败,该目录下没有可读取的文件! "); return; } user=user->child; for(a=1;;a++)//找出要读取文件的所在位置 { if(!strcmp(user->name,ch))

break; if(user->brother==NULL) {

printf("错误:读取失败,当前位置没有该文件! ");

return; }

user=user->brother; } if(user->open==0) { printf("错误:文件读取失败,该文件处于关闭状态! "); return; } else if(user->iffile.read==0) { printf("错误:文件读取失败,该文件受保护,禁止读取! "); return; } printf("读操作,该文件中的内容: "); if(!strcmp(user->iffile.ch,"NULL")) { printf("该文件内没有可读内容! "); return;

} } printf("%s ",user->iffile.ch); printf("文件读取成功! "); void writefile(FFile user)/*写文件*/ { char ch[20]; int a;

} printf("选择要进行写操作的文件名: "); scanf("%s",ch); if(user->child==NULL) { printf("错误:写操作失败,该目录下没有可写的文件! "); return; } user=user->child; for(a=1;;a++)//找出要读取文件的所在位置 { if(!strcmp(user->name,ch))

break; if(user->brother==NULL) {

printf("错误:写操作失败,当前位置没有该文件! ");

return; }

user=user->brother; } if(user->open==0) { printf("错误:文件写操作失败,该文件处于关闭状态! "); return; } else if(user->iffile.write==0) { printf("错误:文件写操作失败,该文件受保护,禁止写! "); return; } printf("写操作,输入内容: "); scanf("%s",user->iffile.ch); user->iffile.length=strlen(user->iffile.ch); printf("文件进行写操作成功! ");

FFile copyfile(FFile user,FFile copyf)/*拷贝文件*/ { char ch[20]; int a; printf("选择要进行拷贝的文件(夹)名: "); scanf("%s",ch);

if(user->child==NULL) {

printf("错误:拷贝失败,该目录下没有可拷贝的文件! ");

return(NULL); } user=user->child; for(a=1;;a++)//找出要拷贝文件的所在位置,用user替代

{

if(!strcmp(user->name,ch))

break;

if(user->brother==NULL)

{

printf("错误:拷贝失败,当前位置没有该文件! ");

return(NULL);

}

user=user->brother; } copyf=user;

} printf("拷贝成功! "); return(copyf); FFile fenpei(FFile copyf,FFile user,FFile parent)/*粘贴时,给已拷贝项分配内存空间,以及给对应信息赋值*/ { user=(Ffile*)malloc(sizeof(Ffile));

//parent对child的连接,以及brother之间的连接已经完成

if(copyf->brother==NULL && copyf->child==NULL) {

user->parent=parent;

user->child=NULL;

user->brother=NULL; }

else{ if(copyf->brother!=NULL) {

user->brother=fenpei(copyf->brother,user->brother,parent); //brother连接,兄弟节点有同一个父结点

user->brother->parent=user->parent; } else { user->brother=NULL; } if(copyf->child!=NULL) { //parent=p; user->child=fenpei(copyf->child,user->child,user);

user->child->parent=user;//完成child对parent的连接

//child连接,自己孩子的父结点就是自己

} else {

user->child=NULL;

user->child->parent=user; } }

//设置结点对应的信息

strcpy(user->name,copyf->name); user->open=copyf->open; user->type=copyf->type; if(user->type==2) {

user->iffile.length=copyf->iffile.length;

user->iffile.read=copyf->iffile.read;

//user->iffile.type=copyf->iffile.type;

user->iffile.write=copyf->iffile.write;

strcpy(user->iffile.ch,copyf->iffile.ch); }

return(user); }

void prastefile(FFile user,FFile copyf)/*粘贴文件*/ //user是要粘贴的地方,copyf是要粘贴的内容, //有相同文件名的会判断会不会覆盖,或者是重命名 //在原树中进行新建操作 { int i,j; char ch[20]; FFile p,user0,parent; parent=user;//记录父结点

user=user->child;

p=user;//记录当前结点的前一个brother结点 strcpy(ch,"NULL"); if(copyf==NULL)//判断有没有拷贝文件 {

printf("错误:粘贴失败,还没有拷贝任何文件(夹)! ");

return; }

//p=(Ffile*)malloc(sizeof(Ffile)); //p->child=(Ffile*)malloc(sizeof(Ffile)); //先给粘贴项分配内存空间

//p->child=fenpei(copyf,p->child,p);

if(user==NULL) //当前位置没有任何文件结点

{

} user=fenpei(copyf,user,parent);//是他自己要分配,不是孩子结点!!! parent->child=user; user->brother=NULL; user->parent=parent; return; //该位置没有任何文件 for(j=1;;j++) { if(user->type==0) //开端的空结点,用新结点覆盖,即:当前位置没有文件结点

{

user=user->parent;

deletechildtree(p);

user=fenpei(copyf,user->child,user);//返还增加的结点

user->brother=NULL;

user->parent=parent;

parent->child=user;

} return; if(!strcmp(user->name,copyf->name)) {

printf("提示:该文件名已经存在! ");

printf("请重命名文件: ");

printf("输入新文件名: ");

scanf("%s",ch);

} if(user->brother==NULL) //普通的退出条件

{

break; } p=user; user=user->brother; } user->brother=fenpei(copyf,user->brother,user->parent); user->brother->parent=user->parent; //若要更名,粘贴分配完内存空间返回时再改变

if(strcmp(ch,"NULL"))

strcpy(user->brother->name,ch); printf("粘贴成功。 "); }

void showroute(FFile user)/*显示当前路径*/ { if(user->parent!=NULL) {

showroute(user->parent); } printf("%s/",user->name);//路径中每个结点的输出项 }

void change(FFile user) { char ch[20]; int a,b;

if(user->child==NULL)

{

} printf("错误:属性修改失败,该目录下没有可修改的文件! "); return; printf("选择要进行属性修改的文件(夹)名: "); scanf("%s",ch); user=user->child; for(a=1;;a++)//找出要拷贝文件的所在位置,用user替代 { if(!strcmp(user->name,ch))

break; if(user->brother==NULL) {

printf("错误:属性修改失败,当前位置没有该文件! ");

return; }

user=user->brother; } if(user->type==1) { printf("错误:文件夹不能进行属性修改! "); return; } for(;;) {

printf("1.修改读权限; "); printf("2.修改写权限; "); printf("3.返回; "); printf("选择操作: "); scanf("%d",&a); if(a==1) { printf("0.禁止;

1.允许; "); printf("请选择: "); scanf("%d",&b); user->iffile.read=b; printf("修改成功! "); } else if(a==2) { printf("0.禁止;

1.允许; "); printf("请选择: "); scanf("%d",&b); user->iffile.write=b;

}

} printf("修改成功! "); } else if(a==3) { return; } else { } printf("错误:没有该操作! "); void main()/*主函数*/ {

FFile d,e,f;//f记录当前显示界面父结点位置 int a,b,c; char ch[20]; a=0; printf("******************************目录****************************** "); printf("

1.选择用户 "); printf("

2.退出 ");

printf("**************************************************************** "); for(;;) {

printf("选择操作: "); scanf("%d",&a); if (a==1) { printf("选择用户: "); printf("1.user1; 2.user2; "); scanf("%d",&b); break; } else if (a==2) { printf("欢迎使用。 "); exit(0);//系统退出的操作码 } else { printf("错误:没有该操作! ");

} } //初始化打开列表 //initopen(); //初始化各个用户的信息

//copyf=(Ffile*)malloc(sizeof(Ffile)); //copyf=NULL; copyf=NULL; user1=init(); strcpy(user1->name,"user1"); user2=init(); strcpy(user2->name,"user2"); d=init(); e=init(); user1->child=d; user2->child=e; d->parent=user1; e->parent=user2; printf("%d",user1->child->type); if(b==1){ printf("已经进入user1系统 "); f=user1; show(user1); }else{

} printf("已经进入user2系统 "); f=user2; show(user2);

for(;;){ printf("**************************************************************** "); printf("1.创建文件(夹)

5.读文件

9.显示当前路径

"); printf("2.删除文件(夹)

6.写文件

10.返回上一层目录

"); printf("3.打开文件(夹)

7.拷贝文件

11.改变普通文件属性 "); printf("4.关闭普通文件

8.粘贴文件

12.退出 "); printf("**************************************************************** "); printf("选择操作: "); scanf("%d",&c); if(c==12) {

break; }else if(c==1) { creatf(f); } else if(c==2) {

printf("选择要删除的文件(夹)的名字: "); scanf("%s",ch); deletefile(f,ch); } else if(c==3) { f=openff(f); } else if(c==4) { closefile(f); } else if(c==5) { readfile(f); } else if(c==6) { writefile(f); } else if(c==7) { copyf=copyfile(f,copyf); } else if(c==8) { prastefile(f,copyf); copyf=NULL; } else if(c==9) { printf("路径为: "); showroute(f); printf(" "); } else if(c==10) {

}

f=backf(f);

} else if(c==11) { change(f); } else { continue; } show(f); } printf("欢迎使用! ");

第9篇:c语言课程设计 学生选修课程系统设计

题目:学生选修课程系统设计

功能:假定有n门课程,每门课程有课程编号,课程名称,课程性质,总学时,授课学时,实验或上机学时,学分,开课学期等信息。试设计一选修课程系统。

分步实施:

1、 初步完成总体设计,搭好框架,确定人机对话界面,确定函数个数;

2、 建立一个文件,将每条记录信息写入文件中并能显示于屏幕上

3、完成上述添加、查找(课程编号、课程名称、课程性质等)、修改等功能。

4、进一步要求:学生选修课程(可选项)

要求:

1、用C语言实现程序设计;

2、利用结构体数组实现信息的数据结构设计;

3、系统的各个功能模块要求用函数的形式实现;

4、界面友好(良好的人机交互),程序加必要的注释。

课程设计实验报告要求:

1、预习报告:题目、课程设计任务、数据结构、程序的总体设计(算法)、模块划分 。

2、实验总结报告:流程图、主要源程序代码(需打印)、测试情况及调试中问题与解决方案、

小结等。

上一篇:公司员工工作规范下一篇:宿舍文明策划