itop-3568 开发板系统编程学习笔记(2)文件 IO

【北京迅为】嵌入式学习之Linux系统编程篇 https://www.bilibili.com/video/BV1zV411e7Cy/ 个人学习笔记

标准 IO 和 文件 IO

文件 IO:直接调用内核提供的系统调用函数,依赖系统,比如本笔记所讲的文件 IO 只能在 linux 系统上运行;

标准 IO:间接调用系统调用函数,为 C 库函数,不依赖操作系统。

open 函数

文件描述符

文件 IO 的一切操作都是围绕文件描述符进行的,Linux 系统中所有打开的文件都有一个对应的文件描述符。文件描述符是一个非负整数,它由系统自动分配。每个进程的 0,1,2 三个描述符已经被使用,分别代表标准输入、标准输出和标准错误。

open 函数介绍

  • 头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
  • 函数定义
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

参数 flags 可以为 O_RDONLY(只读)、O_WRONLY(只写)或者 O_RDWR(可读可写),同时 flags 可以按位或上 O_CREAT(创建文件) 、 O_APPEND(追加写) 或 O_TRUNC(截断写)等,比如 open("xx", O_APPEND|O_RDWR)

当 flags 参数里有 O_CREAT 时,需要加上第三个参数 mode,用来指定新建文件的权限。

#define S_IRUSR 00400 /*文件所有者可读*/
#define S_IWUSR 00200 /*文件所有者可写*/
#define S_IXUSR 00100 /*文件所有者可执行*/
#define S_IRGRP 00040 /*与文件所有者同组的用户可读*/
#define S_IWGRP 00020 /*与文件所有者同组的用户可写*/
#define S_IXGRP 00010 /*与文件所有者同组的用户可执行*/
#define S_IROTH 00004 /*与文件所有者不同组的用户可读*/
#define S_IWOTH 00002 /*与文件所有者不同组的用户可写*/
#define S_IXOTH 00001 /*与文件所有者不同组的用户可可执行*/

#define S_IRWXUGO	(S_IRWXU|S_IRWXG|S_IRWXO)	/* 所有用户可读、写、执行 */
#define S_IALLUGO	(S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO)/* 所有用户可读、写、执行*/
#define S_IRUGO		(S_IRUSR|S_IRGRP|S_IROTH)	/* 所有用户可读 */
#define S_IWUGO		(S_IWUSR|S_IWGRP|S_IWOTH)	/* 所有用户可写 */
#define S_IXUGO		(S_IXUSR|S_IXGRP|S_IXOTH)	/* 所有用户可执行 */

如果直接填 0644(0不能省略,0644 代表八进制数 644),表示文件所有者可读写,同组用户和其他用户只读。

  • 返回值

成功返回新的文件描述符,返回 -1 表示文件打开(创建)失败。

close 函数

  • 头文件:
#include <unistd.h>
  • 函数定义
int close(int fd);
  • 返回值

返回 0 表示成功,-1 表示失败。

read 函数

  • 头文件:
#include <unistd.h>
  • 函数定义
ssize_t read(int fd, void *buf, size_t count);

count 为要读取的字节数,buf 用来存放读取到的数据。

  • 返回值

如果成功,返回读到的字节数,如果失败,返回 -1。

write 函数

  • 头文件:
#include <unistd.h>
  • 函数定义
ssize_t write(int fd, void *buf, size_t count);

buf 为要发送的数据,count 为要写入的字节数。

  • 返回值

如果成功,返回成功写入的字节数,如果失败,返回 -1。

lseek 函数

  • 头文件:
#include <sys/types.h>
#include <unistd.h>
  • 函数定义
off_t lseek(int fd, off_t offset, int whence);

offset 为偏移量(字节),为正数表示向前移动,为负数表示向后移动;

whence 为偏移参考点,可取值包括:

SEEK_CUR:读写偏移量将指向当前位置偏移量 + offset 字节位置处;
SEEK_SET:读写偏移量将指向 offset 字节位置处(从文件头开始算);
SEEK_END:读写偏移量将指向文件末尾 + offset 字节位置处
  • 返回值

如果成功,返回当前偏移量,如果失败,返回 -1。

综合实验

练习题:把 a.c 文件里的内容写到 b.c

个人练习代码,仅供参考:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

char BUFF[1024];

int main()
{
    
    
	int ret = 0, sum = 0;
	int fd1, fd2;

	// 打开 a.c
	fd1 = open("a.c", O_RDONLY);
	if(fd1 < 0)
	{
    
    
		printf("a.c 打开失败.\n");	
		return 0;
	}

	// 读取 a.c 文件大小
	ret = lseek(fd1, 0, SEEK_END);
	if(ret != 0)
	{
    
    
		printf("a.c 大小为 %d bytes.\n", ret);
		lseek(fd1, 0, SEEK_SET); // 将文件指针指向开头
	}
	else
	{
    
    
		printf("a.c 为空, 操作失败.\n");
		return 0;
	}

	// 打开(创建)b.c,写入文件采用截断的方式
	fd2 = open("b.c", O_CREAT|O_TRUNC|O_RDWR, 0644);
	if(fd2 < 0)
	{
    
    
		printf("b.c 打开失败.\n");	
		return 0;
	}

	// 将 a.c 内容拷贝到 b.c
	while((ret = read(fd1, BUFF, 1024)) != 0)
	{
    
    
		sum += write(fd2, BUFF, ret);
	}
	printf("成功向b.c写入 %d bytes.\n", sum);

	
	// 关闭 a.c 和 b.c
	close(fd1);
	close(fd2);
}

编译实验源文件,直接运行,会提示 a.c 不存在,

在这里插入图片描述

手动创建一个 a.c 文件,并手动写入一些数据,然后再运行实验程序,成功实现将 a.c 内容复制到 b.c 。

在这里插入图片描述

如果把 a.c 文件变大,依然可以完成复制。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43772810/article/details/129136204