嵌入式linux/鸿蒙开发板(IMX6ULL)开发(十二)文件IO

简介: 嵌入式linux/鸿蒙开发板(IMX6ULL)开发(十二)文件IO

4.文件IO


这部分内容只是简单的讲解一下关于文件I/O的知识。这部分内容如果要深入去了解,还要去看《操作系统》这本书。参考书:


1670752894877.jpg

这2本书的内容类似,第一本对知识点有更细致的描述,适合初学者;第二本比较直接,一上来就是各种函数的介绍,适合当作字典,不懂时就去翻看一下。

做纯Linux应用的入门,看这2本书就可以了,不需要学习我们的视频。我们的侧重于“嵌入式Linux”。


在Linux系统中,一切都是“文件”:普通文件、驱动程序、网络通信等等。所有的操作,都是通过“文件IO”来操作的。所以,很有必要掌握文件操作的常用接口。


4.1 文件从哪来?

1670752908774.jpg


4.2 怎么访问文件?


4.2.1 通用的IO模型:open/read/write/lseek/close


使用GIT下载所有源码后,本节源码位于如下目录:

01_all_series_quickstart

04_嵌入式Linux应用开发基础知识\source\06_fileio\copy.c


copy.c源码如下:

01
02 #include <sys/types.h>
03 #include <sys/stat.h>
04 #include <fcntl.h>
05 #include <unistd.h>
06 #include <stdio.h>
07
08 /*
09  * ./copy 1.txt 2.txt
10  * argc    = 3
11  * argv[0] = "./copy"
12  * argv[1] = "1.txt"
13  * argv[2] = "2.txt"
14  */
15 int main(int argc, char **argv)
16 {
17      int fd_old, fd_new;
18      char buf[1024];
19      int len;
20
21      /* 1. 判断参数 */
22      if (argc != 3)
23      {
24              printf("Usage: %s <old-file> <new-file>\n", argv[0]);
25              return -1;
26      }
27
28      /* 2. 打开老文件 */
29      fd_old = open(argv[1], O_RDONLY);
30      if (fd_old == -1)
31      {
32              printf("can not open file %s\n", argv[1]);
33              return -1;
34      }
35
36      /* 3. 创建新文件 */
37      fd_new = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
38      if (fd_new == -1)
39      {
40              printf("can not creat file %s\n", argv[2]);
41              return -1;
42      }
43
44      /* 4. 循环: 读老文件-写新文件 */
45      while ((len = read(fd_old, buf, 1024)) > 0)
46      {
47              if (write(fd_new, buf, len) != len)
48              {
49                      printf("can not write %s\n", argv[2]);
50                      return -1;
51              }
52      }
53
54      /* 5. 关闭文件 */
55      close(fd_old);
56      close(fd_new);
57
58      return 0;
59 }
60


本节源码完全可以在Ubuntu上测试,跟在ARM板上没什么不同。

执行以下命令编译、运行:

$ gcc -o copy copy.c
$ ./copy  copy.c new.c


4.2.2 不是通用的函数:ioctl/mmap


使用GIT下载所有源码后,本节源码位于如下目录:

01_all_series_quickstart

04_嵌入式Linux应用开发基础知识\source\06_fileio\copy_mmap.c


在Linux中,还可以把一个文件的所有内容映射到内存,然后直接读写内存即可读写文件。


copy_mmap.c源码如下:

01
02 #include <sys/types.h>
03 #include <sys/stat.h>
04 #include <fcntl.h>
05 #include <unistd.h>
06 #include <stdio.h>
07 #include <sys/mman.h>
08
09 /*
10  * ./copy 1.txt 2.txt
11  * argc    = 3
12  * argv[0] = "./copy"
13  * argv[1] = "1.txt"
14  * argv[2] = "2.txt"
15  */
16 int main(int argc, char **argv)
17 {
18      int fd_old, fd_new;
19      struct stat stat;
20      char *buf;
21
22      /* 1. 判断参数 */
23      if (argc != 3)
24      {
25              printf("Usage: %s <old-file> <new-file>\n", argv[0]);
26              return -1;
27      }
28
29      /* 2. 打开老文件 */
30      fd_old = open(argv[1], O_RDONLY);
31      if (fd_old == -1)
32      {
33              printf("can not open file %s\n", argv[1]);
34              return -1;
35      }
36
37      /* 3. 确定老文件的大小 */
38      if (fstat(fd_old, &stat) == -1)
39      {
40              printf("can not get stat of file %s\n", argv[1]);
41              return -1;
42      }
43
44      /* 4. 映射老文件 */
45      buf = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd_old, 0);
46      if (buf == MAP_FAILED)
47      {
48              printf("can not mmap file %s\n", argv[1]);
49              return -1;
50      }
51
52      /* 5. 创建新文件 */
53      fd_new = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
54      if (fd_new == -1)
55      {
56              printf("can not creat file %s\n", argv[2]);
57              return -1;
58      }
59
60      /* 6. 写新文件 */
61      if (write(fd_new, buf, stat.st_size) != stat.st_size)
62      {
63              printf("can not write %s\n", argv[2]);
64              return -1;
65      }
66
67      /* 5. 关闭文件 */
68      close(fd_old);
69      close(fd_new);
70
71      return 0;
72 }
73


本节源码完全可以在Ubuntu上测试,跟在ARM板上没什么不同。

执行以下命令编译、运行:

