unix环境高级编程 第三版 第一章
1:UNIX体系结构诚层为内核,内核外系统调用,而shell和公用库函数则又是建立在系统调用上,最后系统程序既可以使用
系统调用,又可以使用公共库函数,shell的独特之处在于为其他应用程序提供了一个接口。
2:(1)登录口令文件是/etc/passwd
(2):口令文件由登录项组成,登录项格式为 登录明:加密口令:数字用户ID:数字组ID:注释字段:起始目录:shell程序
(3)UNIX采用目录和文件的层次结构,所有东西的起点称为根目录,即 /.
(4)目录是包含目录项的文件,其中 “/” 和 "空字符" 不能出现在文件名中,很显然,/和空字符分别用于分离和终结文件名。而且每个目录项都会自动创建“.”和".."两个文件,分别用于指向当前目录和父目录。
3:
(1):内核用于表示标识特定进程正在访问的文件称作文件描述符,它通常是一个小的非负整数。进程启动时,shell自动为其打开STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO三个文件描述符。
(2):open,close,write,read,lseek,这几个函数都提供了不带缓冲的I/O,这些函数都使用了文件描述符。
(3):标准I/O为那些不带缓冲的I/O提供了带缓冲的接口。
4:程序和进程
(1):程序是一个存储在磁盘上某个目录的可执行文件。
(2):程序的执行实例被称作进程,UNIX确保每个进程都有唯一的一个数字标识符,称为进程ID.exec族,waitpid,fork三个函数用于主要的进程控制。
(3)线程:通常,线程就是轻量级进程,一个进程内所有线程共享同一地址空间,文件描述符,栈,以及进程相关的属性。线程ID:用于进程内唯一标识某线程的非负整数。
5:出错文件
(1)当UNIX函数出错时,通常会返回一个负值,而且整型变量error通常被设定为具有特定信息的值。
(2)error的两条规则,一是如果没有出错,其值不会被例程清除。第二是任何函数都不会将error值设置为0,而且在<error.h>中所有的常量都不为0。
出错函数如下:
1 #include<string.h>
char *strerror(int errnum);
2 #include<stdio.h>
void perror(const char *msg);
6:信号
(1)信号用于通知进程发生了某种情况,进程有以下三种处理信号的方式。
1 忽略信号
2 按系统默认方式处理
3 提供一个函数,信号发生时调用该函数
3.7 read函数
- /*
- *函数功能:读取已打开文件的数据;
- *返回值:若成功返回读取的字节数,若到文件尾则返回0,若出错则返回-1;
- */
- /*
- *函数原型:
- */
- #include <unistd.h>
- ssize_t read(int filedes, void *buf, size_tnbyte);
- /*
- *参数解释:
- *filedes是指所要读取文件的文件描述符;
- *buf存储所读取数据;
- *nbyte表示最多读取的字节数;
- */
3.8 write函数
- /*
- *函数功能:向已打开文件写入数据;
- *返回值:若成功返回已写的字节数,若出错则返回-1;
- */
- /*
- *函数原型:
- */
- #include <unistd.h>
- ssize_t write(int filedes, const void *buf,size_t nbyte);
- /*
- *参数解释:
- *filedes是指所要写入数据文件的文件描述符;
- *buf存储所要存储的数据;
- *nbyte表示最多写入的字节数;
- */
3.10 文件共享
UNIX支持不同进程共享打开的文件。内核使用三种数据结构表示打开的文件:
进程在进程表中都有一个记录项,记录项中包含一张打开文件的描述符表。每个描述符占一项:描述符标志fd;指向一个文件表项的指针。
内核维持一张所有打开文件的文件表,每个文件表项包含文件状态标志、当前文件偏移量、指向文件v节点表项的指针。
每个打开文件有一个v节点表,每个v节点包含文件类型、操作函数指针和文件的i节点等。
Linux将v节点和i节点实现为独立于文件系统的i节点和依赖文件系统的i节点。
不同进程共享文件时,每个进程都有一个该文件的文件表项,指向同一个v节点表。多个文件描述符也可能指向同一个文件表项,如使用 dup 函数和 fork 后的父子进程。以下是不同进程共享同一个文件的示意图:
3.11 原子操作
原子操作指由多步组成的操作,执行时要么全部执行,要么一步也不执行。
多个进程共享同一个文件,可能造成进程对文件的连续的操作被打乱,这就需要使操作成为原子操作。如 O_APPEND 将到尾端和写入数据组成原子操作,还有 O_CREAT 和 O_EXCL 将检查文件是否存在和创建文件组成原子操作。例如:pread 和 pwrite 将偏移量和读/写组成原子操作。
pread 和 pwrite 函数
- #include <unistd.h>
- /* 函数功能:定位并读取数据
- * 返回值:成功返回读到的字节数,已到文件尾则返回0,出错返回-1 ;
- */
- ssize_t pread(int fd, void *buf, size_tcount, off_t offset);
- /* 函数功能:定位并写入数据
- * 返回值:成功返回写入的字节数,出错返回-1;
- */
- ssize_t pwrite(int fd, const void *buf,size_t count, off_t offset);
3.12 dup函数
- /*
- *函数功能:复制已有的文件描述符;
- *返回值:若成功返回当前可用的文件描述符最小值,若出错则返回-1;
- */
- /*
- *函数原型:
- */
- #include <unistd.h>
- int dup(int filedes);
- /*
- *参数解释:
- *filedes是指当前文件的文件描述符;
- */
- dup2函数
- /*
- *函数功能:复制已有的文件描述符;
- *返回值:若成功返回参数filedes2指定的文件描述符,如果filees2已经打开,则现将其*关闭,如果filedes1等于filedes2,则返回filedes2,不关闭;若出错则返回-1;
- */
- /*
- *函数原型:
- */
- #include <unistd.h>
- int dup2(int filedes1,intfiledes2);
- /*
- *参数解释:
- *filedes是指当前文件的文件描述符;
- */
3.13 刷新缓冲区函数
- unix系统在写数据时是采用文件延迟写,但是我们可以自己刷新缓冲区,将数据写入磁盘。以下是刷新缓冲区,将数据写入磁盘的函数sync,fsync,fdatasync;
- #include <unistd.h>
- /* 将所有修改过的块缓冲区排入写队列,然后返回,不等待写磁盘结束 */
- void sync(void);
- /* 对指定文件刷新块缓冲区,等待写磁盘结束,更新文件属性
- * 返回值:成功返回0,出错返回-1 */
- int fsync(int fd);
- /* 对指定文件刷新块缓冲区,等待写磁盘结束,不更新文件属性
- * 返回值 成功返回0,出错返回-1 */
- int fdatasync(int fd);
3.14 fcntl函数
- /*
- *函数功能:可以改变已打开文件的性质。
- *函数原型:
- */
- #include <unistd.h>
- #include <fcntl.h>
- /*
- * 返回值:成功依赖于cmd,出错返回-1
- */
- int fcntl(int filedes, int cmd, ... /*intarg */ );
- /*
- *参数解释:
- *filedes表示文件描述符;
- *cmd参数,根据 cmd 值的不同,有以下5种功能:
- *
- *(1)F_DUPFD ,复制一个现有的描述符。新描述符为大于等于 arg 的最小可用值。
- *(2)F_GETFD 、 F_SETFD ,获取/设置文件描述符标记。文件描述符标志只有 FD_CLOEXEC ,但一般使用0或1,分别代表 exec 时不关闭或关闭,0为默认值。
- *(3)F_GETFL 、 F_SETFL ,获取/设置文件状态标志。可获取的文件状态标志见 open 函数的 flags 可取值,可设置的文件状态标志不包括访问模式位和创建模式位。
- *(4)F_GETOWN 、 F_SETOWN ,获取/设置异步I/O所有权,即接收 SIGIO和 SIGURG *信号的进程ID或进程组ID, arg 为正为进程ID, arg 为负为等于其绝对值的进程组ID。
- *(5)F_GETLK 、 F_SETLK 、 F_SETLKW ,获取/设置记录锁。
- *agr是指定的整数值;
- */