文 件 I / O

来源:互联网 发布:php开发游戏 编辑:程序博客网 时间:2024/06/08 07:51

本章所说明的函数经常被称之为不带缓存的I / O(u n b u ffered I/O,术语——不带缓存指的是每个 r e a d和w r i t e都调用内核中的一个系统调用。


文件描述符

按照惯例,UNIX shell使文件描述符0与进程的标准输入相结合,文件描述符 1与标准输出相结合,文件描述符2与标准出错输出相结合。


open函数

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char * p a t h n a m e, int o f l a g,.../*, mode_t  m o d e * / ) ;
返回:若成功为文件描述符,若出错为- 1


用下列一个或多个常数进行或运算构成o f l a g参数(这些常数定义在< f c n t l . h >头文件中):
• O_RDONLY 只读打开。
• O_WRONLY 只写打开。
• O_RDWR 读、写打开。


• O_APPEND 每次写时都加到文件的尾端。3 . 11节将详细说明此选择项。
• O_CREAT 若此文件不存在则创建它。使用此选择项时,需同时说明第三个参数 m o d e,
用其说明该新文件的存取许可权位。 ( 4 . 5节将说明文件的许可权位,那时就能了解如何说明
m o d e,以及如何用进程的u m a s k值修改它。)

• O_TRUNC 如果此文件存在,而且为只读或只写成功打开,则将其长度截短为 0


creat函数
也可用c r e a t函数创建一个新文件。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int creat(const char * p a t h n a m e, mode_t m o d e) ;
返回:若成功为只写打开的文件描述符,若出错为- 1

注意,此函数等效于:
o p e n (p a t h n a m e, O_WRONLY |O _ C R E A T|O_TRUNC, m o d e) ;


close函数
可用c l o s e函数关闭一个打开文件:
#include <unistd.h>
int close (int  f i l e d e s);
返回:若成功为0,若出错为- 1

关闭一个文件时也释放该进程加在该文件上的所有记录锁。 


lseek函数
每个打开文件都有一个与其相关联的“当前文件位移量”。它是一个非负整数,用以度量
从文件开始处计算的字节数。通常,读、写操作都从当前文件位移量处开始,并使位移量增加所读或写的字节数。按系统默认,当
打开一个文件时,除非指定O _ A P P E N D选择项,否则该位移量被设置为0。
可以调用l s e e k显式地定位一个打开文件。
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int  f i l e d e s, off_t o f f s e t, int w h e n c e) ;
返回:若成功为新的文件位移,若出错为- 1

对参数offset 的解释与参数w h e n c e的值有关。
• 若w h e n c e是S E E K _ S E T,则将该文件的位移量设置为距文件开始处offset 个字节。
• 若w h e n c e是S E E K _ C U R,则将该文件的位移量设置为其当前值加offset, offset可为正或负。
• 若w h e n c e是S E E K _ E N D,则将该文件的位移量设置为文件长度加offset, offset可为正或负。

若l s e e k成功执行,则返回新的文件位移量,为此可以用下列方式确定一个打开文件的当前
位移量:
off_t currpos;
currpos = lseek(fd, 0, SEEK_CUR);
这种方法也可用来确定所涉及的文件是否可以设置位移量。


read函数
用r e a d函数从打开文件中读数据。
#include <unistd.h>
ssize_t read(int  f i l e d e s, void *b u f f, size_t n b y t e s) ;
返回:读到的字节数,若已到文件尾为 0,若出错为- 1


有多种情况可使实际读到的字节数少于要求读字节数:
• 读普通文件时,在读到要求字节数之前已到达了文件尾端。例如,若在到达文件尾端之
前还有3 0个字节,而要求读1 0 0个字节,则r e a d返回3 0,下一次再调用r e a d时,它将返回0 (文件
尾端)。
• 当从终端设备读时,通常一次最多读一行(第11章将介绍如何改变这一点)。
• 当从网络读时,网络中的缓冲机构可能造成返回值小于所要求读的字节数。
• 某些面向记录的设备,例如磁带,一次最多返回一个记录。
读操作从文件的当前位移量处开始,在成功返回之前,该位移量增加实际读得的字节数。

如r e a d成功,则返回读到的字节数。如已到达文件的尾端,则返回 0。


write函数
用w r i t e函数向打开文件写数据。
#include <unistd.h>
ssize_t write(int  f i l e d e s, const void * b u f f, size_t n b y t e s) ;
返回:若成功为已写的字节数,若出错为- 1


文件共享

内核使用了三种数据结构,它们之间的关系决定了在文件共享方面一个进程对另一个进程
可能产生的影响。
(1) 每个进程在进程表中都有一个记录项,每个记录项中有一张打开文件描述符表,可将
其视为一个矢量,每个描述符占用一项。与每个文件描述符相关联的是:
(a) 文件描述符标志。
(b) 指向一个文件表项的指针。
(2) 内核为所有打开文件维持一张文件表。每个文件表项包含:
(a) 文件状态标志(读、写、增写、同步、非阻塞等)。
(b) 当前文件位移量。
4 2 U N I X环境高级编程
下载
(c) 指向该文件v节点表项的指针。
(3) 每个打开文件(或设备)都有一个 v节点结构。v节点包含了文件类型和对此文件进
行各种操作的函数的指针信息。对于大多数文件, v节点还包含了该文件的 i节点(索引节
点)。这些信息是在打开文件时从盘上读入内存的,所以所有关于文件的信息都是快速可供
使用的。例如, i节点包含了文件的所有者、文件长度、文件所在的设备、指向文件在盘上
所使用的实际数据块的指针等等( 4 . 1 4节较详细地说明了 U N I X文件系统,将更多地介绍 i节
点。)






两进程打开同一个文件

每个进程都有自己的文件表项的一个理由是:这种安排使每个进程都有它自己的对该文件的当前位移量。






dup和d u p 2函数

下面两个函数都可用来复制一个现存的文件描述符:(不关闭原有描述符)
#include <unistd.h>
int dup(int  f i l e d e s) ;
int dup2(int  f i l e d e s, int f i l e d e s 2) ;
两函数的返回:若成功为新的文件描述符,若出错为- 1
由d u p返回的新文件描述符一定是当前可用文件描述符中的最小数值。用 d u p 2则可以用f i l e d e s 2
参数指定新描述符的数值。如果f i l e d e s 2已经打开,则先将其关闭。如若f i l e d e s等于f i l e d e s 2,则
d u p 2返回f i l e d e s 2,而不关闭它。


c标准函数和linux函数区别



理解:

标准I/O会产生FILE指针如图,会有个buffer缓冲区,写入缓冲区之后再调用应用层的API,也即使用文件描述符来向文件中写数据。


如何输出到显示设备:

应用程序A会掉用标准函数库,然后标准函数库会再向下调用应用层的API,通过不断的调用应用层API来输入到内核缓冲区,然后应用层再向下调用内核层的API,内核层的API会将其输出到显示设备上。



原创粉丝点击