软考 软件设计师
计算机基本工作原理
奇偶校验
奇偶校验是一种基于数据位中 1 的个数的简单错误检测技术
- 奇校验:校验位确保所有位的总和为奇数
- 偶校验:校验位确保所有位的总和为偶数
专业术语:
- 校验位:附加的位,用于实现奇偶校验
- 位错误:数据传输过程中的单个位变化
形象例子:
假设我们传输一个 5 位的二进制数11010
- 奇校验:计算 1 的个数(3 个),添加校验位使其成为奇数,结果为
110101
(4 个 1) - 偶校验:计算 1 的个数(3 个),添加校验位使其成为偶数,结果为
110100
(4 个 1)
CRC 循环冗余码
循环冗余校验(CRC)是一种广泛使用的错误检测码,它通过将数据视为一个多项式,并使用约定的生成多项式进行模二除法,得到的余数作为校验码附加到数据后面。CRC 能够检测出多种错误类型,包括奇数个错误位、偶数个错误位以及等于或小于校验码长度的突发错误
形象例子:
假设我们有数据 101011
,生成多项式为 x^4 + x + 1
,其二进制表示为 10011
- 在数据后附加 4 个 0(因为生成多项式的长度为 5 位,所以 k=4),得到
10101100000
- 使用生成多项式
10011
对这个新数据进行模二除法 - 计算得到的余数为
0100
,这就是 CRC 校验码 - 将 CRC 校验码附加到原始数据后面,形成最终的数据包
1010110100
发送出去
在接收端,如果数据在传输过程中没有出错,那么使用相同的生成多项式进行模二除法后,余数应该为 0。如果余数不为 0,则表明数据在传输过程中出现了错误
海明码
海明码(Hamming Code)是一种单比特错误检测和纠正编码。它通过在数据中添加校验位来实现这一功能,确保数据传输的准确性
计算校验位:
- 确定校验位数量 ( r ):满足 ( ),其中 ( m ) 是原始数据位数
- 校验位放置在 ( ) 的位置(例如第 1、2、4 位等)
- 计算每个校验位,确保其覆盖的位(包括自身)的异或值为 0(偶校验)
编码示例:
假设有 4 位数据 1011
,需要计算海明码
计算需要的校验位数 ( r ):满足 ( ),得 ( r = 3 )
校验位位置:第 1 位、第 2 位、第 4 位
计算校验位:
- ( P_1 ) 覆盖第 1、3、5、7 位:( )
- ( P_2 ) 覆盖第 2、3、6、7 位:( )
- ( P_4 ) 覆盖第 4、5、6、7 位:( )
编码结果:
10110011
纠错示例:
接收到的数据为 10110101
,第 5 位出错
重新计算校验位:
- ( P_1 ):( )(错误)
- ( P_2 ):( )
- ( P_4 ):( )
错误位置:第 5 位(由 ( ) 指示)
纠正错误:将第 5 位从 0 改为 1,纠正后的数据为
10110011
海明码广泛应用于计算机内存和数据存储中,以确保数据的完整性和准确性
码距最小为
浮点数表示
设 16 位浮点数,其中阶符 1 位、阶码值 6 位、数符 1 位、尾数 8 位。若阶码用移码表示,尾数用补码表示,则该浮点数所能表示的数值范围是()

