Unix 系统大多数文件 i/o 只需要:open、read、write、lseek、close 这几个函数。但是某些时候我们也需要 fcntl、ioctl、sync 等函数配合使用。这些函数都是不带缓冲区的 I/0(unbuffered I/O),
术语不带缓冲的指的是每个 read 和 write 都是内核中的一个系统调用。这些函数都是 POSIX 和 single UNIX Specification 的组成部分。
这样说可能有点迷糊,举个例子说明
不带缓存的 I/O: read,write,open......
标准 (带缓存的)I/O: fgets,fread,fwrite.....
这里使用两个对应的函数进行比较:
- ssize_t write(int filedes, const void *buff, size_t nbytes)
- size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *fp)
上面的 buff 和 ptr 都是指应用程序自己使用的 buffer,实际上当需要对文件进行写操作时,都会先写到内核所设的缓冲存储器。
1、如果我们直接用非缓存 I/O 对内核的缓冲区进行读写,会产生许多管理不善而造成的麻烦(如一次性写入过多,或多次系统调用导致的效率低下)。
2、标准 (带缓存的)I/O 为我们解决了这些问题,它处理很多细节,如缓冲区分配,以优化长度执行 I/O 等,更便于我们使用。
一切皆是文件 " 是 Unix/Linux 的基本哲学之一。不仅普通的文件,目录、字符设备、块设备、 套接字等在 Unix/Linux 中都是以文件被对待;它们虽然类型不同,但是对其提供的却是同一套操作界面。
对内核而言,所有打开的文件都是通过文件描述符引用的,文件描述符是一个非负的整数,当打开一个现有文件或创建一个新文件,内核向进程返回一个文件描述符。按照惯例,unix 系统 shell 把文件描述符 0 与进程的标准的输入关联,
文件描述符 1 与标准的输出关联,文件描述符 2 与标准错误关联。幻数 0,1,2 虽然已被标准化,我们在使用的时候应该用 STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO 符号代替以提高可读性
unix 系统支持在不同进程间共享打开的文件。
内核使用三种数据结果表示打开的文件。
(1)每个进程在进程表中都有一个记录项,记录项中包含有一张打开文件的描述符表,可将其视为一个矢量,每个描述符占用一项。
每个文件描述符相关连的是:
(2)内核为所有打开文件维持一张文件表。每个文件表项包含:
(3)每个打开的文件都有一个 v 节点结构。v 节点包含了文件类型和对此文件进行各种操作的函数的指针。对于大多数文件,v 节点还包括了该文件的 i 节点。这些信息是再打开文件时从磁盘上读入内存的。这些文件都是从磁盘读入内存的,所以可以快速使用这些参数。
note:没有使用 v 节点,而是使用了通用的 i 节点。
此图为打开文件的内核,该进程有两个不同的打开文件,一个文件打开为标准输入,另一个打开为标准输出。
如果两个独立进程各自打开同一个文件,则有如图所示
我们假设第一个进程在文件描述符 3 打开该文件,而另一个进程在文件描述符 4 上打开该文件。打开该文件的每个进程都得到一个文件表项。但对一个给定的文件只有一个 v 节点表项。每个进程都有自己的一个文件表项,理由是每个进程都要有对一个文件的偏移量。
下面描述上图的产生事件:
可能有多个文件描述符指向同一个文件表项
fork 后也会发生同样的情况,此时父子进程对于每个打开文件描述符共享同一个文件表项。
note:文件描述符标志和恩见状态标志在作用域方面的区别。潜质只用与一个进程的一个进程描述符。而后者则使用语指向改给定文件表项的任何进程中的所有描述符。
当我们看到多个进程进行对一个文件同时操作的时候,这时候就产生了冲突,如何避免呢,那么就是下一节原子操作~
2017/4/5(2 天一博客连载 Unix 环境编程)加油
来源: http://www.cnblogs.com/smartxuchao/p/6671231.html