最近在看UNIX环境高级编程和UNIX网络编程 卷一。每翻开新的一页,就会学到很多,读起来非常的刺激。
在看这两本书的时候,我有一点感悟。 1. 仅仅实现功能,不是一个完整的系统,功能只是系统中的一个组成部分。一个完整的系统必须考虑到所有可能会出现的情况,一个具有较高鲁棒性的系统才配称作系统。 2. 仅仅知道一个函数能完成什么功能是远远不够的,必须知道为了完成这个功能,函数做了什么。 3. 网络编程中对TCP状态的把握很重要。
下面是一些具体的笔记。
文件IO是针对文件描述符的。文件IO是不带缓存的,也就是指每个read和write都调用内核中的一个系统调用。很显然不带缓存将会频繁的调用内核中的系统调用,造成效率比较低。而标准IO库提供缓存机制,以减少使用read和write调用内核系统调用的数量。
对于标准IO库来说,它们的操作是围绕着流进行的。文件IO中使用open函数打开一个文件,在标准IO库中则使用fopen函数打开一个文件。使用它打开一个文件的同时,一个流就和一个文件相结合了。fopen函数返回一个指向FILE结构体的指针。这个结构体包括IO库为管理该流所需的所有信息,比如实际IO的文件描述符,指向流缓存的指针,缓存的长度,当前缓存中的字符数,出错标志等。对于每一个进程来说,系统都为他们预定义了三个流,分别是标准输入,标准输出,标准出错,可通过预定义文件指针stdin,stdout,stderr使用它们。
标准IO库中的流是提供缓存的,而且系统自动提供缓存管理。有三种类型的缓存:
以下三个函数可用于一次读一个字符:
int getc(FILE *fp);
int fgetc(FILE *fp);
int getchar(void);
前两个函数的区别是getc是被实现为宏的,而fgets不是宏,也就是说,调用fgets所需的时间一般会长于调用getc。而函数getchar则相当于getc(stdin),即从标准输入读入一个字符。
下面两个函数提供每次输入一行的功能:
char *fgets(char *buf,int n,FILE *fp);
char *gets(char *buf);
gets从标准输入读,而fgets则从指定的流读。gets是一个不被推荐使用的函数,因为由于它不能指定缓存的长度,这样很可能会造成缓存越界。推荐总是使用fgets和fputs,即从指定流输入或输出一行。
从书中给的数据来看,使用流缓存的程序比不使用缓存的程序要快得多,虽然两者的函数调用次数相同,但是使用流缓存的程序引起的系统调用次数远远低于函数调用次数,而系统调用与普通的函数调用相比是很花费时间的。