原码、反码、补码、移码
- 原码、反码、补码和移码是计算机中用于表示有符号整数的不同编码方式
- 原码:直接在二进制数前面加上符号位(0 表示正数,1 表示负数)
- 反码:正数的反码与原码相同,负数的反码是原码除符号位外,其他各位取反
- 补码:正数的补码与原码相同,负数的补码是反码加 1
- 移码:用于表示浮点数阶码,偏移量通常是 ,其中 n 是位数
例子:假设我们有一个 4 位的二进制数,表示整数-5 和 +5
原码:
- +5:0101
- -5:1011
反码:
- +5:0101
- -5:1001
补码:
- +5:0101
- -5:1010
移码(偏移量为 (2^{3} = 8)):
- +5:0101(原码)+ 8 = 1101
- -5:1011(原码)+ 8 = 1111
存储系统
信息安全和病毒防护
网络攻击
网络攻击可以分为两大类:主动攻击和被动攻击。这两类攻击的主要区别在于攻击者的行为对目标系统的影响和攻击者的隐蔽性
被动攻击
被动攻击是指攻击者从网络上窃听他人的通信内容,通常把这类攻击称为截获。被动攻击不会直接与目标系统交互,而是通过监听或分析网络流量来获取信息。这类攻击通常难以被检测到,因为它们不会改变系统的状态
举例:
- 窃听(Eavesdropping) :攻击者通过监听网络流量,获取敏感信息,如用户名、密码、信用卡信息等
- 流量分析(Traffic Analysis) :攻击者通过分析网络流量模式,推断出通信双方的身份、通信频率、数据量等信息,即使无法直接获取通信内容
主动攻击
主动攻击是指通过一系列的方法,主动地获取并向被攻击对象实施破坏的一种攻击方式。这类攻击通常会留下明显的痕迹,容易被检测到
举例:
- 拒绝服务攻击(DoS/DDoS) :对信息或其他资源的合法访问被无条件地阻止。攻击者通过向目标服务器发送大量请求,使其无法正常处理合法用户的请求,从而导致服务不可用
- 系统干涉:攻击者获取系统访问权,从而干涉系统的正常运行。例如,攻击者可能通过漏洞获取管理员权限,进而控制系统
- 修改数据命令:截获并修改网络中传输的数据命令。例如,在中间人攻击(Man-in-the-Middle, MITM)中,攻击者拦截并篡改通信双方的数据,窃取敏感信息或修改数据
总结
- 被动攻击:通过监听或分析网络流量获取信息,如窃听和流量分析
- 主动攻击:直接与目标系统交互,试图改变系统状态或窃取信息,如拒绝服务攻击、系统干涉和修改数据命令
入侵检测
入侵检测技术包括专家系统、模型检测、简单匹配;漏洞扫描不是入侵检测的内容
加密算法
- RSA 是一种非对称加密算法,由于加密和解密的密钥不同,因此便于密钥管理和分发,同时在用户或者机构之间进行身份认证方面有较好的应用。然而,RSA 的加密速度相对较慢,不适合对大量明文进行加密传输
- SHA-1 是一种安全散列算法,常用于对接收到的明文输入产生固定长度的输出,来确保明文在传输过程中不会被篡改。SHA-1 主要用于数据完整性校验,而不是加密明文,因此不适合对大量明文进行加密传输
- MD5 是一种使用最为广泛的报文摘要算法,但它已经被证明存在安全漏洞,不推荐用于加密传输
- RC5 是一种用于对明文进行加密的算法,在加密速度和强度上,均较为合适,适用于大量明文进行加密并传输
程序设计语言基本概念
文件管理、存储管理
位示图的大小

字编号、位编号



