(026) Linux之自顶向下设计

十年运维系列之基础篇 - Linux

作者:曾林

联系:[email protected]

网站:www.jplatformx.com

版权:文章未经同意请勿转载


一、引言

      随着程序越来越大,越来越复杂,设计、编码和维护都将越来越困难。所以,在设计任何大型项目的时候,我们最好将庞大的、复杂的任务,拆分成一系列小的、简单的任务。

想象一下,我们来描述一个常见的日常任务:你去超市买东西。我们可以按照如下的步骤来进行。

  1. 选择商品
  2. 结账
  3. 离开

但是,我们在结账这个环节则可能需要更多的细节。我们来继续将“结账”这个步骤进一步拆分为一系列的步骤。

  1. 排队
  2. 统计商品
  3. 付钱
  4. 收取零钱

这种先确定上层步骤,然后再逐步细化这些步骤的过程,称之为自顶向下的设计。

通过这种设计方式,我们可以将大而且复杂的任务分解成很多小而简单的任务。自顶向下设计是一种设计程序的常见方式,尤其适合shell编程。

二、shell函数

所谓shell函数,本质上就是shell脚本中的迷你脚本。shell函数有两种语法形式。第一种如下所示:

function name    {
    commands
    return
}

其中name是指这个函数的名称,commands是这个函数中的一系列命令。第二种看起来如下所示:

name()    {
      commands
      return
}

这两种形式等价,并且可以交替使用。如下,我们来提供一个简单的脚本来展示一下shell函数的使用。

#!/bin/bash

# Program to output a system information page

TITLE="System Information Report for $HOSTNAME"
CURRENT_TIME=$(date +"%x %r %Z")
TIME_STAMP="Generated $CURRENT_TIME, by $USER"

report_uptime()    {
    cat <<- _EOF_
                <H2>Report Uptime</H2>
                <PRE>$(uptime)</PRE>
   _EOF_
}

report_disk_space()    {
    cat <<- _EOF_
                <H2>Report disk space</H2>
                <PRE>$(df -h)</PRE>
    _EOF_
}

