最近导师给的活有点坎坷,周末继续来学学apue。。。
废话不多说。
第一章答案看到一个写的较详细地就转载了,第二章跳过。
I/O 5个基本函数:open,read,write,lseek和close这章大部分被称为unbuffered I/O 与第五章对照。涉及在多个进程间共享资源,原子操作的概念就变得很重要。
原子(atomic operation)操作:由多步组成的一个操作。如果该操作原子地执行,则要么执行完所有步骤,要么一步也不执行,不可能只执行所有步骤的一个子集。比如:创建和测试就组成一个原子操作。O_CREAT 和 O_EXCL如果在open中同时使用就会报错。
文件描述符:
内核都用文件描述符引用文件。open或者creat返回的文件描述符标识该文件,将其作为参数传递给read或者write。幻数0.1.2分别对应--STDIN_FILENO. STDOUT_FILENO. STDERR_FILENOpath是要打开或者创建的名字,oflag是多个选项。#include <fcntl.h> int open(const char *path, int oflag, ... /* mode_t mode */ ); int openat(int fd, const char *path, int oflag, ... /* mode_t mode */ );
返回的文件描述符一定是最小的未用的文件描述符。而下面这个opennat就是为了能够在path是相对路径名时,fd作为相对路径名在文件系统的开始地址来使用(fd通过打开相对路径名所在的目录获取的。)这个fd还有一个用途,当它是AT_FDCWD时,路径名从当前目录获取。这样做的目的 1.可以使用相对路径名打开目录中的文件。2.避免TOCTTOU错误,这个是因为两个基于文件的函数调用,他们两个没有组成原子操作,那么就容易出错,甚至有的会通过第一次调用降低文件权限,好制造安全漏洞。这就是信息安全地内容了。。。
等效于 open( path , O_WRONLY | O_CREAT | O_TRUNC, mode );#include <fcntl.h> int creat(const char *path, mode_t mode); Returns: file descriptor opened for write-only if OK, −1 on error
#include <unistd.h> int close(int fd); Returns: 0 if OK, −1 on error
返回新的偏移量,出错返回-1#include <unistd.h> off_t lseek(int fd, off_t offset, int whence);//Returns: new file offset if OK, −1 on error
whence是SEEK_SET/SEEK_CER/SEEK_END分别对应0.1.2分别对应(开始处、当前值、文件长度)加offsetoffset可正可负
还可以调用off_t currpos;
得到当前偏移量哦currpos=lseek(fd,0,SEEK_CUR);
当前偏移量可能为负,所以最好只测试它是否为-1.只有-1代表为错,不要测试是否小于0。
空洞不占内存。一大堆就说了这一个事情。
READ、WRTIE
#include <unistd.h> ssize_t read(int fd, void *buf, size_t nbytes); Returns: number of bytes read, 0 if end of file, −1 on error
#include <unistd.h> ssize_t write(int fd, const void *buf, size_t nbytes); Returns: number of bytes written if OK, −1 on error
这里的const是因为,避免在write过程中有一些坏人(其他进程或者进程中其他线程)企图改变写缓冲区的内容。
I/O效率
就说4096是比较合适的。以为内这个文件系统磁盘块长度为4096.
3句新知识:
1.对UNIX系统内核而言,文本文件和二进制代码文件并无区别。
2.预读技术:系统检测到你正在顺序读取,就试图读入比当前应用所要求的更多的数据,并且假想应用很快聚会读这些数据。
3.第一次运行使得文件进入高速缓存,后续直接从高速缓存读,无须读写磁盘。但是作者考虑到啦~~~反正我是没想到。。不好意思说自己是学过计算机硬件的。
文件共享
感觉最重要的一部分了。
dup和dup2
#include <unistd.h> int dup(int fd); int dup2(int fd, int fd2); Both return: new file descriptor if OK, −1 on error
sync,fsync, andfdatasync Functions
正常系统都延迟写,但是当缓冲区需要空时,就把所有延迟写的数据写进去磁盘。就调用这3个
#include <unistd.h> int fsync(int fd);//
对fd打开的文件起作用,废话。。等待写磁盘结束,并且等待文件属性更新。这样适用于多人读写数据库 int fdatasync(int fd);//不等待文件属性更新 Returns: 0 if OK, −1 on error void sync(void);//把延迟写的数据排入写队列就走了,很不负责任。。程序员可不能这样哦
函数fcntl
f c n t l 函数有五种功能:#include <fcntl.h> int fcntl(int fd, int cmd, ... /* int arg */ ); Returns: depends on cmd if OK (see following), −1 on error
• 复制一个现存的描述符( c m d = F _ D U P F D )。
• 获得 / 设置文件描述符标记( c m d = F _ G E TF D 或 F _ S E T F D )。
• 获得 / 设置文件状态标志( c m d = F _ G E T F L 或 F _ S E T F L )。
• 获得 / 设置异步 I / O 有权( c m d = F _ G E TO W N 或 F _ S E TO W N )。
• 获得 / 设置记录锁( c m d = F _ G E T L K , F _ S E T L K 或 F _ S E T L K W )。
剩下的感觉就是很少用的,先不写了,以后看到了它的作用再补吧。先去取快递了。。。