57
UNIX 基基基基基

UNIX 基础与开发

  • Upload
    cortez

  • View
    129

  • Download
    9

Embed Size (px)

DESCRIPTION

UNIX 基础与开发. 提纲. 如何开发高质量的软件 UNIX 文件系统 UNIX 的 SHELL UNIX 开发与调试 经验分享 讨论. 如何开发高质量的软件 /1. 软件开发 =Coding ? 面试的故事 第一轮: 功能: A 、 B 、 C C 先生: 25 分钟( Coding ) I 先生: 10 (想) +30 ( Coding )分钟 第二轮: 功能: A’ 、 D 、 C C 先生: 10 (改) +25 (重写)分钟 I 先生: 10 (想) +25 ( Coding )分钟 第三轮: - PowerPoint PPT Presentation

Citation preview

Page 1: UNIX 基础与开发

UNIX 基础与开发

Page 2: UNIX 基础与开发

提纲 如何开发高质量的软件 UNIX 文件系统 UNIX 的 SHELL UNIX 开发与调试 经验分享 讨论

Page 3: UNIX 基础与开发

如何开发高质量的软件 /1 软件开发 =Coding ? 面试的故事

第一轮: 功能: A 、 B 、 C C 先生: 25 分钟( Coding ) I 先生: 10 (想) +30 ( Coding )分钟

第二轮: 功能: A’ 、 D 、 C C 先生: 10 (改) +25 (重写)分钟 I 先生: 10 (想) +25 ( Coding )分钟

第三轮: 功能: A 、 B 、 C’ 、 E C 先生: 10 (改) + ?(重写)分钟 I 先生: 10 (想) +25 ( Coding )分钟

Page 4: UNIX 基础与开发

如何开发高质量的软件 /2

软件开发什么最重要? 编写高质量代码最重要? 设计最重要? 需求最重要? 测试最重要? 计划最重要?

Page 5: UNIX 基础与开发

如何开发高质量的软件 /3 高质量代码

先做设计,再写代码 制定编码规范,严格执行 代码走查制度 每个功能块(类)都要有单元测试代码,对不同的入口参数进行充

分测试 了解 OS 原理对编写高质量代码有帮助 权衡:性能与可读性、内存与速度、避免过度的编程技巧(除非特

殊情况)… 正确使用内存空间 参数合法性检查、通信数据合法性检查 作为服务器的程序,要考虑安全性 … …

Page 6: UNIX 基础与开发

如何开发高质量的软件 /4 软件设计

紧扣需求 2/8 原则:以最原始的方法实现某些复杂的功能 形成文档 以不变的架构应万变的需求 确定框架之前,针对实际的系统做部分关键技术研究,

获得实际数据 模块化、可扩展、复用性… …

Page 7: UNIX 基础与开发

如何开发高质量的软件 /5

需求分析 充分与客户沟通,深入挖掘需求 关注隐性需求 需求到功能的转换 2/8 原则:引导客户放弃某些需求,以其他方式

代替某些需求

Page 8: UNIX 基础与开发

如何开发高质量的软件 /6

测试(质量保证) 强调单元测试:

每个功能块(类)对应一个单元测试程序模拟上下接口

每个模块都要建立模拟测试环境 不要因为赶工忽略系统测试,不能运用 2/8 原则 稳定性测试 性能测试(开发人员配合) 压力测试

Page 9: UNIX 基础与开发

如何开发高质量的软件 /7

计划 对于死亡之旅的项目,倒排计划不失为一种好的

方式 风险储备 测试要占用整个项目 1/2 的时间,对于死亡之旅

的项目,测试至少占用 1/3 的时间 计划的执行和跟踪(自我跟踪)

Page 10: UNIX 基础与开发

提纲 如何开发高质量的软件 UNIX 文件系统 UNIX 的 SHELL UNIX 开发与调试 经验分享 讨论

Page 11: UNIX 基础与开发

UNIX 文件系统 /1 所有的 UNIX 都是基于文件的 Solaris 的文件系统是 UFS 文件分类:

普通文件 目录文件 特殊文件

文件是有权限的,文件的权限是与用户的权限相结合来管理的 文件的文件主、同组用户、其他用户 文件的读 - 写 - 执行权限( rwx )