report_home_space()    {
    cat <<- _EOF_
                <H2>Report home space</H2>
                <PRE>$(du -sh /home/*)</PRE>
    _EOF_
}

cat << _EOF_<HTML>    <HEAD>    <TITLE>$TITLE</TITLE>  </HEAD>  <BODY>      <H1>$TITLE</H1>      <P>$TIME_STAMP<P>      $(report_uptime)      $(report_disk_space)      $(report_home_space)  </BODY></HTML>_EOF_

三、局部变量

在目前我们所编写的脚本中,所有的变量(包括常量)都是全局变量。全局变量在整个程序期间会一直存在。在很多情况下,这都不错。但是有时候,它会让shell函数的使用变得复杂。在shell函数中,经常需要的是局部变量。局部变量仅仅在定义它们的shell函数中有效,一旦shell函数终止,它们就不会存在。

局部变量可以让程序员使用已经存在的变量名称,无论是脚本中的全局变量,还是其他shell函数中的变量,而不用考虑潜在的命名冲突。

下面定义一个显示如何定义和使用局部变量的脚本示例。

  1 #!/bin/bash
  2
  3 # local-vars: script to demenstrate local variables
  4
  5 foo=0 # global variable foo
  6
  7 funct_1()   {
  8     local foo
  9     foo=1
 10     echo "funct_1: foo = $foo"
 11 }
 12
 13 funct_2()   {
 14     local foo
 15     foo=2
 16     echo "funct_2: foo = $foo"
 17 }
 18
 19 echo "global: foo = $foo"
 20 funct_1
 21 echo "global: foo = $foo"
 22 funct_2
 23 echo "global: foo = $foo"

运行结果如下图:

可以看到,局部变量是通过在变量名前面添加单词local来定义的。这样,就创建并同时定义了一个shell函数中的局部变量。一旦出了这个shell函数,这个局部变量将不再存在。因此,在两个shell函数中对局部变量foo的赋值,不影响shell函数以外定义的变量foo的值。

四、保持脚本的运行

在开发程序的时候,让程序保持可运行的状态会非常有用。通过这种方式,并经常测试,就可以在开发过程的早期检测到错误。这也会让问题的调试变得容易。例如,如果我们运行某个程序,并对它做了细微的改动,然后再次运行该程序,此时发生了问题。这可能是有可能最近的改动所造成的。通过添加空函数(程序员称之为stub),我们可以在早期验证程序的逻辑流程。当构建一个stub时,最好是包含一些能够为程序员提供反馈信息的东西,这些反馈信息可以显示正在执行的逻辑流程。

五、在.bashrc中添加shell函数

shell函数可以很好的取代别名,并且实际上也是创建个人使用的小命令的首选方法。别名非常局限于命令的种类和它们支持的shell特性,而shell特性则允许任何可以编写为脚本的东西。例如,如果我们很喜欢为脚本开发report_disk_space这个shell函数,则可以为.bashrc文件创建一个相似的名为ds的函数。

ds()    {
    echo "Disk Space Utilization for $HOSTNAME"
    df -h
}

六、本章结束语

在本章,我们介绍了一种常用的程序设计方法——自顶向下,并知道了如何使用shell函数按照要求来构建逐步细化的任务。我们还学习了如何使用局部变量时shell函数的相互独立,并独立于它们所在的程序。这样,我们就可以以可移植和可重用的方式编写shell函数,并将其用到多个程序中,从而节省大量的时间。

时间: 2024-10-13 17:39:54

(026) Linux之自顶向下设计的相关文章

Linux 内存池设计构想

一.基本数据结构 1 union m_block 2 { 3 union m_block* next; 4 unsigned int size; 5 }; 6 7 struct m_list 8 { 9 union m_block* free; 10 pthread_spinlock_t lock; 11 unsigned int size; 12 }; 13 14 struct m_pool 15 { 16 struct m_pool* next; 17 }; 18 19 struct m_m

Cadence Innovus v15.10.000 Linux 1DVD物理设计实现解决方案

Cadence Innovus v15.10.000 Linux 1DVD物理设计实现解决方案新一代的物理设计实现解决方案,使系统芯片(system-on-chip,SoC)开发人员能够在加速上市时间的同时交付最佳功耗.性能和面积(PPA)指 标的的设计.Innovus设计实现系统由具备突破性优化技术所构成的大规模的并行架构所驱动,在先进的16/14/10纳米FinFET工艺制程和其他 成熟的制程节点上通常能提升10%到20%的功耗.性能和面积指标,并实现最高达10倍的全流程提速和容量增益. E

linux应用开发-设计动态库

linux应用开发-设计动态库 一 制作动态库 1. gcc –c mylib.c –o mylib.o 2. gcc -shared -fPIC mylib.o -o libmylib.so  3. 将制作好的libmylib.so 复制到/usr/lib 4 -fpic 使输出的对象模块是按照可重定位地址方式生成 5 -shared 指明产生动态链接库. 二 基本概念见上一章设计静态库

linux应用开发-设计静态库

linux应用开发-设计静态库 一 应用程序 函数库(用户)和系统调用(linux内核) 二 库分类 1 静态链接库(*.a) 一个程序使用一个函数库 2 动态链接库(*.so) 多个程序可以使用同一个函数库,减少程序的大小 3 静态库比动态库大 三 制作自己的静态库 1 gcc -c mylib.c -o mylib.o 2 ar cqs libmylib.a mylib.o 3 将做好的libmylib.a 复制到/usr/lib目录下 四 使用自己创建的静态库 1 linux默认链接动态库

Linux文件系统的设计

总论: linux的文件系统设计非常优秀,总的来讲有两大部分,第一部分就是树形的组织结构,第二部分就是vfs,树形的组织结构组织了文件系统的表象,用户非常方便的使用,而vfs是文件系统的实现机理,它处于内核态,不但实现了树形结构的mount机制,并且还提供了一个统一的接口用来訪问设备. 一.Linux文件系统概述 1.Linux文件系统组织 Linux中使用树来组织文件系统.整个文件系统构成了一颗树,这棵树以/为根.整个系统有且仅仅有这一颗文件树.这棵树描写叙述了文件系统的拓扑结构,没有不论什么

Linux UBI子系统设计初探

问题领域 flash存储设备存在如下特点: 存在坏块 使用寿命较短 存储介质不稳定 读写速度慢 不支持随机访问(nand) 只能通过擦除将0改成1 最小读写单位为page or sub-page 便宜 针对flash设备的特点,flash文件系统的核心功能需求和质量需求需包括如下这几个方面: 读写 性能 可靠性 持久性 针对这些需求,可分析得出flash文件系统需要满足如下属性要求: 数据保护 坏块管理 垃圾回收 磨损均衡 分区管理 文件管理 性能优化 在ubifs文件系统中,这7条属性中的数据

【转】Linux Futex的设计与实现

引子在编译2.6内核的时候,你会在编译选项中看到[*] Enable futex support这一项,上网查,有的资料会告诉你"不选这个内核不一定能正确的运行使用glibc的程序",那futex是什么?和glibc又有什么关系呢? 1. 什么是FutexFutex 是Fast Userspace muTexes的缩写,由Hubertus Franke, Matthew Kirkwood, Ingo Molnar and Rusty Russell共同设计完成.几位都是linux领域的

linux并发服务器设计

linux 并发服务器: http://blog.csdn.net/ygl840455828ygl/article/details/52438167 http://www.2cto.com/os/201309/245280.html http://www.cnblogs.com/venow/archive/2012/11/22/2779667.html http://blog.csdn.net/turkeyzhou/article/details/8609360 1 背景简介 H330S模块集成

Linux SPI驱动设计

1. SPI总线结构 SPI串行外设接口,是一种高速的,全双工,同步的通信总线.采用主从模式架构,支持多个slave,一般仅支持单Master SPI接口共有4根信号线,分别是: 设备选择线(SS).时钟线(SCK).串行输出数据线(MOSI).串行输入数据线(MISO). 2. 数据传输过程 主节点通过MOSI线输出数据,从节点在SIMO处从主节点读取数据.同时,也通过SMOI输出MSB(最高位), 主节点会在MISO处读取从节点的数据,整个过程将一直持续,直至交换完所有的数据. 3. 总线时