Linux 文件 IO 基础操作


Linux文件IO 与 C标准库文件IO

image-20220510161324134

image-20220510161515157

虚拟地址空间

虚拟地址通过页表映射到屋里内存,页表由操作系统维护并被处理器引用。

分为用户段(0~3G)和内核段(3G ~ 4G), 如下图所示。

Ref

image-20220510161614225

文件描述符

def: Linux 系统中,把一切都看做是文件,当进程打开现有文件或创建新文件时,内核向进程返回一个文件描述符,文件描述符就是内核为了高效管理已被打开的文件所创建的索引,用来指向被打开的文件,所有执行I/O操作的系统调用都会通过文件描述符。

  • 每个文件描述符会与一个打开的文件相对应
  • 不同的文件描述符也可能指向同一个文件
  • 相同的文件可以被不同的进程打开,也可以在同一个进程被多次打开

image-20220510162116554

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函数

  1. 移动文件指针到文件头:lseek(fd, 0, SEEK_SET)
  2. 获取当前文件指针的位置:lseek(fd, 0, SEEK_CUR)
  3. 获取文件长度:lseek(fd, 0, SEEK_END)
  4. **拓展文件的长度, 当前文件长度为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

(0)
上一篇 2022年7月23日
下一篇 2022年7月23日

相关推荐

发表回复

登录后才能评论