标签归档:读书笔记

python标准库

python标准库

前言

在这之前已经学过《廖雪峰的python教程》,也看过了《flaskweb实战》,之前还看过《head first in python》,又因为对黑客的好奇,看过了《python绝技:运用python成为顶级黑客》这本书。
熟悉语法之后,接下来其实是熟悉标准库。前面看的书,只是勾起我的兴趣。兴趣才是最大的老师呀。
下面是我划分的学习阶段:
语法大概只占了一门语言的1%,然后还有5%是官方库,10%是第三方库, 10%是开源的框架和SDK, 剩下的是背后的思想,算法,操作系统,协议什么的。

廖雪峰的python教程和《head first in python》其实对语法讲的都不细致。只能说看完之后能写代码了,遇到问题再去搜索。暂时选择标准库来看,回头还要再补习全面的语法。

评价

书有点老,10年的,不过不长,只有329页。到处找了下,貌似都是10/06/07的那本。
书上的例子只有2.0下运行通过。我用的2.7,除了极个别的,都运行通过了。
讲的并不深入,就是对python的标准模块有个了解,有个大概的印象。基本上每个模块都给了个简单的例子。
还是推荐阅读下,全面了解下python标准模块对于阅读理解各种第三方模块的源码很有帮助。我个人感觉到的就是python还真是强大,各种功能都有,确实是unix管理者和黑客爱的玩意儿。我估计也会在这条路上走的越来越远。(虽然以前也写了好几年的php,objective-c,java,但从来没有这么认真过。_)
可以搭配着《unix环境高级编程》一起阅读,要不然有些概念是看了完全没有印象的。
代码已经入github

内容

sys 模块可以让你访问解释器相关参数,比如模块搜索路径,解释器版本号等.
operator 模块提供了和内建操作符作用相同的函数.
copy 模块允许你复制对象

核心模块

内置模块__builtin__

apply, 感觉和js中的apply一样。python中的参数其实大体上只有两种形式,一个是位置参数,另一个是关键字参数。函数参数可以参考廖雪峰的函数的参数

__import__ import 语句,其实是调用的内建的 import 函数。可以根据字符串动态地把module import进来,有啥用呢? 很多框架里面其实都用到了这个。假设你的框架里用了MVC,有个controlers目录,你就可以遍历这个目录,把定义好的名字如UserController.py,等 动态地全部import进来。。而不用一个一个手动去import。

reload有个注意事项:

注意,当你重加载模块时, 它会被重新编译, 新的模块会代替模块字典里的老模 块. 但是, 已经用原模块里的类建立的实例仍然使用的是老模块(不会被更新).
同样地, 使用 from-import 直接创建的到模块内容的引用也是不会被更新的.

dir,没啥好说,看帮助文档就用dir和help。

vars, 这个感觉有也用。运用的好,可以极大地减少代码量。

type 函数,我感觉这个更多地是做类型检查。可以加强代码的健壮性。同时也增加了动态的能力。

__call__ 使得类实现变成callable, 具体实现可以参见廖雪峰的Day 5 – 编写Web框架, 这个框架可以看看,其它框架其实也是这个思路。

你不能使用 type 函数来测试一个实例是否属于一个给定的类; 所有 的实例都是同样的类型! 为解决这个问题,有isinstance。
issubclass 检查的是类型树。

eval,js中也有eval,作用相同。把字符串当成脚本执行。同样都要注意安全问题,字符串可能包含恶意代码。
在python中可以是删除文件。 在js中可以是直接把cookie信息发送到另一个服务器。
在python中,可以通过第二个参数,限定eval能使用的模块。

eval处理简单的表达式,复杂的得用 compileexec函数。

execfile函数,提供了一个从文件加载代码,编译代码,执行代码 快捷方式。

因为 Python 在检查局部名称空间和模块名称空间前不会检查内建函数, 所以 有时候你可能要显式地引用 __builtin__ 模块.(注:就是说你定义的名字,覆盖掉了__builtin__的东西,想调用原来的东西就得显示引用__builtin__模块)

exceptions模块

这个我还是建议了解下,当你自定义的异常选择了恰当的父类,会显得你非常专业。
该模块定义了以下标准异常:

  • Exception 是所有异常的基类. 强烈建议(但不是必须)自定义的异常异 常也继承这个类.
  • SystemExit(Exception) 由 sys.exit 函数引发. 如果它在最顶层没有 被 try-except 语句捕获, 那么解释器将直接关闭而不会显示任何跟踪 返回信息.
  • StandardError(Exception) 是所有内建异常的基类(除 SystemExit 外).
  • KeyboardInterrupt(StandardError) 在用户按下 Control-C(或其他打 断按键)后 被引发. 如果它可能会在你使用 “捕获所有” 的 try-except 语句时导致奇怪的问题.
  • ImportError(StandardError) 在 Python 导入模块失败时被引发.
  • EnvironmentError 作为所有解释器环境引发异常的基类. (也就是说,
    这些异常一般不是由于程序 bug 引起).
  • IOError(EnvironmentError) 用于标记 I/O 相关错误.
  • OSError(EnvironmentError) 用于标记 os 模块引起的错误.
  • WindowsError(OSError) 用于标记 os 模块中 Windows 相关错误.
  • NameError(StandardError) 在 Python 查找全局或局部名称失败时被引
    发.
  • UnboundLocalError(NameError) , 当一个局部变量还没有赋值就被使用
    时, 会引发这个异常. 这个异常只有在 2.0 及之后的版本有; 早期版本
    只会引发一个普通的 NameError .
  • AttributeError(StandardError) , 当 Python 寻找(或赋值)给一个实
    例属性, 方法, 模块功能或其它有效的命名失败时, 会引发这个异常.
  • SyntaxError(StandardError) , 当解释器在编译时遇到语法错误, 这个
    异常就被引发.
  • (2.0 及以后版本) IndentationError(SyntaxError) 在遇到非法的缩进
    时被引发. 该异常只用于 2.0 及以后版本, 之前版本会引发一个 SyntaxError 异常.
  • (2.0 及以后版本) TabError(IndentationError) , 当使用 -tt 选项检 查不一致缩进时有可能被引发. 该异常只用于 2.0 及以后版本, 之前版 本会引发一个 SyntaxError 异常.
  • TypeError(StandardError) , 当给定类型的对象不支持一个操作时被引 发.
  • AssertionError(StandardError) 在 assert 语句失败时被引发(即表达 式为 false 时).
  • LookupError(StandardError) 作为序列或字典没有包含给定索引或键时 所引发异常的基类.
  • IndexError(LookupError) , 当序列对象使用给定索引数索引失败时(不 存在索引对应对象)引发该异常.
  • KeyError(LookupError) 当字典对象使用给定索引索引失败时(不存在索 引对应对象)引发该异常.
  • ArithmeticError(StandardError) 作为数学计算相关异常的基类.
  • OverflowError(ArithmeticError) 在操作溢出时被引发(例如当一个整
    数太大, 导致不能符合给定类型).
  • ZeroDivisionError(ArithmeticError) , 当你尝试用 0 除某个数时被
    引发.
  • FloatingPointError(ArithmeticError) , 当浮点数操作失败时被引发.
  • ValueError(StandardError) , 当一个参数类型正确但值不合法时被引
    发.
  • (2.0 及以后版本) UnicodeError(ValueError) , Unicode 字符串类型相
    关异常. 只使用在 2.0 及以后版本.
  • RuntimeError(StandardError) , 当出现运行时问题时引发, 包括在限
    制模式下尝试访问外部内容, 未知的硬件问题等等.
  • NotImplementedError(RuntimeError) , 用于标记未实现的函数, 或无
    效的方法.
  • SystemError(StandardError) , 解释器内部错误. 该异常值会包含更多
    的细节 (经常会是一些深层次的东西, 比如 “eval_code2: NULL globals” ) . 这本书的作者编了 5 年程序都没见过这个错误. (想必是 没有用 raise SystemError ).
  • MemoryError(StandardError) , 当解释器耗尽内存时会引发该异常. 注 意只有在底层内存分配抱怨时这个异常才会发生; 如果是在你的旧机器 上, 这个异常发生之前系统会陷入混乱的内存交换中