分页存储
分页存储管理方式是一种内存管理技术,用于将进程的逻辑地址空间划分为固定大小的页(pages),并将物理内存划分为同样大小的页框(page frames)。通过这种方式,操作系统可以更有效地管理内存,提高内存利用率,并支持虚拟内存
分页存储管理方式的主要特点
固定大小的页和页框:
- 页(Page) :进程的逻辑地址空间被划分为固定大小的页。每个页的大小通常是 2 的幂次方,例如 4KB、8KB 等
- 页框(Page Frame) :物理内存被划分为同样大小的页框。每个页框的大小与页的大小相同
页表(Page Table) :
- 每个进程都有一个页表,用于将逻辑页号映射到物理页框号。页表中的每个条目(entry)包含逻辑页号和对应的物理页框号
- 页表通常存储在内存中,但现代操作系统可能会使用硬件支持(如 TLB,Translation Lookaside Buffer)来加速地址转换
地址转换:
- 逻辑地址由两部分组成:页号(Page Number)和页内偏移量(Page Offset)
- 通过页表,操作系统可以将逻辑页号转换为物理页框号,然后结合页内偏移量生成物理地址
内存保护和共享:
- 分页存储管理方式支持内存保护,通过页表中的权限位(如读、写、执行权限)来控制对内存的访问
- 多个进程可以共享相同的物理页框,从而实现内存共享
虚拟内存:
- 分页存储管理方式支持虚拟内存,允许进程的逻辑地址空间大于物理内存的大小
- 当物理内存不足时,操作系统可以将部分页换出到磁盘(称为交换或分页),并在需要时将其换回内存
分页存储管理方式的优点
提高内存利用率:
- 通过将内存划分为固定大小的页和页框,操作系统可以更灵活地分配和管理内存,减少内存碎片
支持虚拟内存:
- 分页存储管理方式支持虚拟内存,允许进程的逻辑地址空间大于物理内存的大小,从而提高系统的并发性和多任务处理能力
简化内存管理:
- 分页存储管理方式简化了内存管理,操作系统只需管理页和页框的分配和回收,而不需要考虑进程的连续性
支持内存保护和共享:
- 通过页表中的权限位,操作系统可以实现内存保护,防止非法访问。同时,多个进程可以共享相同的物理页框,从而实现内存共享
分页存储管理方式的缺点
地址转换开销:
- 每次内存访问都需要进行地址转换,这会增加一定的开销。现代操作系统通过使用 TLB 等硬件支持来加速地址转换
页表占用内存:
- 每个进程都需要一个页表,如果进程的逻辑地址空间很大,页表可能会占用较多的内存
页面置换开销:
- 当物理内存不足时,操作系统需要进行页面置换(将部分页换出到磁盘),这会增加系统的开销和延迟
总结
分页存储管理方式是一种重要的内存管理技术,通过将逻辑地址空间和物理内存划分为固定大小的页和页框,提高了内存利用率,支持虚拟内存,简化了内存管理,并实现了内存保护和共享。尽管存在一些缺点,如地址转换开销和页表占用内存,但现代操作系统通过硬件支持和优化技术有效地解决了这些问题

请求页式存储管理
磁盘调度
磁盘调度管理中,先进行移臂调度寻找磁道,再进行旋转调度寻找扇区
磁盘容量


设备管理、作业管理

