网工 软件开发基础

软件生命周期

软件生命周期(Software Development Life Cycle, SDLC)是指从软件产品构思开始直到其不再使用的整个时间段内的一系列阶段。这些阶段覆盖了软件开发过程的所有方面,包括需求分析、设计、实现、测试、部署和维护等。

软件生命周期可以分为几个主要阶段:

  1. 项目规划
    • 在这个阶段确定项目的范围,评估资源需求,并制定项目计划。
    • 这包括定义项目目标、里程碑和交付时间表。
  2. 需求分析
    • 收集并分析用户的需求,明确软件的功能和性能需求。
    • 创建需求规格说明书,作为后续设计和开发的基础。
  3. 设计
    • 根据需求分析的结果设计软件架构和系统设计。
    • 包括总体设计和详细设计两个部分,确保软件的结构能够满足需求。
  4. 实现/编码
    • 开发人员根据设计文档编写代码。
    • 通常会采用模块化的方式进行开发,便于测试和维护。
  5. 测试
    • 对软件进行各种类型的测试,例如单元测试、集成测试、系统测试和验收测试。
    • 目的是找出并修复软件中的缺陷和错误。
  6. 部署/实施
    • 将软件发布给最终用户。
    • 可能涉及安装配置、数据迁移和培训等工作。
  7. 维护
    • 软件上线后需要持续进行维护,修复新发现的问题,改进功能,适应新的技术或业务需求。
    • 维护阶段可能持续很长时间,直到软件被替换或退役。
  8. 退役
    • 当软件不再满足业务需求或技术要求时,可能会被新的软件所替代。
    • 这个阶段涉及到软件的下线、数据归档或转移等工作。

每个组织可能会根据自己特定的需求和流程定制不同的软件生命周期模型,常见的模型有瀑布模型、迭代模型、敏捷开发模型等。

软件开发模型

敏捷开发(Agile Development)是一种以用户需求进化为核心、迭代发布的开发方法。它的出现是为了应对传统瀑布模型中的一些不足之处,特别是当需求变化频繁时,瀑布模型难以适应。敏捷开发强调团队合作、客户协作、响应变化和快速交付。

敏捷开发的主要特点包括:

  1. 迭代和增量开发:软件被分成若干个小的部分,每一部分在短周期内完成,然后发布给客户以收集反馈。这种迭代方式使得开发团队可以及时调整方向,确保产品的价值最大化。
  2. 用户参与:用户(通常是产品的最终用户或者代表用户利益的产品负责人)积极参与到整个开发过程中,确保产品能够满足用户的真实需求。
  3. 团队协作:强调跨职能团队之间的密切合作,鼓励团队成员之间的开放沟通,促进知识共享。
  4. 适应性规划:虽然有总体计划,但是计划会随着项目的进展而不断调整。敏捷方法认为计划应当是灵活的,以应对不断变化的需求。
  5. 持续改进:在每个迭代周期结束后,团队都会评估工作流程的有效性,并寻找改进的机会。
  6. 简化:敏捷开发鼓励简化复杂度,关注最有价值的功能优先开发。
  7. 质量保证:持续集成和测试是敏捷开发的重要组成部分,目的是尽早发现并解决问题。
  8. 响应变化:敏捷开发重视响应变化胜过遵循计划,这意味着即使是在后期阶段,也能接受变更请求。

敏捷开发有许多不同的框架和实践,其中最著名的包括 Scrum、Kanban、XP(极限编程)、Crystal 等。每个框架都有自己独特的方法和实践,但它们都遵循敏捷宣言的原则:

  • 我们最重要的目标,是通过尽早地、持续地交付有价值的软件来使客户满意。
  • 即使到了开发的后期,也欢迎改变需求。敏捷过程利用变化的优势来为客户创造竞争优势。
  • 频繁地交付可以工作的软件,间隔可以从几个星期到几个月,交付的时间间隔越短越好。
  • 业务人员和开发人员必须每天共同工作。
  • 激发个体和互动。构建项目的内外部团队氛围。
  • 可工作的软件是进度的首要度量标准。
  • 敏捷过程倡导可持续开发。责任人、开发人员和用户应该能够保持恒久的工作节奏。
  • 坚持不懈地追求技术卓越和良好设计以增强敏捷能力。
  • 简洁是必不可少的。
  • 最佳的构架、需求和设计出自自组织团队。
  • 团队定期反思如何更有效地工作,并相应地调整自身的行为。