$ gcc -o copy_mmap copy_mmap.c
$ ./copy_mmap  copy_mmap.c  new2.c


4.3 怎么知道这些函数的用法?


Linux下有3大帮助方法:help、man、info。

想查看某个命令的用法时,比如查看ls命令的用法,可以执行:

ls  --help


help只能用于查看某个命令的用法,而man手册既可以查看命令的用法,还可以查看函数的详细介绍等等。它含有9大分类,如下:

1   Executable programs or shell commands       // 命令
2   System calls (functions provided by the kernel)  // 系统调用,比如 man 2 open
3   Library calls (functions within program libraries)  // 函数库调用
4   Special files (usually found in /dev)             // 特殊文件, 比如 man 4 tty 
5   File formats and conventions eg /etc/passwd  // 文件格式和约定, 比如man 5 passwd
6   Games  // 游戏
7   Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7) //杂项
8   System administration commands (usually only for root) // 系统管理命令
9   Kernel routines [Non standard]  // 内核例程


比如想查看open函数的用法时,可以直接执行“man open”,发现这不是想要内容时再执行“man 2 open”。

在man命令中可以及时按“h”查看帮助信息了解快捷键。常用的快捷键是:


f  往前翻一页

b  往后翻一页

/patten 往前搜

?patten 往后搜


就内容来说,info手册比man手册编写得要更全面,但man手册使用起来更容易些。

以书来形容info手册和man手册的话,info手册相当于一章,里面含有若干节,阅读时你需要掌握如果从这一节跳到下一节;而man手册只相当于一节,阅读起来当然更容易。

就个人而言,我很少使用info命令。

可以直接执行“info”命令后,输入“H”查看它的快捷键,在info手册中,某一节被称为“node”,常用的快捷键如下:

Up          Move up one line.
Down        Move down one line.
PgUp        Scroll backward one screenful.
PgDn        Scroll forward one screenful.
Home        Go to the beginning of this node.
End         Go to the end of this node.
TAB         Skip to the next hypertext link.
RET         Follow the hypertext link under the cursor.
l           Go back to the last node seen in this window.
[           Go to the previous node in the document.
]           Go to the next node in the document.
p           Go to the previous node on this level.
n           Go to the next node on this level.
u           Go up one level.
t           Go to the top node of this document.
d           Go to the main 'directory' node.


4.4 系统调用函数怎么进入内核?


1670753030823.jpg


4.5 内核的sys_open、sys_read会做什么?

1670753039340.jpg

相关文章
|
11月前
|
移动开发 前端开发 Android开发
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
1887 12
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
11月前
|
移动开发 JavaScript 应用服务中间件
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
1207 5
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
11月前
|
移动开发 Rust JavaScript
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
1266 4
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
存储 缓存 5G
鸿蒙 HarmonyOS NEXT端云一体化开发-云存储篇
本文介绍用户登录后获取昵称、头像的方法,包括通过云端API和AppStorage两种方式,并实现上传头像至云存储及更新用户信息。同时解决图片缓存问题,添加上传进度提示,支持自动登录判断,提升用户体验。
483 1
|
存储 负载均衡 数据库
鸿蒙 HarmonyOS NEXT端云一体化开发-云函数篇
本文介绍基于华为AGC的端云一体化开发流程,涵盖项目创建、云函数开通、应用配置及DevEco集成。重点讲解云函数的编写、部署、调用与传参,并涉及环境变量设置、负载均衡、重试机制与熔断策略等高阶特性,助力开发者高效构建稳定云端服务。
1029 1
鸿蒙 HarmonyOS NEXT端云一体化开发-云函数篇
|
存储 JSON 数据建模
鸿蒙 HarmonyOS NEXT端云一体化开发-云数据库篇
云数据库采用存储区、对象类型、对象三级结构,支持灵活的数据建模与权限管理,可通过AGC平台或本地项目初始化,实现数据的增删改查及端侧高效调用。
644 1
|
存储 开发者 容器
鸿蒙 HarmonyOS NEXT星河版APP应用开发-ArkTS面向对象及组件化UI开发使用实例
本文介绍了ArkTS语言中的Class类、泛型、接口、模块化、自定义组件及状态管理等核心概念,并结合代码示例讲解了对象属性、构造方法、继承、静态成员、访问修饰符等内容,同时涵盖了路由管理、生命周期和Stage模型等应用开发关键知识点。
790 1
鸿蒙 HarmonyOS NEXT星河版APP应用开发-ArkTS面向对象及组件化UI开发使用实例
鸿蒙 HarmonyOS NEXT星河版APP应用开发-阶段三
本文介绍了UI开发中的样式复用与组件构建技术,涵盖@Extend、@Styles和@Builder的使用方法,并通过Swiper轮播、Scroll滚动、Tabs导航等常用组件实现典型界面效果,结合生肖抽卡、小米轮播、回顶按钮等案例,展示实际应用技巧。
284 1
|
11月前
|
移动开发 Android开发
【03】建立隐私关于等相关页面和内容-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【03】建立隐私关于等相关页面和内容-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
509 0
|
12月前
|
传感器 监控 安全
HarmonyOS NEXT 5.0 的星闪(NearLink)开发应用案例
V哥分享HarmonyOS NEXT 5.0星闪开发实战,涵盖智能车钥匙无感解锁与工业传感器监控。低延迟、高可靠,代码完整,速来学习!
1284 0