输入是从I/O设备拷贝数据到主存,输出是从主存拷贝数据到I/O设备。
一个文件就是一个字节序列。
所有的I/O设备,如网络、磁盘、和终端,都被模型化为文件,而所有的输入和输出都被当做想对应的文件的读写来执行。
1、ISO C的I/O操作是带缓存的,而POSIX标准的I/O操作是指真正发生了系统调用,是不带缓存的
2、文件描述
(1)是对一个已打开文件的引用,是由shell定义,Unix沿用,与内核无关。
(2)文件描述符是一个非负整数,0、1、2已被标准输入、标准输出和标准错误关联
(3)文件描述符是在某一个进程/线程中对一个文件的描述,同一个文件在不同进程/线程中的描述符可以不同,这也是文件共享的理论基础
3、文件打开操作 open()和openat()
(1)返回文件描述符或者-1
int open(char *filename, int flags, mode_t mode);
int openat(int fd,<span style="font-family: Arial, Helvetica, sans-serif;">char *filename, int flags, mode_t mode</span>)
(2)flags参数
O_RDONLY: Reading only
O_WRONLY: Writing only
O_RDWR: Reading and writing
还有O_APPEND、O_CREAT、O_SYNC等常用的参数。有需要参考官方文档。
(3)openat()的引入是为了解决
open()中文件路径为相对路径时,不再只能打开当前工作目录的文件的问题
避免两个函数调用相关联引起的文件覆盖问题
fd为参数指出了相对路径在文件系统的起始地址
4、创建文件
int creat(const char *path,mode_t mode); 等效于 open(path,O_WRONLY|O_CREAT|O_TRUNC,mode)
creat()以只写的方式创建并打开文件,不能立即读取文件,所以最好用第二种方法。
5、文件关闭
int close(int fd);
关闭文件,释放记录锁。进程关闭时,内核会自动关闭该进程的所有调用文件,所以有时不比显示关闭文件。
6、文件偏移函数
off_t lseek(int fd,off_t offset, int whence);
whence:
SEEK_SET 文件操作从offset处开始
SEEK_CUR 文件已有偏移+offset
SEEK_END 文件长度+offset
offset 可正负
off_t的类型决定了一个文件的最大长度,32位时,有符号位,最大长度为2^31-1,2GB
7、读操作
ssize_t read(int fd, void *buf,size_t nbytes);
(1)返回-1,出错;返回0,到达文件末尾;返回正整数,读取字节数
(2)设置读取nbytes,在不同设备上可以读取的字节数往往不能满足nbytes
8、写操作
ssize_t write(int fd, void *buf,size_t nbytes);
(1)出错,返回-1,成功返回写的字节数
(2)默认写操作时从当前偏移开始的,但是当在打开文件设置了O_APPEND参数时,文件偏移设为了末尾,在末尾插入nbytes数据。
9、文件共享
(1)每个进程的进程表有一个表项记录打开文件的文件描述符表,不同的描述符,都对应一个不同的文件表
(2)文件表记录文件的状态(读、写、阻塞、同步、添加等)、文件偏移量和指向文件V结点结构的指针,仍然属于当前进程
(3)文件V结点结构是描述具体文件的信息载体。包含文件类型、对此文件的各种操作、文件作者、长度、指向文件所在磁盘位置的指针等。
文件V结点也是对具体文件系统的抽象,不属于某一个进程。
这样,不同进程可以对同一个文件V结点结构进行操作,在处理好同步的情况下,可以实现不同进程/线程的文件共享。
10、文件描述符的复制
共享同一个文件表
int dup(int fd); int dup2(int fd, int fd2);
dup()函数返回fd文件符描述文件的最小可用文件描述符,失败返回-1
dup2(fd,fd2)函数返回指定文件描述符fd2,如果fd2被占用,则先将其关闭,如果fd2=fd,返回fd2。失败返回-1。
11、缓存区刷新
延迟写:
内核中设有缓存区高速缓存或者页高速缓存,大多数I/O操作都要经过缓存区,再排入读写队列,最后由系统守护进程定时调用sync函数写入磁盘
void sync(void); int fsync(int fd);
sync将修改过的缓存区排入写队列,就返回,不管是否写入磁盘。写队列由系统守护进程update维护
fsync(fd)只将文件描述符fd描述的文件的修改部分立即调用I/O操作写入磁盘。
12、改变已打开文件的属性
int fcntl(int fd,int cmd,.../*int arg*/);
该函数有五种功能:
(1)辅助一个已有的描述符,功能同dup() dup2()函数
(2)获取/设置文件描述符的标志,即改变FD_CLOEXEC的值,0开,1关闭
(3)获取/设置文件状态
(4)获取/设置异步I/O的所有权
(5)获取/设置记录锁
13、ioctl函数
ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制。
详细参考:http://blog.csdn.net/shanshanpt/article/details/19897897