软件工程概述
瀑布模型将开发阶段描述为从一个阶段瀑布般地转换到另一个阶段的过程
原型模型中,开发人员快速地构造整个系统或者系统的一部分以理解或澄清问题
增量模型是把软件产品作为一系列的增量构件来设计、 编码、集成和测试, 每个构件由多个相互作用的模块组成, 并且能够完成特定的功能
喷泉模型开发过程中以用户需求为动力, 以对象为驱动,适合于面向对象的开发方法
要解决这个问题,我们需要理解不同软件开发模型的特点,并确定哪种模型最不适宜用于开发一个需要频繁变更和灵活应对变化的软件
常见的软件开发模型
瀑布模型(Waterfall Model) :
- 特点:线性顺序,阶段分明,每个阶段完成后才能进入下一个阶段
- 优点:结构清晰,易于管理
- 缺点:不灵活,难以应对需求变更
迭代模型(Iterative Model) :
- 特点:将开发过程分为多个迭代周期,每个迭代周期产生一个可执行版本
- 优点:灵活性较高,能够逐步完善和适应需求变更
- 缺点:需要良好的规划和管理
增量模型(Incremental Model) :
- 特点:将系统分为多个增量,每个增量都是一个可执行的子系统
- 优点:灵活性较高,能够逐步完善和适应需求变更
- 缺点:需要良好的规划和管理
螺旋模型(Spiral Model) :
- 特点:结合了瀑布模型和迭代模型的特点,每个周期包括风险分析、工程实现和评审
- 优点:灵活性高,能够应对需求变更和风险
- 缺点:复杂度高,需要丰富的经验和技能
敏捷模型(Agile Model) :
- 特点:强调迭代和增量开发,注重客户反馈和团队协作
- 优点:高度灵活,能够快速响应需求变更
- 缺点:需要良好的团队协作和沟通
分析题目需求
题目描述的软件需要监控产品的生产和销售过程,从购买各种材料开始,到产品的加工和销售进行全程跟踪。购买材料的流程、产品的加工过程以及销售过程可能会发生变化
选择最不适宜的模型
根据题目描述,软件的需求可能会频繁变更,因此需要一个灵活性较高的开发模型。瀑布模型由于其线性顺序和难以应对需求变更的特点,最不适宜用于这种场景
软件工程是一种层次化的技术体系,自下而上依次涵盖质量、过程、方法和工具。任何工程方法均需以有组织的质量承诺为基石。软件工程的核心在于过程,它是将技术融合在一起的粘合剂,确保计算机软件得以合理且及时地开发。过程定义了关键过程区域,构成了软件项目管理与控制的基础;方法则提供了构建软件的技术指导,涵盖了众多任务。方法亦依赖于一系列基本原则,这些原则贯穿于各个技术领域,并包括建模活动及其他描述性技术;工具则为过程和方法提供自动化或半自动化的支持,例如计算机辅助软件工程(CASE)。软件工程的基本要素主要包括方法、工具和过程
数据库
关系代数
关系代数中的操作符
选择(Selection):用符号 σ 表示,用于从关系中选择满足特定条件的元组
投影(Projection):用符号 π 表示,用于从关系中选择特定的列
自然连接(Natural Join):用符号 ⨝ 表示,用于连接两个关系,并自动匹配相同列名的列
笛卡尔积(Cartesian Product):用符号 × 表示,用于生成两个关系的所有可能组合
RxS


