Unix体系结构: 很多书上一开始往往要讲到操作系统结构,这本书当然也不例外,其实这个结构很抽象。什么内核、系统调用、库函数以及shell等等,给人总是很模糊的,我不喜欢这些,对 于开源项目,最好的解释就是代码伺候。 文件和目录: Unix一开始就设定好了一种目录结构,其实就是一棵树,有很明显的树根(和windows相比),而且很明确的树的操作。树根叫“/”.而且为了进程的概念,引入当前目录,上 级目录等概念。其实最早的操作系统应该是Unix。当时写这个操作系统美国佬,还特地发明了一种程序语言,就是C语言。 输入输出: Unix上面有三个特殊文件。输入设备、输出设备和出错设备。这个文件个人认为都是系统为了扩展性而设计的,三个文件可以是一种设备,也可以是单纯的文件。他们文件描 述符分别是0,1,2.这是操作系统定的,谁能连接上这三个描述符,谁就是这个三个设备。通常我们用shell打开的程序时,shell把这个三个文件描述符都同时链接到当前终端控制 台。 说起输入输出,又想起缓冲等概念。一般为了程序,也是操作系统的吞吐量和速度,都喜欢搞一个缓冲区,当然这确实也有效。例如我们最开始学C语言接触的printf输出函数 。这个函数是将我们的输出先放到一个缓冲区里,然后当缓冲区满了,或者程序给出特定标识来刷新缓冲区时,才把我们信息输出到输出设备上。printf是行缓冲,也就是一行满 的时候或者遇到了换行符时候,系统才把我们信息输出。 当然如何知道printf就是缓冲区输出,还得看它的源代码。 程序和进程: 有时经常听到别人讨论,也有人问我或者想考我的:进程是什么东东?我通常很简单的回答,进程就是程序,运行中的程序。说完第一句的时候,问的人不免有点自喜,以为 一下就把我给考住了,等我过一会儿再说出第二句的时候,问的人就有点失望了,哈哈。其实我理解也很简单,因为程序和进程,两者都有一个“程”字,所以有它共同点,不同 的是“进”和“序”,很明显,进表示前进、进行,是活的有生命的。序表示序列,有序的东东,是死的。提到进程,给人的第一概念就是fork()函数。其实这个fork和微软的 CreateProcess有很大的不同,他仅仅是CreateProcess前部分,后部分是execve()等系列四个函数。 对于刚入门的Unix的系列的程序员,大概对这个fork很难理解. if (pid = fork()) 中的pid是什么,为什么同一个函数会返回两次呢?这也不怪,对于写惯了程序的人,肯定 有点难以接受,我们平常接触的程序都只有一个出口,就是return,难道他return 完后,再return一次,这样就出现了矛盾了。拔开乌去见丽日,返回两次是在不同的进程内,在 同一个进程内也只能返回一次,也就是return.因为进程是互相隔离的,所以对于两个进程都不知道对方正在做什么,除非他问对方。这里又出现另一个问题,为什么两个进程在同 一个函数内呢?按我们理解是,代码段一般不能共享的,其实代码段可以共享,也就是两个进程都同时拥有这段代码,所以同一函数可以出现两个进程。 这里还要提一点的就是,在返回值上Unix和Windows风格不一样,Unix习惯0表示正确,而Windows习惯大于0表示正确,相反则错误。前面我已经提到Unix操作系统最开始设计 的时候就有一人叫出错设备的文件,所以一旦出错,首先代码段出返回一个error整形变量,其次系统会将出错信息输出到出错设备中。 另外对于出错恢复,Windows一般在例程开始的时候提供一个异常帧,以保证错误可以恢复。Unix系统对于出错恢复并没有做有效的管理,最多在资源占用时候,会延时再试, 出错管理还得程序员自己做。
用户和组: 对于这个概念,一直很乱七八糟的。什么超级用户、根用户、当前用户、域用户、组用户、组、附加组等等,概念太多,很多书上自认为说得很清楚,但很少我看得出他们说 得很清楚。其实我认为,这些所有概念无非就是这个操作系统是谁的?当前进程是谁?这个用户是谁家里的?分辨出这些就可以了,非要讲些什么支配权、登录名、口令等等乱七 八糟东东,无奈。
信号: 信号是进程间通信(IPC)一种技术,可以是内核进程,也可以是用户进程。也就是可以运行在内核模式也可用户模式。信号是系统大力支持一种通信方式,而且特定为信号设 计了一个数据结构,并且在内核中(比如中断)深入支持。你可以添加自己的信号,也可以修改系统信号,当然你得按系统给你设定的方式做些事情。 我认为信号通信最大的好处就是简单,发送者只需发送一个信号代码即可。没有消息那么多信息,没有socket那么复杂,没有管道那么多同步。 时间值: 长期以来,Unix一直使用两种不同的时间值: 1,日历时间。该值是从1970年1月1日00:00:00以来所经过的秒数。它时系统硬件Bios专门记录的。(time_t) 2,进程时间。它是系统时钟中断产生的系统滴答所记录的数值。(clock_t) 其实二者主要是字宽不同,前者是long long.后者是long. 二,标准化及实现 由于Unix是开源项目,所以由此产生很多版本,比如最早的AT&T实验室的SVR4,加州大学伯克利分校的FreeBSD,当今流行开源系统Linux,Apple公司的Max OS X,Sun公司的 Solaris。 系统之多,就会引起分歧。各行各的,就会导致程序很乱,必须一套大家共遵循的标准才行。 首先是C语言,因为大多操作系统都是用C语言开发的。 ISO C:即国际标准化组织制定的C标准规范。1999年ISO C标准被更新为ISO/IEC 9899:1999。 其次就是系统调用规范,几乎每个操作系统都提供一套自己的系统调用,因为它是内核模式运行的,不同于用户模式,是程序开发的根本,所以也必须标准化。 IEEE POSIX:POSIX是一系列由IEEE制定的标准,也是可移值操作系统的接口。现行成熟标准是POSIX.1,由Austin Group开发工作组维护。 Single UNIX Specification:他也POSIX标准,只是他是POSIX.1的一个超集,扩展了POSIX.1所提供的功能。相应的接口也被改称为X/Open系统接口,由Open Group开发维护 。2002年被ISO批准为国际标准ISO/IEC 9945:2002。 每个操作系统为用户提供开发接口,也都定义了一套系统数据类型。以下是/usr/include/sys/types.h文件内容,提供了系统基本数据类型定义。 /* * POSIX Standard: 2.6 Primitive System Data Types */ #ifndef _SYS_TYPES_H #define _SYS_TYPES_H 1 #include __BEGIN_DECLS #include #ifdef __USE_BSD # ifndef __u_char_defined typedef __u_char u_char; typedef __u_short u_short; typedef __u_int u_int; typedef __u_long u_long; typedef __quad_t quad_t; typedef __u_quad_t u_quad_t; typedef __fsid_t fsid_t; # define __u_char_defined # endif #endif typedef __loff_t loff_t; #ifndef __ino_t_defined # ifndef __USE_FILE_OFFSET64 typedef __ino_t ino_t; # else typedef __ino64_t ino_t; # endif # define __ino_t_defined #endif #if defined __USE_LARGEFILE64 && !defined __ino64_t_defined typedef __ino64_t ino64_t; # define __ino64_t_defined #endif #ifndef __dev_t_defined typedef __dev_t dev_t; # define __dev_t_defined #endif #ifndef __gid_t_defined typedef __gid_t gid_t; # define __gid_t_defined #endif #ifndef __mode_t_defined typedef __mode_t mode_t; # define __mode_t_defined #endif #ifndef __nlink_t_defined typedef __nlink_t nlink_t; # define __nlink_t_defined #endif #ifndef __uid_t_defined typedef __uid_t uid_t; # define __uid_t_defined #endif #ifndef __off_t_defined # ifndef __USE_FILE_OFFSET64 typedef __off_t off_t; # else typedef __off64_t off_t; # endif # define __off_t_defined #endif #if defined __USE_LARGEFILE64 && !defined __off64_t_defined typedef __off64_t off64_t; # define __off64_t_defined #endif #ifndef __pid_t_defined typedef __pid_t pid_t; # define __pid_t_defined #endif #if (defined __USE_SVID || defined __USE_XOPEN) && !defined __id_t_defined typedef __id_t id_t; # define __id_t_defined #endif #ifndef __ssize_t_defined typedef __ssize_t ssize_t; # define __ssize_t_defined #endif #ifdef __USE_BSD # ifndef __daddr_t_defined typedef __daddr_t daddr_t; typedef __caddr_t caddr_t; # define __daddr_t_defined # endif #endif #if (defined __USE_SVID || defined __USE_XOPEN) && !defined __key_t_defined typedef __key_t key_t; # define __key_t_defined #endif #ifdef __USE_XOPEN # define __need_clock_t #endif #define __need_time_t #define __need_timer_t #define __need_clockid_t #include #ifdef __USE_XOPEN # ifndef __useconds_t_defined typedef __useconds_t useconds_t; # define __useconds_t_defined # endif # ifndef __suseconds_t_defined typedef __suseconds_t suseconds_t; # define __suseconds_t_defined # endif #endif #define __need_size_t #include #ifdef __USE_MISC /* Old compatibility names for C types. */ typedef unsigned long int ulong; typedef unsigned short int ushort; typedef unsigned int uint; #endif /* These size-specific names are used by some of the inet code. */ #if !__GNUC_PREREQ (2, 7) /* These types are defined by the ISO C99 header . */ # ifndef __int8_t_defined # define __int8_t_defined typedef char int8_t; typedef short int int16_t; typedef int int32_t; # if __WORDSIZE == 64 typedef long int int64_t; # elif __GLIBC_HAVE_LONG_LONG __extension__ typedef long long int int64_t; # endif # endif /* But these were defined by ISO C without the first `_'. */ typedef unsigned char u_int8_t; typedef unsigned short int u_int16_t; typedef unsigned int u_int32_t; # if __WORDSIZE == 64 typedef unsigned long int u_int64_t; # elif __GLIBC_HAVE_LONG_LONG __extension__ typedef unsigned long long int u_int64_t; # endif typedef int register_t; #else /* For GCC 2.7 and later, we can use specific type-size attributes. */ # define __intN_t(N, MODE) \ typedef int int##N##_t __attribute__ ((__mode__ (MODE))) # define __u_intN_t(N, MODE) \ typedef unsigned int u_int##N##_t __attribute__ ((__mode__ (MODE))) # ifndef __int8_t_defined # define __int8_t_defined __intN_t (8, __QI__); __intN_t (16, __HI__); __intN_t (32, __SI__); __intN_t (64, __DI__); # endif __u_intN_t (8, __QI__); __u_intN_t (16, __HI__); __u_intN_t (32, __SI__); __u_intN_t (64, __DI__); typedef int register_t __attribute__ ((__mode__ (__word__)));
/* Some code from BIND tests this macro to see if the types above are defined. */ #endif #define __BIT_TYPES_DEFINED__ 1
#ifdef __USE_BSD /* In BSD is expected to define BYTE_ORDER. */ # include /* It also defines `fd_set' and the FD_* macros for `select'. */ # include /* BSD defines these symbols, so we follow. */ # include #endif /* Use BSD. */
#if defined __USE_UNIX98 && !defined __blksize_t_defined typedef __blksize_t blksize_t; # define __blksize_t_defined #endif /* Types from the Large File Support interface. */ #ifndef __USE_FILE_OFFSET64 # ifndef __blkcnt_t_defined typedef __blkcnt_t blkcnt_t; /* Type to count number of disk blocks. */ # define __blkcnt_t_defined # endif # ifndef __fsblkcnt_t_defined typedef __fsblkcnt_t fsblkcnt_t; /* Type to count file system blocks. */ # define __fsblkcnt_t_defined # endif # ifndef __fsfilcnt_t_defined typedef __fsfilcnt_t fsfilcnt_t; /* Type to count file system inodes. */ # define __fsfilcnt_t_defined # endif #else # ifndef __blkcnt_t_defined typedef __blkcnt64_t blkcnt_t; /* Type to count number of disk blocks. */ # define __blkcnt_t_defined # endif # ifndef __fsblkcnt_t_defined typedef __fsblkcnt64_t fsblkcnt_t; /* Type to count file system blocks. */ # define __fsblkcnt_t_defined # endif # ifndef __fsfilcnt_t_defined typedef __fsfilcnt64_t fsfilcnt_t; /* Type to count file system inodes. */ # define __fsfilcnt_t_defined # endif #endif #ifdef __USE_LARGEFILE64 typedef __blkcnt64_t blkcnt64_t; /* Type to count number of disk blocks. */ typedef __fsblkcnt64_t fsblkcnt64_t; /* Type to count file system blocks. */ typedef __fsfilcnt64_t fsfilcnt64_t; /* Type to count file system inodes. */ #endif
/* Now add the thread types. */ #if defined __USE_POSIX199506 || defined __USE_UNIX98 # include #endif __END_DECLS #endif /* sys/types.h */ |