Page 12: UNIX 基础与开发

UNIX 文件系统 /2

UNIX 文件系统的树形结构( Solaris )

Page 13: UNIX 基础与开发

UNIX 文件系统 /3

普通文件 文件名: 255字节长度限制 文件路径名:相对路径名、绝对路径名 文件名扩展: file.c, file.h

某些编程语言( C )对文件的扩展名依赖性强大多数情况文件名扩展是可选的

隐藏的文件名: .file

Page 14: UNIX 基础与开发

UNIX 文件系统 /4 目录文件

Solaris 的重要目录 / 根目录 /dev 设备(特殊)文件 /etc 本地计算机系统配置 /home 用户目录 /tmp 临时文件 /usr 第二个主文件层次结构

/usr/bin 用户命令 /usr/sbin 非重要的系统管理二进制文件 /usr/lib 库文件和现场 /usr/include 头文件 /usr/man 手册页

执行权限对于目录来说就是搜索的权限,对一个目录要有读和执行权限,才能转移到目录下

Page 15: UNIX 基础与开发

UNIX 文件系统 /5

特殊文件 设备文件: /dev

硬盘 /硬盘分区CDROM 、软盘、磁带PCI卡(网卡)… …

有名管道 Socket Proc 文件系统:

虚拟文件系统包含系统和进程的调试信息,对服务器程序的调试很有帮助

Page 16: UNIX 基础与开发

提纲 如何开发高质量的软件 UNIX 文件系统 UNIX 的 SHELL UNIX 开发与调试 经验分享 讨论

Page 17: UNIX 基础与开发

UNIX 的 SHELL

shell 是一种命令解释程序和编程语言 运行命令 高级语言

通用 Shell : Bourne shell ( sh/bsh ):最初的 UNIX shell C shell ( csh ): Berkeley UNIX Korn shell ( ksh ):综合多个 shell 特点

Solaris 的默认 Shell : Bourne shell ( sh/bsh )

Page 18: UNIX 基础与开发

Shell 基础 /1

开始 登录

图形界面、字符界面、仿真终端、 telnet 注销

Logout 、 exit 超级用户:最好不要用超级用户登录 修正错误

删除一个字符: BACKSPACE 、 CONTROL-H 、 Delete 、 Del删除一个单词: CONTROL-W删除一行: CONTROL-U终止程序执行: CONTROL-C 、 CONTROL-Z 、 Kill -9

Page 19: UNIX 基础与开发

Shell 基础 /2

