c/c++文件操作学习
open函数
函数
int open(const char * pathname, int flags);
int open(const char * pathname, int flags, mode_t mode);
pathname:指路径
flag | 功能 |
---|---|
O_RDONLY | 以只读方式打开文件 |
O_WRONLY | 以只写方式打开文件 |
O_RDWR | 以可读写方式打开文件 |
上述三种旗标是互斥的, 也就是不可同时使用, 但可与下列的旗标利用OR运算符组合 | |
O_CREAT | 若欲打开的文件不存在则自动建立该文件 |
O_EXCL | 如果O_CREAT 也被设置, 此指令会去检查文件是否存在. 文件若不存在则建立该文件, 否则将导致打开文件错误. 此外, 若O_CREAT 与O_EXCL 同时设置, 并且欲打开的文件为符号连接, 则会打开文件失败 |
O_NOCTTY | 如果欲打开的文件为终端机设备时, 则不会将该终端机当成进程控制终端机 |
O_TRUNC | 若文件存在并且以可写的方式打开时, 此旗标会令文件长度清为0, 而原来存于该文件的资料也会消失 |
O_APPEND | 当读写文件时会从文件尾开始移动, 也就是所写入的数据会以附加的方式加入到文件后面 |
O_NONBLOCK | 以不可阻断的方式打开文件, 也就是无论有无数据读取或等待, 都会立即返回进程之中 |
O_NDELAY | 同O_NONBLOCK |
O_SYNC | 以同步的方式打开文件 |
O_NOFOLLOW | 如果参数pathname |
O_DIRECTORY | 如果参数pathname 所指的文件并非为一目录, 则会令打开文件失败 |
参数mode 则有下列数种组合, 只有在建立新文件时才会生效, 此外真正建文件时的权限会受到umask 值所影响, 因此该文件权限应该为 (mode-umaks)
mode | 权限 |
---|---|
S_IRWXU00700 | 代表该文件所有者具有可读、可写及可执行的权限 |
S_IRUSR 或S_IREAD, 00400 | 代表该文件所有者具有可读取的权限 |
S_IWUSR 或S_IWRITE, 00200 | 代表该文件所有者具有可写入的权限 |
S_IXUSR 或S_IEXEC, 00100 | 代表该文件所有者具有可执行的权限 |
S_IRWXG 00070 | 代表该文件用户组具有可读、可写及可执行的权限 |
S_IRGRP 00040 | 代表该文件用户组具有可读的权限 |
S_IWGRP 00020 | 代表该文件用户组具有可写入的权限 |
S_IXGRP 00010 | 代表该文件用户组具有可执行的权限 |
S_IRWXO 00007 | 代表其他用户具有可读、可写及可执行的权限 |
S_IROTH 00004 | 代表其他用户具有可读的权限 |
S_IWOTH 00002 | 代表其他用户具有可写入的权限 |
S_IXOTH 00001 | 代表其他用户具有可执行的权限 |
错误代码
参数 | 功能 |
---|---|
EEXIST | 参数pathname 所指的文件已存在, 却使用了O_CREAT 和O_EXCL 旗标 |
EACCESS | 参数pathname 所指的文件不符合所要求测试的权限 |
EROFS | 欲测试写入权限的文件存在于只读文件系统内 |
EFAULT | 参数pathname 指针超出可存取内存空间 |
EINVAL | 参数mode 不正确 |
ENAMETOOLONG | 参数 pathname 太长 |
ENOTDIR | 参数pathname 不是目录 |
ENOMEM | 核心内存不足 |
ELOOP | 参数pathname 有过多符号连接问题 |
EIO | I/O 存取错误 |
mmap函数
头文件
#include <unistd.h>
#include <sys/mman.h>
函数
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offsize);
//mmap()用来将某个文件内容映射到内存中,对该内存区域的存取即是直接对该文件内容的读写。
参数说明
参数 | 说明 |
---|---|
start | 指向欲对应的内存起始地址,通常设为NULL,代表让系统自动选定地址,对应成功后该地址会返回 |
length | 代表将文件中多大的部分对应到内存 |
prot | 代表映射区域的保护方式,有下列组合 PROT_EXEC:映射区域可被执行 PROT_READ :映射区域可被读取PROT_WRITE:映射区域可被写入PROT_NONE:映射区域不能存取 |
flags | 会影响映射区域的各种特性:**MAP_FIXED **: 如果参数 start 所指的地址无法成功建立映射时,则放弃映射,不对地址做修正。通常不鼓励用此旗标。**MAP_SHARED **: 对应射区域的写入数据会复制回文件内,而且允许其他映射该文件的进程共享。MAP_PRIVATE: 对应射区域的写入操作会产生一个映射文件的复制,即私人的"写入时复制" (copy on write)对此区域作的任何修改都不会写回原来的文件内容。MAP_ANONYMOUS : 建立匿名映射,此时会忽略参数fd,不涉及文件,而且映射区域无法和其他进程共享。**MAP_DENYWRITE ** :只允许对应射区域的写入操作,其他对文件直接写入的操作将会被绝。MAP_LOCKED: 将映射区域锁定住,这表示该区域不会被置换(swap)。在调用mmap()时必须要指定MAP_SHARED 或MAP_PRIVATE。 |
fd | open()返回的文件描述词,代表欲映射到内存的文件 |
offset | 文件映射的偏移量,通常设置为0,代表从文件最前方开始对应,offset必须是分页大小的整数倍 |
返回值
若映射成功则返回映射区的内存起始地址,否则返回MAP_FAILED(-1),错误原因存于errno 中。返回值:若映射成功则返回映射区的内存起始地址,否则返回MAP_FAILED(-1),错误原因存于errno 中。
错误代码:
代码 | 功能 |
---|---|
EBADF | 参数fd 不是有效的文件描述词 |
EACCES | 存取权限有误。如果是MAP_PRIVATE 情况下文件必须可读,使用MAP_SHARED 则要有PROT_WRITE 以及该文件要能写入 |
EINVAL | 参数start、length 或offset 有一个不合法 |
EAGAIN | 文件被锁住,或是有太多内存被锁住 |
ENOMEM | 内存不足 |
使用中的问题
include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> #include <iostream> using namespace std; int main()
{
int fd;
fd = open("Wandering.txt", O_RDWR | O_CREAT, 00777);
char* Out = (char*) mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
string He = "Hello World!";
char* str = (char*)&He;
cout << &He << endl;
Out[1] = '1';
while(*str != '\0')
{
cout << *str++ << endl;
}
munmap(Out, 100); /* 解除映射 */ }
当向mmap地址中写入数据总是出现Bus error的提示
发生错误的原因是因为mmap不能去扩展一个内容为空的新文件,因为大小为0,所有本没有与之对应的合法的物理页,不能扩展。所以只需要在新创建的空文件中先写入一些数据即可。
lseek()函数
所有打开的文件都有一个当前文件偏移量(current file offset),以下简称为 cfo。cfo 通常是一个非负整数,用于表明文件开始处到文件当前位置的字节数。读写操作通常开始于 cfo,并且使 cfo 增大,增量为读写的字节数。文件被打开时,cfo 会被初始化为 0,除非使用了O_APPEND 。
函数调用
#include <unistd.h>
#include <sys/types.h>
off_t lseek(int filedes, off_t offset, int whence);
参数说明
返回值:
- -1:失败
- 数据 新的偏移量
whence | 功能 |
---|---|
SEEK_SET | 文件偏移量将被设置为 offset |
SEEK_CUR | 文件偏移量将被设置为 cfo 加上 offset |
SEEK_END | 文件偏移量将被设置为文件长度加上 offset |
SEEK_SET、SEEK_CUR 和 SEEK_END 是 System V 引入的,在这之前使用的是 0、1 和 2。