os模块

封装了操作系统细节,跨平台用的。
open/file 处理文件
listdir 列出目录列表,需要注意的是并没有包含”.”(当前目录)和”..”(上级目录)两个目录。
getcwdchdir 函数分别用于获得和改变当前工作目录.
makedirsremovedirs 函数用于创建或删除目录层。removedirs只能移除空目录。如果目录里有文件,会抛异常。(如果需要删除非空目录, 你可以使用shutil 模块中的 rmtree 函数)
mkdirrmdir 函数只能处理单个目录级
statfstat 函数可以用来获取一个存在文件的信息.(在管道中文件是没有名字的,只能用fstat)
chmodutime 函数修改文件的权限模式和时间属性
system 函数在当前进程下执行一个新命令, 并等待它完成。其实system 就是打开一个新进程(fork),新进程执行命令(exec),父进程等待子进程完成(wait),拿到输出结果。
exec 函数会使用新进程替换当前进程。基本上exec簇总是和fork在一起的。Flask Web开发 基于Python的Web应用开发实战这本书里,巧妙地在设置环境变量后用exec函数重启应用。

所有的守护进程都没有控制终端,其终端名设置为问号
创建守护进程的方法很简单,先fork复制一个进程,然后把自己退出。这样子进程就成了孤儿进程。
完整的经验规则是:

   1. 首先要做的是调用umask将文件模式创建屏蔽字设置为一个已知值(通常是0)。由继承得来的文件模式创建屏蔽字
      可能会被设置为拒绝某些权限。
   2. 调用fork,然后使父进程exit。这样做实现了下面几点。第一,如果该守护进程是作为一条简单的shell命令启动的,那么
      父进程终止会让shell认为这条命令已经执行完毕。第二,虽然子进程继承了父进程的进程组ID,但获得了一个新的进程ID,
      这就保证了子进程不是一个进程组的组长长进程。这是下面将要进得的setsid调用的先决条件。
   3. 调用setsid创建一个新会话。使进程:a 成为新会话的首进程 b、成为一个新进程组的组长进程。c、没有控制终端
   4. 将当前工作目录更改为根目录。从父进程处继承过来的当前工作目录可能是一个挂载的文件系统中。
      因为守护进程通常是在系统再引导之前是一直存在的,所以如果守护进程的当前工作目录在一个挂载文件系统中,
      那么该文件系统就不能被卸载。
   5. 关闭不再需要的文件描述符。
   6. 某些守护进程打开/dev/null使其具有文件描述符0、1、2.这样,任何一个试图读标准输入、写标准输出或标准错误的库例程
      都不会产生任何效果。

exit在被捕获异常的情况下,并不会真的终止进程,而_exit则会。

os.path处理文件名

os.path 模块包含了许多与平台无关的处理长文件名的函数. 也就是说, 你不需要处理前后斜杠, 冒号等
expanduser 把目录中的”~”,解析成实际的用户目录。
expandvars 函数将文件名中的环境变量替换为对应值。
walk 函数会帮你找出一个目录树下的所有文件。感觉类似于find命令。至少可以很方便地利用walk实现find命令。
os.listdir 只列表一级目录。再往下得自己去递归。
文中的DirectoryWalker 并不是generator,而是因为实现了getitem方法,成为了可迭代对象。

其它模块