软件性能测试

  性能测试的类型
               性能测试类型包括负载测试、强度测试和容量测试等。
               (1)负载测试:负载测试是一种性能测试,指数据在超负荷环境中运行,程序是否能够承担。
               (2)强度测试:强度测试是在系统资源特别低的情况下考查软件系统运行情况。
               (3)容量测试:确定系统可处理的同时在线的最大用户数。

软件开发模型

https://blog.csdn.net/lonelymanontheway/category_10805425.html

软件产品从形成概念开始,经过开发、使用和维护,直到最后退役的全过程,叫软件生存周期模型,又叫软件开发方法、软件开发模型(Software Develop Model)、软件过程模型 (Software Process Model)

大体来说,有3类:

  • 软件需求完全确定为前提,可以采用瀑布模型;
  • 软件开发初期阶段只能提供基本需求,可以采用迭代式或渐进式模型,如喷泉模型,螺旋模型、统一开发过程和敏捷方法、极限编程。开发人员对算法的效率,操作系统的兼容性和人机交互的形式不明确等情况下,快速原型开发
  • 形式化为基础的变换模型

原型模型

又称快速原型模型,是快速建立起来的可以在计算上运行的程序,是软件的一个早期可运行的版本,它的功能是最终产品的子集。用途主要是获取用户的真正的需求。

原型模型主要有两个阶段:

  • 原型开发阶段。软件开发人员根据用户提出的软件系统的定义,快速地开发一个原型。该原型应该包含目标系统的关键问题和反映目标系统的大致面貌,展示目标系统的全部或部分功能、性能等
  • 目标软件开发阶段。在征求用户对原型的意见后对原型进行修改完善,确认软件系统的需求并达到一致的理解,进一步开发实际系统

瀑布模型

特点:
阶段间具有顺序性和依赖性,前一阶段结束后才能开始后一阶段的工作,前一阶段的输出是后一阶段的输入;推迟实现观点,尽可能推迟程序的物理实现;强调质量保证观点,每个阶段必须完成规定的文档,每个阶段结束前完成文档以便及早改正错误。

瀑布模型可以说是最早使用的软件生存周期模型之一。由于这个模型描述软件生存的一些基本过程活动,所以它被称为软件生存周期模型。这些活动从一个阶段到另一个阶段逐次下降,形式上很像瀑布。瀑布模型的特点是因果关系紧密相连,前一个阶段工作的结果是后一个阶段工作的输入。

每一个阶段都是建立在前一个阶段的正确结果之上,前一个阶段的错误和疏漏会隐蔽地带入后一个阶段。这种错误有时甚至可能是灾难性的,因此每一个阶段工作完成后,都要进行审查和确认。

优点:

  • 原理简单,容易掌握
  • 各阶段间都有验证和确认环节,以便进行质量管理
  • 主要用于支持结构化方法

缺点:

  • 缺乏灵活性,不能适应用户的需求变化
  • 缺乏演化性,返回上一级的开发需要付出十分高昂的代价
  • 是线性的软件开发模型,回溯性差

渐增模型

也叫增量模型,其实质上是分段的线性模型,是一种非整体开发模型,渐增模型把软件产品作为一系列增量构件来设计、编码、集成和测试,在项目开发过程中以一系列的增量方式来逐步开发系统。

优点:

  • 可分批次提交软件产品,方便用户及时了解软件开发进展情况,及早发现问题
  • 以组件为单位进行开发,降低软件开发风险
  • 开发顺序灵活,优先级最高的服务首先交付

缺点:

  • 由于对整个软件系统的需求没有一个完整的定义,会给总体设计带来麻烦
  • 在把每个新的增量构件集成到现有软件结构中时,必须不破坏原来已开发出的产品
  • 软件的体系结构必须是开放的,即向产品中加入新构件的过程必须简单、方便。每次增量开发的产品都应当是可测试的,可扩充的

适用场合:

  • 软件产品可以分批次地进行交互
  • 待开发的软件系统能够被模块化
  • 软件开发人员对应用领域不熟悉、难以一次性地进行软件开发时
  • 项目管理人员把握全局的水平较高时
  • 对软件需求把握不准确、设计方案有一定风险的项目

螺旋模型

螺旋模型是在结合瀑布模型与快速原型模型基础上演变而成,加入风险分析。

软考很恶心的地方在于抠字眼(单选题):

  • 有瀑布和原型两个选项,选择原型
  • 有快速、原型、瀑布三个选项,选择快速

