POSIX是可移植操作系统接口的简写,英文全程是Portable Operating System Interface。最初由IEEE(Institute of Electrical and Electronics Engineers,IEEE)开发,目的是为了提高UNIX环境下的应用程序可移植性。实际上POSIX并不局限于UNIX,只要符合此标准的操作系统的系统调用是一致的,例如Linux和Microsoft Windows NT。POSIX是一组操作系统调用的规范,本节介绍其中的文件I/O编程规范。
1 底层的文件I/O操作
和ANSI文件操作函数不同的是,POSIX文件操作的函数基本上和计算机设备驱动的底层操作(例如read,write等)是一一对应的。读者可以把POSIX文件操作理解为对设备驱动操作的封装。由此也可以看出,POSIX文件操作是不带数据缓冲的。
2 文件描述符
POSIX文件操作也使用文件描述符来标识一个文件。与ANSI文件描述符不同的是,POSIX文件描述符是int类型的一个整数值。POSIX文件描述符仅是一个索引值,代表内核打开文件记录表的记录索引。在一个系统中,文件打开关闭比较频繁,因此同一个POSIX文件描述符的值在不同时间可能代表不同的文件。
任何打开的文件都将被分配一个唯一标识该打开文件的文件描述符,为一个大于等于0的整数。需要注意的是,对于一个进程来说,打开文件的数量不是任意大小的。POISX没有规定一个进程可以打开文件的最大数目,不同的系统有不同的规定,例如Linux系统默认一个进程最多可以打开1024个文件,用户可以在console模式下通过ulimit –n命令查看系统允许进程打开文件的数量。
3 创建/打开/关闭文件
POSIX使用open()函数打开一个文件,使用creat()函数创建一个新文件,这两个函数在手册里常常放在一起介绍,因为open()函数在指定一定参数的情况下会隐含调用creat()函数创建文件。
1.open()函数
2.creat()函数
3.close()函数
clos()函数定义形式如下:
#include <unistd.h> int close(int fd);
4 读写文件内容
POSIX文件操作使用read()函数和write()函数对文件读写,和ANSI文件操作的fread()函数和fwrite()函数不同的是read()函数和write()函数是不带缓冲的,并且不支持记录方式。write()函数的定义如下:
#include <unistd.h> ssize_t write(int fd, const void *buf, size_t count);
mode参数说明
- r或rb为
读打开文件 - w或wb
为写打开文件,并把文件长度置为0(清空文件) - a或ab
在文件结尾添加打开 - r+或r+b或rb+
为读和写打开 - w+或w+b或wb+
为写打开文件,并把文件长度置0(清空文件) - a+或a+b或ab+
在文件结尾读写打开
5 文件内容定位
每当打开一个文件的时候,都会有一个与文件相关联的读写位置偏移量,相当于一个文件指针。文件偏移量是一个非负整数,表示相对于文件开头的偏移。通常情况下,文件的读写操作都是从当前文件偏移量开始,读写之后使文件偏移量增加读写的字节数。打开文件时,如果不指定O_APPEND方式,文件偏移量默认是从0开始。
POSIX文件操作提供了lseek()函数用于设置文件偏移量,函数定义如下:
#include <sys/types.h> #include <unistd.h> off_t lseek(int fildes, off_t offset, int whence);
参数值解释SEEK_SET从文件开始处设置文件偏移量SEEK_CUR从当前文件偏移量设置SEEK_END从文件结尾处设置文件偏移量
6 修改已打开文件属性
fcntl()函数提供了获取或者改变已打开文件性质的功能,函数定义如下:
#include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd); int fcntl(int fd, int cmd, long arg); int fcntl(int fd, int cmd, struct flock *lock);
7 POSIX文件编程实例
最后给出一个POSIX操作文件的例子,完成文件的创建,读写等操作。
#include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include stdio.h> #include <errno.h> extern int errno; int main(){ int fd;,file_mode; // 注意,文件描述符是整型值 char buf[64] = "this is a posix file!(line1)\n"; off_t curr_pos; fd = open("./posix.data", O_CREAT|O_RDWR|O_EXCL, S_IRWXU); //打开一个不存在的文件,并创建文件,权限是用户可读写执行 if (-1==fd) { // 检查文件打开是否成功 switch (errno) { case EEXIST: // 文件已存在 printf("File exist!\n"); break; default: // 其他错误 printf("open file fail!\n"); break; } return 0; } write(fd, buf, strlen(buf)); // 把字符串写入文件 curr_pos = lseek(fd, 0, SEEK_CUR); // 取得当前文件偏移量位置 printf("File Point at: %d\n", curr_pos); lseek(fd, 0, SEEK_SET); // 把文件偏移量移动到文件开头 strcpy(buf, "File Pointer Moved!\n"); write(fd, buf, strlen(buf)); // 把新的数据写入文件 file_mode = fcntl(fd, F_GETFL); // 获取文件状态标记 if (-1!=file_mode) { switch (file_mode&O_ACCMODE) { // 检查文件状态 case O_RDONLY: printf("file mode is READ ONLY\n"); break; case O_WRONLY: printf("file mode is WRITE ONLY\n"); break; case O_RDWR: printf("file mode is READ & WRITE\n"); break; } } close(fd); return 0; }