string, 字符串估计是要打交道最多的模块了。用的时候,用dir(string)看下有哪些功能。平时用的更多是字符串方法。
re, 正则表达式语法没啥。关键是知道正达式是啥,语法反而不重要。推荐看下《精通正则表达式》,讲的很透彻。这里要吐槽下Java的正则表达式。。有次项目里居然在正则表达式这里挂了,因为匹配失败,居然迭代了几十亿次,直接导致后面的代码没机会执行(参考:http://blog.csdn.net/shixing_11/article/details/5997567),阿里还有人专门自己写了个java的正则表达式。
math 模块实现了许多对浮点数的数学运算函数. 这些函数一般是对平台 C 库 中同名函数的简单封装
cmath 模块实现复数的计算。
operator 模块为 Python 提供了一个 “功能性” 的标准操作符接口
需要注意的是单个字符也是序列。在使用时得注意下。
copy 模块提供拷贝功能。分浅拷贝和深拷贝。copy.copy是浅拷贝,copy.deepcopy是深拷贝。
sys 模块提供了许多函数和变量来处理 Python 运行时环境的不同部分。在命令行脚本中用提比较多。

    * sys.argv, sys.path, sys.builtin_module_names,sys.modules。标准库可以多用下help和        dir来获取信息。
    * python通过引用计数来管理的内存,引用计数可以通过sys.getrefcount获取到。
    * 可以通过sys.platform判断当前是啥系统,然后写针对该系统的特定代码。
    * sys.setprofile函数允许你配置一个分析函数(profiling function). 这个函数 会在每次调用      某个函数或方法时被调用(明确或隐含的), 或是遇到异常的时候 被调用。适宜做分析工具,基于该函     数, profile 模块提供了一个完整的分析器框架.
    * sys.settrace, pdb基于这个实现的。
    * sys.stdin,sys.stdout,sys.stderr 要重定向输出只要创建一个对象, 并实现它的 write 方法.
    * sys.exit退出程序,可捕获。
    * sys.exitfunc,可以在exit之前做一些清理操作。。感觉是那些不会自动释放的资源有必要用这个东西来做。

atexit
对sys.exitfunc封装了一下,可以方便地注册多个退出钩子函数。后注册的先调用。
time模块 提供了获取当前时间,字符串到时间对象的相互转换。
types 模块包含了标准解释器定义的所有类型的类型对象
gc 模块,提供了到内建循环垃圾收集器的接口。gc.collect用来回收自引用的数据结构的对象。

更多标准模块

  • fileinput 模块允许你循环一个或多个文本文件的内容。利用glob.glob可以模糊搜索文件,然后利用fileinput模块可以把文件统一处理。
  • shutil 模块 shell util?shutil 实用模块包含了一些用于复制文件和文件夹的函数.可以删除非空目录哦,os.removedirs可不行。
  • tempfile模块。tempfile.mktemp其实并不安全,在获取临时文件名和创建文件之间有个时间窗口,在这期间可能有其它程序创建了同名文件。不如用tempfile.TemporaryFile()
  • StringIO 模块。提供了内建文件一样的函数,区别是在内存中执行,速度会很快。当然由于受到内存的限制,不能处理过大的文件。
  • cStringIO 模块是StringIO更快速的实现。
  • mmap 模块提供了操作系统内存映射函数的接口。把文件的数据 映射到一块内存操作。效率很高。具体概念请看内存映射文件原理
  • UserDict 模块包含了一个可继承的字典类 (事实上是对内建字典类型的 Python 封装).
  • UserList 模块包含了一个可继承的列表类 (事实上是对内建列表类型的 Python 封装).
  • UserString 模块包含两个类, UserString 和 MutableString .MutableString性能不高,不如用array模块
  • traceback 模块允许你在程序里打印异常的跟踪返回 (Traceback)信息, 类似未捕获异常时解释器所做的。可以使用 traceback.extract_tb 函数格式化跟踪返回信息, 得到包含错误信息的列表
  • errno 模块定义了许多的符号错误码, 比如 ENOENT (“没有该目录入口”) 以及 EPERM (“权限被拒绝”).
  • getopt 模块包含用于抽出命令行选项和参数的函数, 它可以处理多种格式的选 项。在python绝技:运用python成为顶级黑客中用的挺多,不过书里用的是optparse,现在应该用getopt了。
  • getpass 模块提供了平台无关的在命令行下输入密码的方法. 在做需要命令行用户认证时有用。
  • glob 根据给定模式生成满足该模式的文件名列表, 和 Unix shell 相同.星号(* ) 匹配零个或更多个字符, 问号(? ) 匹配单个字符. 你也可以使用方括号来指定字符范围, 例如 [0-9] 代表一个数字. 其他所有字符都代表它们本身。
  • fnmatch 模块使用模式来匹配文件名. glob是根据模式返回文件名列表。fnmatch是用模式来判断文件名是否匹配模式,返回True/False。fnmatch.translate可以把模式转成正则表达式。glob 和 find 模块在内部使用 fnmatch 模块来实现.
  • random 模块包含许多随机数生成器。choice随机挑选,shuffle打乱。gauss (高斯)函数来生成满足高斯分的布随机数字(是伪随机生成器,并不适合密码学用途)
  • md5 (Message-Digest Algorithm 5)模块用于计算信息密文(信息摘要). 新版用hashlib。工作中基本是用的16进制的,即hexdigest。
  • sha 模块提供了计算信息摘要(密文)的另种方法。已过期,新版用hashlib。
  • crypt 模块实现了单向的 DES 加密, Unix 系统使用这个 加密算法来储存密码, 这个模块真正也就只在检查这样的密码时有用.密码验证一定得用不可逆的加密算法,这样即使暴库,也不至于泄露密码。即使这样也应该提供salt,不同的密码用不同的salt,这样防止别人搞一个md5库和crypt库暴力反解(彩虹库暴力破解)。crypt-example-2.py在mac上测试失败,密码都是*号,同时获取密码最不好不用raw_input,用getpass模块比较好,不会在屏幕上回显密码
  • zlib 模块为 “zlib” 压缩提供支持。compress 和 decompress 提供压缩和解压。在python绝技:运用python成为顶级黑客中用到了,用来暴力破解。在内容少的时候,经过压缩文件反而变大了,呃。。
  • code 模块提供了一些用于模拟标准交互解释器行为的函数。类似功能的还有evalcompileexec函数、execfile模块

线程和进程

为了保证两个线程可以同时访问相同的内部数据, Python 使用了 global interpreter lock (全局解释器锁) . 在同一时间只可能有一个线程执行 Python 代码;(这意味着python不能运用到多核CPU的威力,真要用只能使用多进程了。)
threading 模块为线程提供了一个高级接口。
Queue 模块提供了一个线程安全的队列 (queue) 实现.
thread 模块提为线程提供了一个低级 (low_level) 的接口.注意当主程序退出的时候, 所有的线程也随着退出. 而 threading 模块不存在 这个问题 . (该行为可改变)
commands 模块(仅适应unix)包含一些用于执行外部命令的函数
pipes 模块(只用于 Unix)提供了 “转换管道 (conversion pipelines)” 的支持. 你可以创建包含许多外部工具调用的管道来处理多个文件.
popen2 模块允许你执行外部命令, 并通过流来分别访问它的 stdin 和 stdout ( 可能还有 stderr ). popen2已经被subprocess替代。
signal 模块配置你自己的信号处理器 (signal handler)

数据表示

marshal 和 pickle 模块用于在不同的 Python 程序间共享/传递数据.
marshal 模块使用了简单的自描述格式( Self-Describing Formats ), 它支持 大多的内建数据类型, 包括 code 对象. Python 自身也使用了这个格式来储存 编译后代码( .pyc 文件).
pickle 模块提供了更复杂的格式, 它支持用户定义的类, 自引用数据结构等等. pickle 是用 Python 写的, 相对来说速度较慢, 不过还有一个 cPickle 模块, 使用 C 实现了相同的功能, 速度和 marshal 不相上下.

  • array 模块实现了一个有效的阵列储存类型. 阵列和列表类似, 但其中所有的 项目必须为相同的类型. 该类型在阵列创建时指定.
  • struct 模块用于转换二进制字符串和 Python 元组. pack 函数接受格式字符串以及额外参数, 根据指定格式将额外参数转换为二进制字符串. upack 函数 接受一个字符串作为参数, 返回一个元组.
  • xdrlib 模块用于在 Python 数据类型和 Sun 的 external data representation (XDR) 间相互转化
  • marshal 模块可以把不连续的数据组合起来 – 与字符串相互转化, 这样它们就 可以写入文件或是在网络中传输.
  • pickle 模块同 marshal 模块相同, 将数据连续化, 便于保存传输. 它比 marshal 要慢一些, 但它可以处理类实例, 共享的元素, 以及递归数据结构等,pickle 不能处理 code 对象
  • cPickle 模块是针对 pickle 模块的一个更快的实现.
  • copy_reg 模块注册你自己的扩展类型.这样 pickle 和 copy 模 块就会知道如何处理非标准类型.
  • pprint 模块( pretty printer )用于打印 Python 数据结构.
  • repr 模块提供了内建 repr 函数的另个版本. 它限制了很多(字符串长度, 递 归等).
  • base64 base64 编码体系用于将任意二进制数据转换为纯文本. 它将一个 3 字节的二 进制字节组转换为 4 个文本字符组储存, 而且规定只允许以下集合中的字符出 现:
    ABCDEFGHIJKLMNOPQRSTUVWXYZ
    abcdefghijklmnopqrstuvwxyz
    0123456789+/
    另外, = 用于填充数据流的末尾. 有时我们会把base64作为url的参数传输,这时要注意末尾的=号要处理下。
  • binhex 模块用于到 Macintosh BinHex 格式的相互转化.
  • quopri 模块基于 MIME 标准实现了引用的可打印编码
  • uuuu 编码体系用于将任意二进制数据转换为普通文本格式. 该格式在新闻组中很 流行, 但逐渐被 base64 编码取代.
  • binascii binascii 提供了多个编码的支持函数, 包括 base64 , binhex , 以及 uu

文件格式

  • xmllib 模块. 已经被xml.sax替代。
  • xml.parsers.expat 模块是 James Clark’s Expat XML parser 的接口.
  • sgmllib 模块, 提供了一个基本的 SGML 语法分析器. 它与 xmllib 分析器基 本相同, 但限制更少(而且不是很完善).
  • htmlib 模块包含了一个标签驱动的( tag-driven ) HTML 语法分析器, 它会将数据发送至一个格式化对象.
  • htmlentitydefs 模块包含一个由 HTML 中 ISO Latin-1 字符实体构成的字典.
  • formatter 模块提供了一些可用于 htmllib 的格式类( formatter classes ).这些类有两种, formatter 和 writer . formatter 将 HTML 解析器的标签和数 据流转换为适合输出设备的事件流( event stream ), 而 writer 将事件流输出 到设备上.
  • ConfigParser 模块用于读取配置文件.格式类似于ini文件。
  • netrc 模块可以用来解析 .netrc 配置文件。该文件 用于在用户的 home 目录储存 FTP 用户名和密码. (别忘记设置这个文件的属 性为: “chmod 0600 ~/.netrc,” 这样只有当前用户能访问).
  • shlex 模块为基于 Unix shell 语法的语言提供了一个简单的 lexer (也就是 tokenizer).
  • zipfile 模块可以用来读写 ZIP 格式.
  • gzip 模块用来读写 gzip 格式的压缩文件.

邮件和新闻消息处理

  • rfc822 模块包括了一个邮件和新闻组的解析器 (也可用于其它符合 RFC 822 标准的消息, 比如 HTTP 头).
    通常, RFC 822 格式的消息包含一些标头字段, 后面至少有一个空行, 然后是信 息主体.
  • mimetools 模块包含一些读写 MIME 信息的工具. 它还提供了一个类似 rfc822 模块中 Message 的类, 用于处理 MIME 编码的信息.
  • MimeWriter 模块用于生成符合 MIME 邮件标准的 “multipart” 的信息。已被email模块替代。
  • mailbox 模块用来处理各种不同类型的邮箱格式。
  • mailcap 模块用于处理 mailcap 文件, 该文件指定了不同的文档格式的处理方 法( Unix 系统下).
  • mimetypes 模块可以判断给定 url ( uniform resource locator , 统一资源定 位符) 的 MIME 类型. 它基于一个内建的表, 还可能搜索 Apache 和 Netscape 的配置文件
  • packmail 模块可以用来创建 Unix shell 档案. 已经废弃
  • mimify 模块用于在 MIME 编码的文本信息和普通文本信息(例如 ISO Latin 1 文本)间相互转换.已被email模块替代。
  • multifile 模块允许你将一个多部分的 MIME 信息的每部分作为单独的文件处理2.5之后废弃

网络协议(这个是web开发需要关注的重点)

  • socket 模块实现了到 socket 通讯层的接口. 你可以使用该模块创建客户端或 是服务器的 socket
  • select 模块允许你检查一个或多个 socket , 管道, 以及其他流兼容对象所接 受的数据。
  • asyncore 模块提供了一个 “反馈性的( reactive )” socket 实现. 该模块允许 你定义特定过程完成后所执行的代码, 而不是创建 socket 对象, 调用它们的方法. 你只需要继承 dispatcher 类, 然后重载如下方法 (可以选择重载某一 个或多个)就可以实现异步的 socket 处理器.
    • handle_connect : 一个连接成功建立后被调用.
    • handle_expt : 连接失败后被调用.
    • handle_accept : 连接请求建立到一个监听 socket 上时被调用. 回调时( callback )应该使用 accept 方法来获得客户端 socket .
    • handle_read : 有来自 socket 的数据等待读取时被调用. 回调时应该使用 recv 方法来获得数据.
    • handle_write : socket 可以写入数据的时候被调用. 使用 send 方法写入数据.
    • handle_close : 当 socket 被关闭或复位时被调用.
    • handle_error(type, value, traceback) 在任何一个回调函数发生Python 错误时被调用. 默认的实现会打印跟踪返回消息到 sys.stdout .
  • asynchat 模块是对 asyncore 的一个扩展. 它提供对面向行( line-oriented ) 的协议的额外支持. 它还提供了增强的缓冲区支持(通过 push 方法和 “producer” 机制.
  • urlib 模块为 HTTP , FTP , 以及 gopher 提供了一个统一的客户端接口. 它会 自动地根据 URL 选择合适的协议处理器.
  • urlparse 模块包含用于处理 URL 的函数, 可以在 URL 和平台特定的文件名间 相互转换
  • cookie 模块为 HTTP 客户端和服务器提供了基本的 cookie 支持.
  • robotparser 模块用来读取 robots.txt 文件. 做为一个有良心的爬虫,最好还是遵循下robot协议。
  • ftplib 模块包含了一个 File Transfer Protocol (FTP , 文件传输协议)客户 端的实现.
  • gopherlib 模块包含了一个 gopher 客户端实现.Gopher是Internet上一个非常有名的信息查找系统,它将Internet上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点,现在已经过时。
  • httplib 模块提供了一个 HTTP 客户端接口
  • poplib 模块(如 Example 7-28 所示) 提供了一个 Post Office Protocol( POP3 协议) 客户端实现. 这个协议用来从邮件服务器 “pop” (拷贝) 信息到 你的个人电脑.
  • imaplib 模块提供了一个 Internet Message Access Protocol ( IMAP, Internet 消息访问协议) 的客户端实现. 这个协议允许你访问邮件服务器的邮件目录, 就好像是在本机访问一样.
  • smtplib 模块提供了一个 Simple Mail Transfer Protocol (SMTP , 简单邮件 传输协议) 客户端实现. 该协议用于通过 Unix 邮件服务器发送邮件。 读取邮件请使用 poplib 或 imaplib 模块.
  • telnetlib 模块提供了一个 telnet 客户端实现.
  • nntplib 模块提供了一个网络新闻传输协议( Network News Transfer Protocol, NNTP,网络新闻传输协议)客户端的实现.
  • SocketServer 为各种基于 socket 的服务器提供了一个框架. 该模块提供了大量的类, 你可以用它们来创建不同的服务器.
  • BaseHTTPServer 模块,这是一个建立在 SocketServer 框架上的基本框架, 用于 HTTP 服务器.
  • SimpleHTTPServer 模块是一个简单的 HTTP 服务器, 它提供了标准的 GET 和 HEAD 请求处理器.
  • CGIHTTPServer 模块是一个可以通过公共网关接口( common gateway interface , CGI )调用外部脚本的 HTTP 服务器.
  • cgi 模块为 CGI 脚本提供了函数和类支持. 它还可以处理 CGI 表单数据.
  • webbrowser 模块提供了一个到系统标准 web 浏览器的接口. 哈。居然调起了chrome在打开页面。。

国际化

  • locale 模块提供了 C 本地化( localization )函数的接口
  • unicodedata 模块包含了 Unicode 字符的属性, 例如字符类别, 分解数据, 以及数值
  • ucnhash 模块为一些 Unicode 字符代码提供了特定的命名. 你可以直接使用 \N{} 转义符将 Unicode 字符名称映射到字符代码上.
    ##多媒体相关模块
  • imghdr 模块可识别不同格式的图片文件. 当前版本可以识别 bmp , gif , jpeg , pbm , pgm , png , ppm , rast (Sun raster), rgb (SGI), tiff , 以及 xbm 图 像.
  • sndhdr 模块, 可来识别不同的音频文件格式, 并提取文件内容相关信息
  • aifc 模块用于读写 AIFF 和 AIFC 音频文件(在 SGI 和 Macintosh 的计算机 上使用).
  • sunau 模块用于读写 Sun AU 音频文件
  • sunaudio 模块用于识别 Sun AU 音频文件, 并提取其基本信息. sunau 模块为 Sun AU 文件提供了更完成的支持.
  • wave 模块用于读写 Microsoft WAV 音频文件
  • audiodev 为 Sun 和 SGI 计算机提供了音频播放支持.(only unix)
  • winsound 模块允许你在 Winodws 平台上播放 Wave 文件.(only windows)

数据储存

Python 提供了多种相似数据库管理( database manager )的驱动, 它们的模型 都基于 Unix 的 dbm 库.

  • anydbm 模块为简单数据库驱动提供了统一标准的接口.anydbm 模块会自动寻找一个合适的数据库驱动, 按照 dbhash , gdbm , dbm , 或 dumbdbm 的顺序尝试. 如果没有找到任何模块, 它 将引发一个 ImportError 异常.
  • whichdb 模块可以判断给定数据库文件的格式。
  • shelve 模块使用数据库驱动实现了字典对象的持久保存. shelve 对象使用字 符串作为键, 但值可以是任意类型, 所有可以被 pickle 模块处理的对象都可 以作为它的值.
  • dbhash 模块为 bsddb 数据库驱动提供了一个 dbm 兼容的接口
  • dbm 模块提供了一个到 dbm 数据库驱动的接口(在许多 Unix 平台上都 可用)
  • dumbdbm 模块是一个简单的数据库实现, 与 dbm 一类相似, 但使用纯 Python 实现. 它使用两个文件: 一个二进制文件 (.dat ) 用于储存数据, 一个文本文 件 (.dir ) 用于数据描述.
  • gdbm 模块提供了到 GNU dbm 数据驱动的接口
    ##工具和实用程序
    标准库中有一些模块既可用作模块又可以作为命令行实用程序.
  • dis 模块是 Python 的反汇编器. 它可以把字节码转换为更容易让人看懂的格式。个人觉得要成为真正的大师,汇编一定得学学。我在mac上,python2.7 并不能直接dis.py hello.py, 改成python -m dis hello.py可以
  • pdb 模块是标准 Python 调试器( debugger ). 它基于 bdb 调试器框架.
  • bdb 模块为提供了一个调试器框架. 你可以使用它来创建自定义的调试器
  • profile 模块是标准 Python 分析器.
  • pstats 模块用于分析 Python 分析器收集的数据
  • tabnanny 模块用于检查 Python 源文件中的含糊的缩进. 当文件 混合了 tab 和空格两种缩进时候, nanny (保姆)会立即给出提示.
    ##其它模块
  • fcntl 模块(只用于 Unix)为 Unix 上的 ioctl 和 fcntl 函数提供了一个接口. 它们用于文件句柄和 I/O 设备句柄的 “out of band” 操作, 包括读取扩展属性, 控制阻塞. 更改终端行为等等.
  • pwd (只用于 Unix) 提供了一个到 Unix 密码/password “数据库”( /etc/passwd 以及相关文件 )的接口
  • grp 模块(只用于 Unix) 提供了一个到 Unix 用户组/group ( /etc/group )数 据库的接口.
  • nis 模块 This module contains functions for accessing NIS maps.
  • curses 模块 The curses module provides an interface to the curses library, the de-facto standard for portable advanced terminal handling.
  • termios 模块 (只用于 Unix , 可选) termios 为 Unix 的终端控制设备提供了一个接口. 它可用于控制终端通讯端口的大多方面.
  • tty 模块(只用于 Unix) 包含一些用于处理 tty 设备的工具函数。
  • resource 模块(只用于 Unix , 可选) 用于查询或修改当前系统资源限制设置.
  • syslog 模块(只用于 Unix 可选) 用于向系统日志设备发送信息( syslogd ). 这些信息如何处理依不同的系统而定, 通常会被记录在一个 log 文件中, 例如 /var/log/messages , /var/adm/syslog , 或者其他类似处理.
  • msvcrt 模块(只用于 Windows/DOS ) 用于访问 Microsoft Visual C/C++ Runtime Library (MSVCRT) 中函数的方法.
  • nt 模块(非直接使用模块, 只用于 Windows ) nt 模块是 os 模块在 Windows 平台下调 用的执行模块. 几乎没有任何原因直接使用这个模块, 请使用 os 模块替代.
  • _winreg 模块(只用于 Windows , 2.0 中新增) _winreg 模块提供了访问 Windows 注册表数 据库的一个基本接口.
  • posix 模块(非直接使用模块, 只用于 Unix/POSIX ) posix 模块是 os 模块在 Unix 及其 他 POSIX 系统下使用的实现模块. 一般只需要通过 os 模块访问它即可.

执行支持模块

  • dospath 模块提供了 DOS 平台下的 os.path 功能
  • macpath 模块( 参见 Example 13-2 )提供了 Macintosh 平台下的 os.path 功 能. 你也可以使用它在其他平台处理 Macintosh 路径.
  • ntpath 模块( 参见 Example 13-3 )提供了 Windows 平台下的 os.path 功能. 你也可以使用它在其他平台处理 Windows 路径.
  • posixpath 模块( 参见 Example 13-4 )提供了 Unix 和其他 POSIX 兼容平台下 的 os.path 功能
  • imp 模块包含的函数可以用于实现自定义的 import 行为
  • new 模块是一个底层的模块, 你可以使用它来创建不同的内建对象, 例如类对 象, 函数对象, 以及其他由 Python 运行时系统创建的类型.
  • py_compile 模块用于将 Python 模块编译为字节代码. 它和 Python 的 import 语句行为类似, 不过它接受文件名而不是模块名作为参数
  • compileall 模块用于将给定目录下(以及 Python path )的所有 Python 脚本编 译为字节代码. 它也可以作为可执行脚本使用(在 Unix 系统下, Python 安装 时会自动调用执行它).
  • ihooks 模块为替换导入提供了一个框架. 这允许多个导入机制共存.
  • linecache 模块用于从模块源文件中读取代码. 它会缓存最近访问的模块 (整 个源文件).traceback 模块使用这个模块实现了对导入操作的跟踪.
  • macurl2path 模块用于 URL 和 Macintosh 文件名的相互映射. 一般没有必要直接使用它, 请使用 urllib 中的机制.
  • nturl2path 模块用于 URL 和 Windows 文件名的相互映射.
  • tokenize 模块将一段 Python 源文件分割成不同的 token . 你可以在代码高亮工具中使用它.
  • keyword 模块有一个包含当前 Python 版本所使用的关键字的列表. 它还提供了一个字典, 以关键字作为key, 以一个描述性函数作为value, 它可用于检查给定单词是否是 Python 关键字.
  • parser 模块提供了一个到 Python 内建语法分析器和编译器的接口
  • symbol 模块包含 Python 语法中的非终止符号. 可能只有你涉及 parser 模块 的时候用到它
  • token 模块包含标准 Python tokenizer 所使用的 token 标记.

其它模块(少用)

  • pyclbr 模块包含一个基本的 Python 类解析器
  • filecmp 模块用于比较文件和目录
  • cmd 模块为命令行接口( command-line interfaces , CLI )提供了一个简单的 框架. 它被用在 pdb 模块中, 当然你也可以在自己的程序中使用它。你只需要继承 Cmd 类, 定义 do 和 help 方法. 基类会自动地将这些方法转换 为对应命令.
  • readline 模块使用 GNU readline 库(或兼容库)实现了 Unix 下增强的 输入编辑支持
  • rlcompleter 模块为 readline 模块提供了单词自动完 成功能.
  • statvfs 模块包含一些与 os.statvfs (可选)函数配合使用的常量和函数, 该 函数会返回文件系统的相关信息
  • calendar 模块是 Unix cal 命令的 Python 实现. 它可以将给定年份/月份的 日历输出到标准输出设备上.
  • sched 模块为非线程环境提供了一个简单的计划任务模式
  • statcache 模块提供了访问文件相关信息的相关函数. 它是 os.stat 的扩展模 块, 而且它会缓存收集到的信息.2.7没看到
  • grep 模块提供了在文本文件中搜索字符串的另种方法已经废弃
  • bisect 模块用于向排序后的序列插入对象.insort(sequence, item) 将条目插入到序列中, 并且保证序列的排序. 序列可 以是任意实现了 __getitem__ 和 insert 方法的序列对象.
    其它废弃的模块没写了。

学会提问十大关键问题之【理由是什么】

学会提问十大关键问题之【理由是什么】

所谓理由,就是指用来支撑或证明结论的看法、证据、隐喻、类比和其他陈述。

当一位作家有个结论希望你接受的时候,他不但要提供各种理由来说明他的结论是正确的,而且要证明为什么他的结论是正确的。

只有当你找到支撑结论的理由时你才能判定一个结论的价值。

只有论证和推理中才有可能存在逻辑错误。因为一个理由本身只是一个孤立的想法,它并不能反映出一种逻辑关系。

论证本身的几个特点值得我们加以注意:

  • 论证必有其目的。人们展开论证的目的是希望说明我们相信某些事情或是按某些特定的方式行动,所以论证需要别人对之做出回应。不论我们的反应类似于海绵还是淘金者,我们一般总会做出回应。
  • 论证的质量有高有低。我们需要依赖批判性思维来判定一个论证的质量高低。
  • 论证有两个明显的必要构成部分–一个结论及其支撑理由。二者当中如果有一个我们找不到,也就意味着我们失去了客观评价这一论证的机会。我们无法找到的东西自然也无法对其做出评价。

要想成为一个理由,一个陈述(或一系统陈述)必须被演说者用做结论的支撑或根据。

找到结论有提示词

如同寻找结论的情形一样,有些特定的词常常显示出紧随其后的往往就是理由。请记住:推理论证的基本结构是“甲之所以成立是因为乙”。这样,“因为”这个词,以及与之意义相同或功能相近的词,经常提示我们理由会紧随其后出现。以下是表示理由的一些提示词:

  • 由于(as a result of)
  • 因为这个原因(for the reason that)
  • 因为这个事实(because of the fact that)
  • 鉴于(in view of)
  • 由以下材料支撑(is supported by)
  • 因为证据是(because the evidence is)
  • 研究显示(studies show)
  • 第一,第二,第三(first….second….third)

理由是模具,结论据此成型

当作者或演说家尽力证明一个描述性结论,对“为什么”这个问题的回答通常就是证据。

请记住:结论本身并不是证据,它是由一个证据或其他看法支撑起来的看法。

在规定性论证中,理由常常不是一般性的规定性陈述就是描述性的看法或原则。

薄弱的理由必然导致薄弱的推论
理想的做法是,理由是模具,结论据此得以成型和修改

推荐阅读:
学会提问
学会提问十大关键问题之论题和结论是什么

第三章 文件I/O

第三章 文件I/O

引言

UNIX系统中的大多数文件I/O只需要用到5个函数:open、read、write、lseek以及close。

本章说明的函数经常被称为不带缓冲的I/O。术语 ****不带缓冲**** 指的是每个read和write都调用内核的一个系统调用。

多个进程共享文件 相关的函数:dup、fcntl、sync、fsync和ioctl

文件描述符

文件描述符的变化范围是0~OPENMAX。

open函数

#include
int open(const char pathname, int oflag, … / modet mode */);

ODSYNC和OSYNC标志有微妙的区别。仅当文件属性需要更新以反映文件数据变化(例如,更新文件大小以反映文件中包含了更多的数据)时,ODSYNC标志
才影响文件属性。而设置OSYNC标志后,数据和属性总是同步更新。当文件用ODSYNC标志打开,在重写其现有的部分内容时,文件时间属性不会同步更新。与此相反,如果文件是用OSYNC标志打开,那么对该文件的每一次
write操作都将在write返回前更新文件时间, 这与是否改写现有字节或增写文件无关。

由open返回的文件描述符一定是最小的未用描述符数值。

POSIXNNOTRUNC有效,则在整个路径名超过PATHMAX, 或路径名中任一文件名超过NAMEMAX时,返回出错状态,并将errno设置为ENAMETOOLONG。

create函数

#include
int create(const char *pathname, modet mode);
此函数等效于open(pathname, OWRONLY | OCREATE | OTRUNC, mode);

close函数

#include
int close(int filedes);

关闭一个文件时还会释放该进程加在该文件上的所有 ****记录锁****
当一个进程终止时,内核自动关闭它所有打开的文件。

lseek函数

#include
offt lseek(int filedes, offt offset, int whence);

可以用以下方式确认当前文件偏移量
offt currpos;
currpos = lseek(fd,0,SEEKCUR);

这种方法也可以用来确定所涉及的文件是否可以设置偏移量。如果文件描述符引用的是一个管道、FIFO或网络套接字,则lseek返回-1,并将errno设置为ESPIPE。

通常,文件的当前偏移量是一个非负整数,但是,某些设备也可能允许负的偏移量。但对于普通文件,则其偏移量必须是非负值 。因为偏移量可能是负值,所以在比较lseek的返回值时
应当谨慎,不要测试它是否小于0,而是要测试它是否等于-1。

lseek仅将当前文件的偏移量记录在内核中,它并不引起任何I/O操作。然后该偏移量用于下一个读/写操作。

文件偏移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写操作将加长该文件,并在文件中构成一个空洞。位于文件中但没有写过的字节都被 ****读为0****

文件中的空洞并不要求在磁盘上占用存储区。具体处理方式与文件系统的实现有关,当定位到超出文件尾端之后写时,对于新写的数据需要分配磁盘快,
但是对于原文件尾端和新开始写位置之间的部分则不需要分配磁盘块。

read函数

#include
ssizet read(int filedes, void *buf, sizet nbytes);

有多种情况可使实际读到的字节数少于要求读的字节数:
1. 读普通文件时,在读到的要求字节数之前已达到了文件尾端。
2. 从终端设备读时,通常一次最多读一行。
3. 当从网络读时,网络中的缓冲机制可能造成返回值小于所要求读的字节数。
4. 当从管道或从FIFO读时,如若管道包含的字节少于所需要的字节数,那么read将只返回实际可用的字节数。
5. 当从某些面向记录的设备(如磁带)读时,一次最多返回一个记录。
6. 当某一信号造成中断,而已经读了部分数据量时。

write函数

#include
ssizet write(int filedes, const void *buf, sizet nbytes);
返回值通常和nbytes相同,不相同则出错。
出错的原因可能是:
1. 磁盘满
2. 超过了一个给定进程的文件长度限制

I/O效率

BUFFSIZE的选取,和块大小sbblksize一致,最高效。
操作系统检测到顺序读时,会采取某种预读技术(read ahead)

文件共享

内核使用三种数据结构表示打开的文件:
1. 每个进程在进程表中都有一个记录项,记录项中包含有一张打开文件描述符表,每个描述符占一项。与每个描述符相关联的是:
1. 文件描述符标志(closeonexit)。
2. 指向一个文件表项的指针。
2. 内核为所有打开文件维持一张文件表。每个文件表项包含:
1. 文件状态标志
2. 当前文件偏移量
3. 指向该文件v节点表项的指针
3. 每个打开文件都有一个v节点结构。v节点包含了文件类型和对此文件进行各种操作的函数的指针。对于大多数文件,v节点还包含了该文件的i节点。
这些信息是在打开文件时从磁盘上读入内存的,所以所有关于文件的信息都是快速可供使用的。

如果两个独立进程各自打开了同一个文件。打开该文件的每个进程都得到一个文件表项,但对一个给定的文件只有一个v节点表项。
每个进程都有自己的文件表项的一个理由是:这种安排使每个进程都有它自己的对该文件的当前偏移量。

可能有多个文件描述符项指向同一个文件表项。譬如dup,fork。

文件描述符标志和文件状态标志在作用域方面的区别,前者只用于一个进程的一个文件描述符,而后者则适用于指向该文件表项的任何进程中的所有描述符。

当多个进程写同一个文件时,可能产生预期不到的效果。解决办法,参考下面的原子操作的概念。

原子操作

添写至一个文件

任何一个需要多个函数调用的操作都不可能是原子操作,因为在两个函数调用之间,内核可能会临时挂起该进程。
UNIX提供了OAPPEND标志,内核在写之前会将偏移量设置为文件尾端处,而不用调用lseek。

pread和pwrite函数

把lseek和I/O读写捆绑成了原子操作。由内核提供。

#include
ssizet pread(int filedes, void *buf, sizet nbytes, offt offset);
ssizet pwrite(int filedes, const void *buf, sizet nbytes, offt offset);

创建一个文件

open提供OCREATE和OEXCL选项。当同时指定这两个选项,而该文件又已经存在时,open将失败。
一般而言,原子操作指的是由多步组成的操作。如果该操作原子地执行,则要么执行完所有步骤,要么一步也不执行,不可能只执行所有步骤中的一个子集。
* 内核是怎么实现的?当执行其中一个时,发生信号中断呢?或者两个语句中,第一个语句执行时间过长导致CPU时间片用完呢?*

dup和dup2函数

这两个函数都可用来复制一个现存的文件描述符,返回的新文件描述符与参数fieldes共享同一个文件表项。

#include
int dup(int fieldes);
int dup2(int fieldes, int fieldes2);

由dup返回的新文件描述符一定是当前可用文件描述符中的最小数值。用dup2则可以用fieldes2参数指定新描述符的数值。如果filedes2已经打开,则先将其关闭。如若filedes等于filedes等于
filedes2,则dup2返回filedes2,而不关闭它。

复制一个描述符的另一种方法是fcntl函数。
调用
dup(filedes);
等效于
fcntl(filedes, FDUPFD, 0)

而调用
dup2(filedes, filedes2);
等效于
close(filedes);
fcntl(filedes, FDUPFD, filedes2);
第二个有区别,主要在于一个是原子操作,另一个不是。

sync、fsync和fdatasync函数

传统的UNIX实现在内核中设有缓冲区高速缓存或页面高速缓存,大多数磁盘I/O都通过缓冲进行。写->缓冲区->输出队列->队首时,实际的I/O操作。这种方式称为延迟写。
内核已经提供了缓冲机制,不过这个缓冲机制是为了减少频繁的I/O操作。
之后说的标准I/O函数库的缓冲是指对系统调用的数据做了缓冲,这个缓冲的目的是为了减少系统调用次数。系统调用由于涉及到内核态和用户态的切换,是有一定的开销的。

延迟写减少了磁盘读写次数,但是却降低了文件内容的更新速度。当系统发生故障时,这种延迟可能造成文件更新内容的丢失。
为了保证磁盘上实际文件系统与缓冲区高速缓存中内容的一致性,UNIX系统提供了sync、fsync和fdatasync三个函数。

#include
int fsync(int filedes);
int fdatasync(int filedes);

void sync(void);

sync函数只是将所有修改过的块缓冲区排入写队列,然后就返回,它并不等待实际写磁盘操作结束。
通过称为update的系统守护进程会周期性地(一般每隔30秒)调用sync函数。这就保证了定期冲写内核的块缓冲区。

fsync会等待磁盘操作结束,适合数据库应用。

fcntl函数

  • Note taken on [2016-04-05 Tue 06:56]

#include
int fcntl(int filedes, int cmd, … * int arg *);

fcntl函数有5种功能:
1. 复制一个现有的描述符(cmd = FDUPFD)
2. 获得/设置文件描述符标记(cmd = FGETFD或FSETFD)
3. 获得/设置文件状态标志(cmd = FGETFL或FSETFL)
4. 获得/设置异步I/O所有权(cmd = FGETOWN或FSETOWN)
5. 获得/设置记录锁(cmd = FGETLK、FSETLK或FSETLW)

由磁盘驱动器将队列数据写到磁盘上。
在UNIX系统中,通常write只是将数据排入队列,而实际的写磁盘操作则可能在以后的某个时刻进行。
程序运行时,设置OSYNC标志会增加时钟时间(等待磁盘IO操作结束).

ioctl函数

ioctl函数是I/O操作的杂物箱。终端I/O是ioctl的最大使用方面。

#include * System V *
\#include <sys/ioctl.h> * BSD and linux *
\#include * XSI STREAMS *

int ioctl(int filedes, int request, … );

每个设备驱动程序都可以定义它自己专用的一组ioctl命令。系统则为不同种类的设备提供通用的ioctl命令。

/dev/fd

打开文件/dev/fd/n 等效于复制描述符n。

/dev/fd文件主要由shell使用,它允许使用路径名作为调用参数的程序,能用处理其它路径名的相同方式处理标准输入和输出。

filter file2 | cat file1 – file3 | lpr
在命令行中用”-” 作为一个参数,特指标准输入或标准输出,这已由很多程序采用。但是这会带来一些问题,例如若用”-“指定第一个文件名,
那么它看起来就像指定了命令行中的一个选项,/dev/fd则提高了文件名参数的一致性,也更加清晰。

第一章 UNIX基础知识

操作系统有两个含义:
1. 仅指内核,它控制计算机硬件资源,提供程序运行环境。
2. 广义上,包括内核和一些其它软件,如系统实用程序、应用软件、shell以及公用函数库等。

文件与目录

UNIX文件系统的大多数实现并不在目录项中存放属性。有inode就够。

程序的正确性是由硬件->内核->系统调用->标准库函数->第三方库->程序员 逐步保证的。

程序与进程

程序是存放在磁盘上,处于某个目录中的一个可执行文件。使用6个exec函数中的一个由内核将程序读入存储器,并使其执行。

有三个用于进程控制的主要函数:fork、exec和waitpid。

线程和线程ID

通常,一个进程只有一个控制线程,同一时刻只执行一组机器指令。
在一个进程内的所有线程共享同一地址空间、文件描述符、栈以及与进程相关的属性。因为它们能访问同一存储区,所以各线程在访问共享数据时需要采取同步措施以避免不一致性。

出错处理

当UNIX函数出错时,一般返回一个负值,而且整型变量errno通常被设置为含有附加信息的一个值。
返回一个指向对象指针的大多数函数,在出错时,将返回一个null指针。

POSIX和ISO C将errno定义为这样一个符号,它扩展成为一个可修改的整型左值(lvalue)。这可以是包含出错编号的一个函数,或者是一个返回出错编号指针的函数。
extern int * _errnolocation(void);
#define errno (*_errnolocation())
在支持多线程的环境中,多个线程共享进程地址空间,每个线程都有属于它自己的局部errno以避免一个线程干扰另一个线程。
对于errno应当知道两条规则:
1. 如果没有出错,则其值不会被一个例程清除。因此,仅当函数的返回值指明出错时,才检验其值。
2. 任一函数都不会将errno值设为0,在中定义的所有常量都不为0。

用户标识

对于权限,使用数值用户ID和数值值ID是历史上形成的。1是数字比字符串的存储空间小,每个文件都会存放用户ID和组ID;2是查验权限期间,比较整数更快。

信号

信号是通知进程已发生某种情况的一种技术。

进程处理信息有三种选择:
1. 忽略信号。
2. 按系统默认方式处理。
3. 提供一个信号捕捉函数,自定义处理。

在键盘上产生信号的办法,中断键盘(Ctrl+C)和退出键(Ctrl+)。

时间值

长期以来,UNIX系统一直使用两种不同的时间值。
1. 日历时间。自1970年1月1日00:00:00以来UTC所经过的秒数。
2. 进程时间。也被称为CPU时间,用来度量进程使用的中央处理器资源。
1. 时钟时间
2. 用户CPU时间
3. 系统CPU时间。