其基本思想,使用原型及其它方法来尽量降低风险。沿着螺线进行若干次迭代。两个显著特点:

  • 采用循环的方式逐步加深系统定义和实现的深度,降低风险
  • 确定一系列里程碑,确保项目开发过程中的相关利益者都支持可行的和令人满意的系统解决方案

形式化方法

形式化方法是一种具有坚实数学基础的方法,从而允许对系统和开发过程做严格处理和论证,适用于那些系统安全级别要求极高的软件的开发。

主要优越性:能够数学(精确)地表述和研究应用问题及软件实现。

但是它要求开发人员具备良好的数学基础。用形式化语言书写的大型应用问题的软件规格说明往往过于细节化,并且难以为用户和软件设计人员所理解。由于这些缺陷,形式化方法在目前的软件开发实践中并未得到普遍应用。

敏捷方法

目标:尽可能早地、持续地对有价值的软件的交付
1.极限编程–XP
价值观:沟通、简单、反馈、勇气
原则:快速反馈,简单性假设,逐步修改,提倡更改和优质工作
2.水晶法(Crystal)
水晶法认为每个不同的项目都需要不通的策略、约定和方法论,认为人对软件质量有重要的影响,软件质量随开发人员素质的提高而提高
3.并列争求法(Scrum)
用迭代的方法,把每30天一次的迭代看做一次冲刺,并按需求的优先级来实现产品

企业集成

  • 企业信息集成是一个十分复杂的问题,按照组织范围来分,分为企业内部的信息集成外部的信息集成两个方面。
  • 1.企业内部的信息集成
  • 按集成内容,企业内部的信息集成一般可分为以下四个方面:
  • (1)技术平台的集成
  • 系统底层的体系结构、软件、硬件以及异构网络的特殊需求首先必须得到集成。这个集成包括信息技术硬件所组成的新型操作平台,如各类大型机、小型机、工作站、微机、通信网络等信息技术设备,还包括置入信息技术或者说经过信息技术改造的机床、车床、自动化工具、流水线设备等新型设施和设备。
  • (2)数据的集成
  • 为了完成应用集成和业务流程集成,需要解决数据和数据库的集成问题。数据集成的目的是实现不同系统的数据交流与共享,是进行其他更进一步集成的基础。数据集成的特点是简单、低成本,易于实施,但需要对系统内部业务的深入了解。
  • 数据集成是对数据进行标识并编成目录,确定元数据模型。只有在建立统一的模型后,数据才能在数据库系统中分布和共享。数据集成采用的主要数据处理技术有数据复制、数据聚合和接口集成等。
  • (3)应用系统的集成
  • 应用系统集成是实现不同系统之间的互操作,使得不同应用系统之间能够实现数据和方法的共享。它为进一步的过程集成打下了基础。
  • (4)业务过程的集成
  • 对业务过程进行集成的时候,企业必须在各种业务系统中定义、授权和管理各种业务信息的交换,以便改进操作、减少成本、提高响应速度。业务流程的集成使得在不同应用系统中的流程能够无缝连接,实现流程的协调运作和流程信息的充分共享。

配置库

配置库有三种:开发库、受控库、产品库。

信息系统项目完成后,最终产品或项目成果应置于产品库内,当需要在此基础上进行后续开发时,应将其转移到受控库后进行。

电子政务与电子商务

B2B:企业与企业之间通过互联网进行产品、服务及信息的交换
B2C:是指企业直接面向消费者提供商品或服务
G2E:指政府(Government)与政府公务员即政府雇员(Employee)之间的电子政务
G2B:是指政府(Government )与企业(Business)之间的电子政务

软件集成测试

软件集成测试也称为组装测试、联合测试(对于子系统而言,则称为部件测试)。它将已通过单元测试的模块集成在一起,主要测试模块之间的协作性。从组装策略而言,可以分为一次性组装测试和增量式组装(包括自顶向下、自底向上及混合式)两种。集成测试计划通常是在软件概要设计阶段完成的,集成测试一般采用黑盒测试方法。一般来说:单元测试所对应的是详细设计环节;
集成测试对应概要设计;
系统测试,就是根据需求分析;验收测试与用户需求对应,是非设计流程。

  • UML中将各种事物构造块归纳成了以下4类。
  • (1)结构事物:UML的静态部分,用于描述概念或物理元素。包含包括类、对象、接口、用例、协作、构件、节点等。
  • (2)行为事物:UML的动态部分,描述一种跨越时间、空间的行为。行为事物包括交互、状态机等。
  • (3)分组事物:类的分组。
  • (4)注释事物:注释图形。