特殊字符 支持通配符: * 、 [0-9] 特殊字符: & ; | * ? ‘ “ ` [ ] ( ) $ < > { } ^ # / \ % !

~ + 引用特殊字符:反斜杠 \ ,如 \*\* ,或引号“”

联机帮助: man

Page 20: UNIX 基础与开发

Shell命令 /1

基本实用命令 ls :列出某个目录下的内容 cat :显示一个文本文件 pg 、 more :显示一个长文本文件 rm :删除一个文件 hostname :显示计算机名 echo :显示文本 date :显示时间和日期 script :记录一个 Solaris会话

Page 21: UNIX 基础与开发

Shell命令 /2 文件和目录基本处理

cp :复制文件 mv :更改文件名 grep :查找一个字符串 head :显示文件开始 tail :显示文件结尾 Sort :按次序显示文件(不会改变文件的内容) uniq :删除文件中的重复行 diif :比较两个文件 file :测试文件的内容 mkdir :创建一个目录 cd :更换到其他工作目录 pwd :显示工作目录的路径名 rmdir :删除一个目录(必须是空目录) mv :移动一个目录或文件 rm :删除一个文件,或目录及其下的所有文件

Page 22: UNIX 基础与开发

Shell命令 /3

文件的权限 ls –l 能列出文件或目录的权限 chmod :更改访问权限 chmod g+w file1 setuid 和 setgid 权限 chmod s+w program

减少 s e t u i d 和 s e t g i d 程序的使用不要编写 setuid 的 shell脚本

目录的权限 读权限:能列出目录下的文件 写权限:能在目录下信件文件 执行权限:能转移到目录的子目录下

Page 23: UNIX 基础与开发

Shell命令 /4 文件的连接

ln :创建一个连接ln /home/jenny/draft /hom

e/alex/letter 与 cp 的区别:文件副本

的个数,连接是一个文件副本, cp 有两个文件副本

符号连接与硬连接:符号连接的文件副本可以不存在

连接的删除: rm

Page 24: UNIX 基础与开发

Shell命令 /5

文件的压缩和存档 compress :压缩文件 uncompress 、 zcat :扩展文件 tar :打包和解包某个文件

Page 25: UNIX 基础与开发

Shell命令 /6

网络命令 ping :测试网络连接 rlogin 、 telnet 、 ssh :访问某个远程计算机 rcp 、 ftp :通过网络传输文件 rsh :远程运行一个命令

文件系统 newfs :新建一个文件系统 fsck :检查文件系统 mount/umount :安装 /反安装一个文件系统

Page 26: UNIX 基础与开发

Shell命令 /7

其他命令 which 、 whereis :查找命令的位置 ps :查看系统进程的信息 top :查看系统性能 who 、 w 、 finger :列出系统上的用户名单 write 、 talk :向其他用户发送消息、通信 mesg :拒绝或接受消息

Page 27: UNIX 基础与开发

Shell命令 /8

Vi 编辑器 启动 vi

vi file

两种操作模式命令模式输入模式

结束 Vi :q!, :wq!, ZZ

命令区分大小写 撤销命令的执行: u

Page 28: UNIX 基础与开发

Shell命令 /9 Vi 编辑器

命令模式光标移动换屏删除字符: x删除一行或多行: dd 、 Xdd从 vi 执行 shell命令: :sh, :!cmd(:!pwd)读取文件: :[address]r[filename]写入文件: :[address]w[!][filename]到文件尾: :$到文件头: :1到行头: 0到行尾: $

Page 29: UNIX 基础与开发

Shell命令 /10

Vi 编辑器 输入模式

插入命令: i追加命令: a新建一行: o替换命令: r 、 s复制: yy – p

建议:远端 windows 用户用 eltraedit 通过 ftp编辑文件

Page 30: UNIX 基础与开发

Shell语言 /1

Shell 基础知识 命令行语法

command [arg1][arg2] ...[arg n]

标准输入 /标准输出 重定向:〉 管道: | 后台运行: &

Page 31: UNIX 基础与开发

Shell语言 /2

控制结构 if-then 、 if-then-else 、 if...then...elif for. . . i n for 结构 while 结构 until 结构 break 和 c o n t i n u e语句 case 结构

Page 32: UNIX 基础与开发

Shell语言 /3

参数与变量 关键字变量:环境变量 用户自定义变量 位置参数: $0, $1 特殊参数: $?, $$

Page 33: UNIX 基础与开发

Shell

运行 Shell脚本 赋予执行权限,直接运行 sh sh_script

自动启动一个服务 /etc/init.d /etc/rcX.d 目录下建符号连接( S/K 前缀) 是否有命令实现?

Page 34: UNIX 基础与开发

提纲 如何开发高质量的软件 UNIX 文件系统 UNIX 的 SHELL UNIX 开发与调试 经验分享 讨论

Page 35: UNIX 基础与开发

编译 gcc 、 g++

gcc test.c –o test g++ test.cpp –o test 编译选项: -O3 、 -g 、 -c

自动编译: make 编写 Makefile

Page 36: UNIX 基础与开发

调试 gdb :面向源代码和目标码 可视化的调试工具? 程序里人工加入 debug 信息 /proc中看信息(对于服务程序)

Page 37: UNIX 基础与开发

调试( linux )怎样用 gdb从目标级作 debug ?

使用带调试信息的选项编译: gcc -g 让程序 down掉( segment fault )的时候产生 c

ore 文件: ulimit –c unlimited gdb ./test core.XXXX Gdb 下常用命令: where 、 frame X 、 print

Page 38: UNIX 基础与开发

进程和线程 /1 进程是系统资源管理的最小单位,线程是程序执行的最小单位。线程和进程十分相似,不同的只是线程比进程小,因而调度的开销也比进程小。

一个程序里面的所有的线程都在同一个运行空间中执行,而一个程序的子进程则是运行在另外的执行空间中的。所以线程之间的所有资源都是共享的,而平级进程之间的资源不共享,子进程也只继承父进程的资源,但不能共享。

同一个进程中的某个线程的故障可以影响其它的线程,因为所有的线程共享同一个虚拟内存空间以及其他资源。例如,某个线程对没有初始化的指针进行写操作,就可能影响其它的线程。而一个出了问题的进程是不会影响其它的进程的,因为它们分别在不同的进程空间进行自己的操作。

线程之间共享数据是很方便的,因为不同的线程本来就是共享同样的存储空间。(然而这里就要非常仔细的处理竞争的情况。)而不同进程之间共享数据则需要使用一些 IPC机制,例如管道、共享内存、套接字等等

创建新的进程需要进行内存的拷贝操作,这就额外的增加了系统负担,而线程则不需要这个拷贝过程。不过由于现在的操作系统的实现是仅仅当内存需要改变的时候才拷贝改动的部分,所以这里的影响相对还是比较小的。

线程通常用在某些需要比较好的同步操作的场合。例如,某个问题可以分解为多个几乎对等同步处理的任务的话,则是用线程是很好的选择。进程则适合应用在不需要严格的同步的场合。

Page 39: UNIX 基础与开发

进程和线程 /2

进程编程 fork 进程之间的通信方式

共享空间: mmap 、 shmget管道Socket IPC文件

临界资源的竞争 -锁文件锁 flock线程锁:将锁变量定义为共享变量

Page 40: UNIX 基础与开发

进程和线程 /3

线程编程( pthread ) Pthread_create Phread_destroy Pthread_detach Pthread_join Pthread_attr_XXXX Pthread_mutex_init Pthread_mutex_lock Pthread_mutex_unlock

Page 41: UNIX 基础与开发

进程和线程 /4

线程间通信 共享空间:全局变量 管道 Socket IPC 文件

临界资源的竞争 -锁 线程锁 信号灯 +线程锁

Page 42: UNIX 基础与开发

进程和线程 /5 Linux 下进程 /线程模型的测试结果 -1 (创建与销毁)

系统支持的最大进程数是 14000多个,在系统总的进程数没有达到这个数时,一个进程可以创建的进程个数不受限制

系统支持的最大线程数是 14000多个,一个进程可以允许 300 个左右线程同时存活(包括 detach 和不 detach 的);但如果线程创建后 detach ,且会自行退出,一个进程便可以创建多余 300 个线程,如果线程创建后不 detach ,即使自行退出,一个进程可以创建的线程数仍为 300 个

进程创建和销毁的开销与 CPU主频有关, CPU主频越高,开销越小;与 CPU 个数关系不大

线程创建和销毁的开销与 CPU主频、 CPU 个数、创建后是否 detach 都有关系, CPU主频越高,开销越小;开销与 CPU 个数不成反比, CPU 个数越多,开销反而越大;线程创建后 detach ,比不 detach 的开销小很多

线程创建 /销毁的开销比进程创建 /销毁的开销小很多

Page 43: UNIX 基础与开发

进程和线程 /6

Linux 下进程 /线程模型的测试方案 -2 (运算型)

主进程

子进程或

线程

子进程或

线程

子进程或

线程

… …

1...N循环创建

同步终止

运算

运算

运算

Page 44: UNIX 基础与开发

进程和线程 /7

Linux 下进程 /线程模型的测试结果 -2 (运算型) 在单 CPU 的情况下,进程 /线程数的增加对运算性能影响不大

不是进程 /线程数越多越好,当进程 /线程数太多的时候,反而影响性能

当进程 /线程数达到 CPU 数的时候,更多的进程 /线程就不能增加性能了

超线程的影响不总是正面的,如进程 /线程数等于实际物理 CPU 数的时候,不开放超线程的性能更高;当进程 /线程数多于实际物理 CPU 数的时候,开放超线程就有优势了

Page 45: UNIX 基础与开发

进程和线程 /8

Linux 下进程 /线程模型的测试方案 -3 (共享内存通信型 )

主进程

写进程或

线程

读进程或

线程

共享队列

处理

主进程

写进程或

线程

读进程或

线程

共享队列

处理

读进程或

线程处理

读进程或

线程处理

… … Lock

进程/线程池

Page 46: UNIX 基础与开发

进程和线程 /9 Linux 下进程模型的测试结果 -3 (共享内存通信型 )

在单 CPU 情况下,读进程数增多,对于性能增加不大 采用进程池的方法时,进程个数与 CPU 个数(逻辑的)相等比较合适,数量更多并不能提高性能

动态创建进程的方法,只适合于队列元素较少,或者每个元素处理复杂,需要占用很多时间的情况;而进程池的方法对于队列元素处理不需占用太多时间,且元素个数又很多的情况,很适合

超线程的影响不总是正面的,如在进程池的测试中:进程数等于实际物理 CPU 数的时候,不开放超线程的性能更高;当进程数多于实际物理 CPU 数的时候,开放超线程就有优势了

超线程对于动态创建进程的情况,比不开放超线程略有优势

Page 47: UNIX 基础与开发

进程和线程 /10 Linux 下线程模型的测试结果 -3 (共享内存通信型 )

在单 CPU 情况下,读线程数增多,对于不但不能增加性能,反而会降低性能

采用线程池的方法时,线程个数与 CPU 个数(逻辑的)相等比较合适,数量更多并不能提高性能

动态创建线程比动态创建进程性能要好 超线程的影响不总是正面的,如在线程池的测试中:线程数等于实

际物理 CPU 数的时候,不开放超线程的性能更高;当线程数多于实际物理 CPU 数的时候,开放超线程就有优势了

当处理复杂元素时,超线程对于动态创建线程的情况,比不开放超线程略有优势;而对于简单元素,则相反。不过这种差别很小

Page 48: UNIX 基础与开发

提纲 如何开发高质量的软件 UNIX 文件系统 UNIX 的 SHELL UNIX 开发与调试 经验分享 讨论

Page 49: UNIX 基础与开发

多用 man命令 man 2 XXX :查看系统调用的联机帮助

man 2 read man 3 XXX :查看库函数的联机帮助

man 3 fread man 5 XXX :查看配置文件的联机帮助

man 5 inittab

Page 50: UNIX 基础与开发

编码规范 严格遵守编码规范 做好代码走查例子:

if (a == NULL) 最好写成: if (NULL == a) free A ,最好写成: If (NULL != A ) { free (A); A = NULL; }

Page 51: UNIX 基础与开发

测试 要有单元测试程序,单元测试不能只测一次,

应该反复测试碰到无缘无故“修复”的 bug ,应该查到底,这时 bug往往是被隐藏,并非真正修复

Page 52: UNIX 基础与开发

BUG 调试技巧 使用 gdb从 core 文件中找信息在 proc 文件系统中也能查出一些信息(针对

正在运行的程序,适合于查找资源泄露情况)

Page 53: UNIX 基础与开发

其它 少用全局变量,避免使用常用单词作为全局变量名

(容易与系统全局变量混淆) 避免使用大空间的静态局部变量,改用 malloc申请

空间 使用指针变量时要防止内存泄露和缓冲区溢出,怎样防止?(一般编码规范里有规定) 指针使用时检查空间是否申请 不用的空间及时释放 释放的空间避免再次使用

“拿来主义”:充分利用 linux 的开源资源

Page 54: UNIX 基础与开发

其它 如果要使用系统配置文件,避免直接对它操作,而

是在配置文件的备份文件上操作 CPU 使用、内存使用和程序复杂度的折中,除非是

特殊应用,不要因为节约 CPU 和内存资源而增加程序复杂度

IO操作(主要是文件):尽量减少读写次数 内存问题:可以使用 hook 帮助查找问题( linux )

Page 55: UNIX 基础与开发

其他 如何优化软件的性能

对于性能要求非常敏感的应用,一般的编码规范需要做调整

少用函数调用,使用内联调用循环展开调整编译器的优化选项使用寄存器变量使用系统调用,而不是库函数

在代码内部插入时间统计函数,有针对性的优化( 2/8 原则)

Page 56: UNIX 基础与开发

提纲 如何开发高质量的软件 UNIX 文件系统 UNIX 的 SHELL UNIX 开发与调试 经验分享 讨论

Page 57: UNIX 基础与开发