UNIX系统 文件操作接口

一、文件描述符

     对于内核而言所有打开的文件都是通过文件描述符引用。文件描述符是一个非负整数。当打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。当读或者写一个文件时使用open或creat返回文件描述符标识该文件,将作为参数传递给read或write

    UNIX系统shell把文件描述符0与进程的标准输入关联,文件描述符1与标准输出关联,文件描述符2与标准错误关联。这是各种shell以及很多程序使用的惯例,与UNIX内核无关。

     在符合POSIX.1的应用程序中。幻数0、1、2以及被标准化。但是建议使用符号常量:STDIN_FILENO、STDOUT_FILENO 、STDERR_FILENO以提高可读性。这些常量定义在头文件<unistd.h>中。

    文件描述符的变化范围是0~OPEN_MAX-1。早期可以同时使用的文件描述符是20个(既可以同时打开20个文件),现在多是64。可以使用函数sysconf来查看OPEN_MAX的值。

long sysconf(int _SC_OPEN_MAX)

二、文件操作

1、文件创建与打开

(1)open

1)函数原型

#include <fcntl.h>
int open(const char*path,int oflag,.../*mode_t mode*/);
2)参数说明

   path是要打开或创建文件的名字。

   最后一个参数写为...表明余下的参数的数量及类型是可变的。仅当创建新文件时才使用最后这个参数mode.用于指定文件的访问权限位。

   oflag参数可以用来说明此函数的多个选项。用下列一个或多个常量进行“或”运算构成oflag参数

O_RDONLY      只读模式
O_WRONLY      只写模式
O_RDWR        读写模式
O_EXEC         只执行打开

O_SEARCH 只搜索打开(应用与目录)
打开/创建文件时,至少得使用上述五个常量中的一个。以下常量是选用的:

O_APPEND       每次写操作都写入文件的末尾
O_CREAT        如果指定文件不存在,则创建这个文件。使用此选项时要同时说明open函数的第三个参mode,用mode指定该新文件的权限位。
O_EXCL         如果要创建的文件已存在,则返回 -1,并且修改 errno 的值
O_TRUNC        如果文件存在,并且以只写/读写方式打开,则清空文件全部内容
O_NOCTTY       如果路径名指向终端设备,不要把这个设备用作控制终端。
O_NONBLOCK     如果路径名指向 FIFO/块文件/字符文件,则把文件的打开和后继 I/O设置为非阻塞模式(nonblocking mode)

以下三个常量同样是选用的,它们用于同步输入输出

O_DSYNC        等待物理 I/O 结束后再 write。在不影响读取新写入的数据的前提下,不等待文件属性更新。
O_RSYNC        read 等待所有写入同一区域的写操作完成后再进行
O_SYNC         等待物理 I/O 结束后再 write,包括更新文件属性的 I/O

3)返回值

open 函数返回的文件描述符一定是最小的未用的描述符值。

(2)openat

int openat(int fd, const char* path,int oflag,.../*mode_t mode*/);
   与open 不同的是openat函数可以使用相对路径名打开目录中的文件,而不再只打开当前工作目录。

    path参数是绝对路径名时,fd参数被忽略,openat函数就相当于open函数;path参数是相对路径名时,fd参数指出了相对路径名在文件系统中的开始地址。fd参数是通过打开相对路径名所在的目录来获取;若fd参数的值为AT_FDCWD则,路径名会在当前工作目录中获取。

(3)creat

#include<fcntl.h>
int create(const char* path,mode_tmode);
等价于

open(path,O_WRONLY | O_CREAT | O_TRUNC, mode);

create 的不足之处是它一只写的方式打开所创建的文件。

2、文件关闭

#include<unistd.h>
int close(int fd);
关闭一个文件时还会释放该进程加在该文件上的所有记录锁。

当一个进程结束时,内核会自动关闭它所有打开的文件。
3、读文件

(1)read

1)函数原型

#include<unistd.h>
ssize_t read(int fd,void *buf,size_t nbytes)
2)返回值

read 成功时,返回读到的字节数。如已到达文件的尾端,则返回0;若出错,返回-1。

3)说明

多种情况会使实际读到的字节数少于要求读的字节数。例如:在读到要求的字节数之前已经到达了文件的尾端;从终端设备读时,通常一次最多读一会等

4、写文件

(1)write

#include <unistd.h>
ssize_t write(int fd,const void* buf,size_t nbytes);

write函数向打开的文件写数据。若成功返回已写的字节数,若出错返回-1.

5、其它

(1)使用int dup(int fd)或int dup2(int fd,int fd2)函数进行文件描述符复制

  (2)  使用int fsync(int fd)或void sync(void);将缓冲区数据写至磁盘

(3)使用fcntl函数gaibian已经打开的文件属性

(4)使用off_t lseek(int fd,off_t offset,int whence);函数显示设置一个已经打开文件的偏移量

三、与标准C函数库的区别

标准C库是对系统文件I/O接口的封装。标准I/O库处理了很多细节,如缓冲区分配、以优化的块长度执行I/O等。

1、不带缓冲

 不带缓冲指:每个read和write都调用内核中的一个系统调用

2、文件描述符与流

对于内核所有的文件操作都是围绕文件描述符来进行的;但是标准C I/O库是围绕流(FILE*)进行的。







猜你喜欢

转载自blog.csdn.net/zxx910509/article/details/56667096