软件文档是影响软件可维护性的决定因素。软件系统文档可以分为用户文档和(系统文档)两类。其中,用户文档主要描述(系统功能)和使用方法,并不关心这些功能是怎样实现的。

网工 进程管理

进程管理中的死锁是指两个或更多进程相互等待对方释放资源,从而导致所有进程都无法继续执行的情况。为了避免或解决死锁问题,操作系统通常采用预防、避免、检测和恢复等策略。

死锁的四个必要条件

死锁的发生必须满足以下四个必要条件:

  1. 互斥条件:至少有一个资源必须被独占使用。
  2. 请求与保持条件:一个已经保持至少一个资源的进程可能请求新的资源。
  3. 不可抢占条件:已经分配给进程的资源不能被抢占,只能由拥有进程显式释放。
  4. 循环等待条件:存在一个进程-资源的环形链。

总结:系统中有N个并发进程,若规定每个进程需要申请R个某类资源,则当系统提供K=N*(R-1)+1个同类资源时,无论采用何种方式申请使用,一定不会发生死锁。

如果是3各进程请求2个资源时,则至少需要3*(2-1)+1 =4

死锁的处理策略

处理死锁的策略通常包括预防、避免、检测和恢复四个方面:

  1. 预防
    • 通过破坏上述四个必要条件之一来预防死锁的发生。
    • 例如,可以采用以下方法:
      • 破坏互斥条件:不太实用,因为许多资源必须独占使用。
      • 破坏请求与保持条件:进程一次性请求所有资源。
      • 破坏不可抢占条件:允许资源被抢占。
      • 破坏循环等待条件:通过资源分配图或资源编号来避免循环等待。
  2. 避免
    • 在分配资源之前,先检查资源分配是否会导致死锁。
    • 使用安全算法来判断分配资源后系统是否处于安全状态。
    • 例如,银行家算法就是一个经典的资源分配算法,它可以确保系统始终处于安全状态。
  3. 检测
    • 定期检查系统是否处于死锁状态。
    • 使用资源分配图来检测是否存在死锁环路。
    • 如果检测到死锁,需要采取措施来解决。
  4. 恢复
    • 一旦检测到死锁,需要采取措施来解除死锁。
    • 方法包括:
      • 剥夺资源:从一些进程中剥夺资源分配给其他进程。
      • 撤销进程:终止一些进程以释放其占用的资源。
      • 回退:让进程回退到之前的状态,释放一些资源。

死锁处理示例

假设我们有两个进程 P1 和 P2,它们分别需要获取资源 R1 和 R2。P1 先获取 R1,然后尝试获取 R2,而 P2 先获取 R2,然后尝试获取 R1。这样就形成了一个死锁环路。

预防策略示例

  • 如果采用一次性请求所有资源的策略,那么 P1 和 P2 都需要在启动时请求所有需要的资源。如果资源不可用,则进程等待,直到所有资源都可用为止。

避免策略示例

  • 使用银行家算法来分配资源。在资源分配之前,检查分配资源后系统是否仍然安全。如果安全,则分配资源;如果不安全,则拒绝分配。

检测和恢复策略示例

  • 定期检查资源分配图是否存在环路。如果检测到死锁,可以选择撤销进程 P1 或 P2,或者从其中一个进程中剥夺资源来打破环路。

总结

  • 预防:通过破坏死锁的必要条件之一来避免死锁。
  • 避免:在分配资源之前检查是否会导致死锁。
  • 检测:定期检查系统状态,以确定是否存在死锁。
  • 恢复:一旦检测到死锁,采取措施解除死锁状态。

进程的PV操作是用于同步进程间通信的一种机制,也称为信号量机制。PV操作是由荷兰计算机科学家Edsger W. Dijkstra提出的,其中P操作(Proberen,尝试)用于请求资源,V操作(Verhogen,增加)用于释放资源。PV操作主要用于解决进程间的同步问题,尤其是临界区问题。

信号量的概念

信号量是一个整型变量,它用来表示资源的数量或状态。信号量的值可以是非负数,也可以是负数。信号量的值大于0表示资源可用,小于0表示等待资源的进程数量。

PV操作的定义

  • P操作:尝试获取资源。P操作会将信号量减1。如果信号量变为负数,则进程进入阻塞状态,等待资源可用。
    • 如果S > 0,则S = S – 1,进程继续执行。
    • 如果S ≤ 0,则将进程的状态置为等待状态,并将其插入到信号量S的等待队列中。
  • V操作:释放资源。V操作会将信号量加1。如果信号量为负数,则唤醒等待队列中的一个进程。
    • 如果S < 0,则从S的等待队列中唤醒一个进程。
    • 如果S ≥ 0,则S = S + 1。