数据库范式
数据库范式介绍
数据库范式(Normalization)是数据库设计中的一个重要概念,用于减少数据冗余和提高数据完整性。范式通过一系列规则来规范化数据库表结构,确保数据存储的有效性和一致性。常见的范式包括第一范式(1NF)、第二范式(2NF)、第三范式(3NF)和第四范式(4NF)
第一范式(1NF)
定义:一个关系模式 R 属于第一范式,当且仅当 R 中的每个属性都是原子的(不可再分的)
要点:
- 每个属性必须是单一值,不能包含多个值或嵌套结构
- 消除重复组(重复列)
示例:
假设有一个表 学生
,包含以下字段:
- 学号
- 姓名
- 课程(可能有多个课程,以逗号分隔)
这个表不符合 1NF,因为“课程”字段包含多个值。解决方法是将“课程”字段拆分为多个行,每行包含一个课程
第二范式(2NF)
定义:一个关系模式 R 属于第二范式,当且仅当 R 属于 1NF,并且每个非主属性完全依赖于主键(而不是主键的一部分)
要点:
- 消除部分函数依赖
- 确保每个非主属性完全依赖于整个主键
示例:
假设有一个表 学生课程
,包含以下字段:
- 学号
- 课程号
- 课程名
- 成绩
如果“课程名”只依赖于“课程号”,而不依赖于“学号”,则这个表不符合 2NF。解决方法是将“课程名”移到一个新的表中,只保留“课程号”和“课程名”
第三范式(3NF)
定义:一个关系模式 R 属于第三范式,当且仅当 R 属于 2NF,并且每个非主属性都不传递依赖于主键
要点:
- 消除传递函数依赖
- 确保每个非主属性直接依赖于主键
示例:
假设有一个表 学生
,包含以下字段:
- 学号
- 姓名
- 系号
- 系名
如果“系名”只依赖于“系号”,而不依赖于“学号”,则这个表不符合 3NF。解决方法是将“系号”和“系名”移到一个新的表中,只保留“学号”、“姓名”和“系号”
第四范式(4NF)
定义:一个关系模式 R 属于第四范式,当且仅当 R 属于 3NF,并且 R 中不存在多值依赖(Multi-valued Dependency)
要点:
- 消除多值依赖
- 确保每个多值依赖都被分解
示例:
假设有一个表 学生课程
,包含以下字段:
- 学号
- 课程号
- 教师号
如果一个学生可以选修多门课程,并且每门课程可以由多个教师教授,则这个表可能存在多值依赖。解决方法是将“教师号”移到一个新的表中,只保留“学号”和“课程号”
总结
数据库范式通过一系列规则来规范化数据库表结构,确保数据存储的有效性和一致性。常见的范式包括:
- 第一范式(1NF) :确保每个属性都是原子的
- 第二范式(2NF) :消除部分函数依赖,确保每个非主属性完全依赖于整个主键
- 第三范式(3NF) :消除传递函数依赖,确保每个非主属性直接依赖于主键
- 第四范式(4NF) :消除多值依赖,确保每个多值依赖都被分解
通过遵循这些范式,可以减少数据冗余,提高数据完整性,并确保数据库设计的合理性和高效性
23 种设计模式
设计模式(Design Patterns)是软件工程中用于解决常见问题的可重用解决方案。它们提供了一种在特定上下文中解决问题的标准方法,有助于提高代码的可维护性、可扩展性和可重用性。设计模式分为三大类:创建型模式、结构型模式和行为型模式
创建型模式(Creational Patterns)
创建型模式关注对象的创建机制,试图以适当的方式创建对象,以满足系统的实际需求
单例模式(Singleton) :
- 确保一个类只有一个实例,并提供一个全局访问点
- 示例:全局配置对象
工厂方法模式(Factory Method) :
- 定义一个创建对象的接口,但由子类决定实例化哪个类
- 示例:图形库中的图形对象创建
抽象工厂模式(Abstract Factory) :
- 提供一个接口,用于创建一系列相关或依赖对象的家族,而不指定其具体类
- 示例:跨平台的 UI 组件创建
建造者模式(Builder) :
- 将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示
- 示例:复杂文档的创建
原型模式(Prototype) :
- 通过克隆现有对象来创建新对象,而不是通过实例化类
- 示例:复杂对象的复制
结构型模式(Structural Patterns)
结构型模式关注类和对象的组合,以形成更大的结构
适配器模式(Adapter) :
- 将一个类的接口转换成客户端所期望的另一个接口
- 示例:不同数据格式的转换
桥接模式(Bridge) :
- 将抽象部分与其实现部分分离,使它们可以独立变化
- 示例:不同平台的图形库
组合模式(Composite) :
- 将对象组合成树形结构以表示“部分-整体”的层次结构,使得客户端对单个对象和组合对象的使用具有一致性
- 示例:文件系统中的文件和文件夹
装饰器模式(Decorator) :
- 动态地给一个对象添加一些额外的职责,而不改变其结构
- 示例:图形对象的边框和阴影
外观模式(Facade) :
- 为子系统中的一组接口提供一个统一的接口,使得子系统更容易使用
- 示例:操作系统中的 API 封装
享元模式(Flyweight) :
- 运用共享技术有效地支持大量细粒度的对象
- 示例:文本编辑器中的字符对象
代理模式(Proxy) :
- 为其他对象提供一种代理以控制对这个对象的访问
- 示例:远程对象的本地代理
行为型模式(Behavioral Patterns)
行为型模式关注对象之间的通信和职责分配
责任链模式(Chain of Responsibility) :
- 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系
- 示例:事件处理链
命令模式(Command) :
- 将请求封装成对象,从而使你可以用不同的请求、队列或者日志来参数化其他对象
- 示例:撤销/重做操作
解释器模式(Interpreter) :
- 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子
- 示例:SQL 解析器
迭代器模式(Iterator) :
- 提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部表示
- 示例:集合类的遍历
中介者模式(Mediator) :
- 用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互
- 示例:聊天室中的用户通信
备忘录模式(Memento) :
- 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后可以将对象恢复到原先保存的状态
- 示例:游戏存档
观察者模式(Observer) :
- 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
- 示例:GUI 中的事件监听
状态模式(State) :
- 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类
- 示例:有限状态机
策略模式(Strategy) :
- 定义一系列算法,封装每个算法,并使它们可以互换。策略模式使得算法可以独立于使用它的客户端而变化
- 示例:排序算法的切换
模板方法模式(Template Method) :
- 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤
- 示例:游戏中的关卡设计
访问者模式(Visitor) :
- 表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作
- 示例:编译器中的语法树遍历
案例题
1
1
先看图 2,找加工,找对应的条,再找实体
2
描述中找不到直接加“表”
3
- 数据流 起点或者终点至少有一个是加工(P 开头的)
- 父图和子图要平衡(父图中有的子图中也要有)
- 加工至少有一条输出和一条输入
4
- 数据流组成: xxxx 数据流= xx + xx + xx
2
- 主键下面画实线
- 外键下面画虚线
3
用例名
用例(Use Case)是软件工程中的一种描述系统功能和用户交互的模型元素。用例名是对用例的简要描述,通常是一个动词短语,用于概括用例的主要功能或目标。用例名应该简洁明了,能够清晰地表达用例的核心意图
例如,对于一个在线购物系统,用例名可以是:
- “浏览商品”
- “添加商品到购物车”
- “下订单”
- “支付订单”
用例之间的关系
用例之间的关系描述了不同用例之间的交互和依赖关系。常见的用例关系包括:
包含关系(Include) :
- 定义:一个用例(基本用例)包含另一个用例(包含用例),即基本用例的执行过程中必然会调用包含用例
- 符号:基本用例 → 包含用例,箭头上标注
<<include>>
- 示例:“下订单”用例包含“支付订单”用例
扩展关系(Extend) :
- 定义:一个用例(扩展用例)在特定条件下扩展另一个用例(基本用例)的功能,即扩展用例在特定条件下才会被调用
- 符号:扩展用例 → 基本用例,箭头上标注
<<extend>>
- 示例:“使用优惠券”用例扩展“支付订单”用例
泛化关系(Generalization) :
- 定义:一个用例(子用例)是另一个用例(父用例)的特化或具体化,即子用例继承了父用例的功能,并在此基础上增加了特定的功能
- 符号:子用例 → 父用例,箭头上标注
<<generalization>>
- 示例:“支付订单”用例是“支付”用例的泛化,“支付订单”用例继承了“支付”用例的功能,并增加了订单相关的特定功能
关联关系(Association) :
- 定义:用例与参与者(Actor)之间的关联关系,表示参与者与用例之间的交互
- 符号:参与者 → 用例,箭头上不标注特殊符号
- 示例:“用户”参与者与“浏览商品”用例之间的关联关系
泛化关系

组合关系
部分不能脱离整体存在

聚合关系
部分可以脱离整体存在

依赖关系

示例
假设我们有一个在线购物系统的用例图,包含以下用例:
- “浏览商品”
- “添加商品到购物车”
- “下订单”
- “支付订单”
- “使用优惠券”
用例之间的关系如下:
- “下订单”用例包含“支付订单”用例
- “支付订单”用例扩展“使用优惠券”用例
- “支付订单”用例是“支付”用例的泛化
- “用户”参与者与“浏览商品”用例、“添加商品到购物车”用例、“下订单”用例、“支付订单”用例之间有关联关系
总结
用例名是对用例的简要描述,通常是一个动词短语,用于概括用例的核心意图。用例之间的关系包括包含关系、扩展关系、泛化关系和关联关系,这些关系描述了不同用例之间的交互和依赖关系,帮助开发团队更好地理解和设计系统功能