Linux文件IO 与 C标准库文件IO
虚拟地址空间
虚拟地址通过页表映射到屋里内存,页表由操作系统维护并被处理器引用。
分为用户段(0~3G)和内核段(3G ~ 4G), 如下图所示。
文件描述符
def: Linux 系统中,把一切都看做是文件,当进程打开现有文件或创建新文件时,内核向进程返回一个文件描述符,文件描述符就是内核为了高效管理已被打开的文件所创建的索引,用来指向被打开的文件,所有执行I/O操作的系统调用都会通过文件描述符。
- 每个文件描述符会与一个打开的文件相对应
- 不同的文件描述符也可能指向同一个文件
- 相同的文件可以被不同的进程打开,也可以在同一个进程被多次打开
open函数
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/*
int open(const char *pathname, int flags); 打开一个已经存在的文件
- pathname: 文件路径
- flags: 对文件的操作权限设置
O_RDONLY、O_WRONLY,ORDWR 三个设置是互斥的
errno:属于 Linux 系统函数库,库中定义全局变量,记录的是最近的错误号。
perror(const char *s):打印 error 对应的错误描述
int open(const char *pathname, int flags, mode_t mode); 创建一个新的文件
-pathname: 要创建的文件路径
-flags:文件的操作权限和其他设置, 同上, O_CREAT,文件不存在,创建新文件
- mode: 八进制数
最终权限是 mode & ~umask, umask 0002, ~umask 0775
0777 & 0775 = 0775
umask作用:抹去某些权限, 其他组不可以进行写的操作
*/
int main(int argc, char *argv[]) {
// int fd = open("a.txt", O_RDONLY);
// if (fd == -1) {
// perror("open failed");
// }
// close(fd);
int fd = open("create.txt", O_RDWR | O_CREAT, 0777);
if (fd == -1) {
perror("create failed");
}
close(fd);
return 0;
}
read & write
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
/*
ssize_t read(int fd, void *buf, size_t count);
- fd: 文件描述符
- buf:缓冲区,读取数据存放的地方,数组的地址
- count:指定的数组的大小
返回值:
> 0: 返回实际读取的大小字节
=0:文件已经读完了
-1: 失败
ssize_t write(int fd, const void *buf, size_t count);
- fd: 文件描述符
- buf:缓冲区,要往磁盘写入的数据
- count:要写的数据的实际大小
返回值:
> 0: 实际写入的字节大小
-1: 失败
*/
void errif(bool flag, const char *msg) {
if (flag) {
perror(msg);
exit(EXIT_FAILURE);
}
}
int main() {
// open打开文件
int src_fd = open("./create.txt", O_RDONLY);
errif(src_fd == -1, "open failed");
// 创建一个新的文件
int dest_fd = open("copy.txt", O_WRONLY | O_CREAT, 0664);
errif(dest_fd == -1, "open failed");
// 频繁的读写操作
char buf[1024];
bzero(&buf, sizeof(buf));
int len = 0;
while ((len = read(src_fd, buf, sizeof(buf))) > 0) {
write(dest_fd, buf, len);
}
// 关闭文件
close(src_fd);
close(dest_fd);
return 0;
}
lseek函数
- 移动文件指针到文件头:
lseek(fd, 0, SEEK_SET)
- 获取当前文件指针的位置:
lseek(fd, 0, SEEK_CUR)
- 获取文件长度:
lseek(fd, 0, SEEK_END)
- **拓展文件的长度, 当前文件长度为10b, 110b, 增加了100个字节: **
lseek(fd, 100, SEEK_END)
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
/*
off_t lseek(int fd, off_t offset, int whence);
fd: 文件描述符,通过 open 得到的
offset: 偏移量
whence:
SEEK_SET
设置文件指针偏移量(文件开始处)
The file offset is set to offset bytes.
SEEK_CUR
设置偏移量:当前位置 + 第二个参数 offset
The file offset is set to its current location plus offset bytes.
SEEK_END
文件大小 + 第二个参数 offset
The file offset is set to the size of the file plus offset bytes.
返回文件指针所在位置
移动文件指针到文件头
lseek(fd, 0, SEEK_SET);
获取当前文件指针的位置
lseek(fd, 0, SEEK_CUR);
获取文件长度
lseek(fd, 0, SEEK_END);
拓展文件的长度,当前文件 10b,增加 100 字节 100 字节
*/
int main() {
int fd = open("create.txt", O_RDWR);
if (fd == -1) {
perror("open failed");
return -1;
}
int ret = lseek(fd, 100, SEEK_END);
if (ret == -1) {
perror("lseek failed");
return -1;
}
write(fd, " ", 1);
close(fd);
return 0;
}
原创文章,作者:6024010,如若转载,请注明出处:https://blog.ytso.com/276349.html