PV操作的应用

PV操作可以用于解决多种同步问题,包括但不限于:

  1. 临界区问题
    • 临界区是指进程中访问共享资源的那段代码。
    • 使用信号量和PV操作可以确保一次只有一个进程访问临界区。
    • 通常使用一个初始值为1的信号量S来实现互斥访问。
  2. 生产者-消费者问题
    • 生产者进程生成数据并放入缓冲区,消费者进程从缓冲区中取出数据。
    • 使用两个信号量:一个表示缓冲区中可用数据的数量(initially 0),另一个表示缓冲区中可用空间的数量(initially buffer size)。
    • 生产者在生产数据前执行P操作(尝试获取空闲空间),在生产数据后执行V操作(释放空间)。
    • 消费者在消费数据前执行P操作(尝试获取数据),在消费数据后执行V操作(释放数据)。
  3. 读者-写者问题
    • 多个读者可以同时读取共享资源,但写入时不允许其他读者或写者访问。
    • 使用两个信号量:一个用于控制写者(initially 0),另一个用于控制读者的数量(initially 0)。

示例代码

下面是一个使用PV操作解决临界区问题的简单示例:

import threading

# 创建一个信号量
semaphore = threading.Semaphore(1)

def critical_section():
    semaphore.acquire()  # P操作
    # 执行临界区代码
    print(f"{threading.current_thread().name} is in the critical section.")
    semaphore.release()  # V操作

def process_function():
    # 其他非临界区代码
    critical_section()
    # 其他非临界区代码

# 创建多个线程
threads = []
for i in range(5):
    thread = threading.Thread(target=process_function)
    threads.append(thread)
    thread.start()

# 等待所有线程完成
for thread in threads:
    thread.join()

总结

PV操作是实现进程间同步的重要手段,通过信号量和P/V操作可以有效地解决临界区问题、生产者-消费者问题等多种同步问题。在现代操作系统中,PV操作被广泛应用于多线程编程和并发控制中。

示例

1、某企业生产流水线M 共有两位生产者,生产者甲不断地将其工序上加工的半成品放入半成品箱,生产者乙从半成品箱取出继续加工。假设半成品箱可存放n 件半成品,采用PV 操作实现生产者甲和生产者乙的同步可以设置三个信号量S、S1 和S2,其同步模型如下图所示

信号量S 是一个互斥信号量,初始值为(22);S1、S2 的初始值分别为(23)

这里成品箱看作控制信号量(互斥信息号量)其初始值为1 ,s1,s2的初值分别为n 和0 。

2、假设系统中有n个进程共享3台打印机,任一进程在任一时刻最多只能使用1台打印机。若用PV操作控制n个进程使用打印机,则相应信号量S的取值范围为____(1)____;若信号量S的值为-3,则系统中有____(2)____个进程等待使用打印机。 

在使用PV(也称为P和V,或者wait和signal)操作来同步进程对共享资源(如打印机)的访问时,信号量是一个非常重要的工具。信号量可以用来确保多个进程不会同时访问同一资源,从而避免冲突。

信号量 S 的取值范围

我们有3台打印机,所以信号量 S 的最大值应该是3,表示所有打印机都可用。当一个进程开始使用打印机时,它会执行P(S)操作,这将使信号量的值减1。当进程完成并释放打印机时,它会执行V(S)操作,这将使信号量的值加1。

因此,信号量 S 的取值范围取决于以下几个因素:

  1. 所有打印机都没有被使用时,S = 3。
  2. 当所有打印机都被占用且还有进程在等待时,S 的值会变为负数,其绝对值表示正在等待的进程数量。

如果没有任何进程在等待,也没有任何打印机被占用,那么S = 3。如果有1台打印机被占用,那么S = 2;如果有2台打印机被占用,那么S = 1;如果有3台打印机都被占用但没有进程等待,那么S = 0。如果已经有进程开始等待,那么S 的值就会小于0,每多一个等待的进程,S 的值就减少1。

所以信号量S 的取值范围为3,2,1,0,-1,…-(n-3)

信号量 S 取 -3 的含义

如果信号量 S 的值是 -3,这意味着所有的3台打印机都被占用了,并且除了已经占用打印机的进程外,还有3个额外的进程正在等待使用打印机。因此,此时有3个进程正在等待。