嵌入式Linux入门-Linux文件IO讲解并实现copy程序

news/2024/5/18 14:33:35/文章来源:https://blog.csdn.net/freestep96/article/details/126645277

嵌入式Linux入门学习教程汇总:嵌入式Linux教程—裸机、应用、驱动完整教程目录

在Linux系统中,一切都是“文件”:普通文件、驱动程序、网络通信等等。所有的操作,都是通过“文件IO”来操作的。

IO就是input和output,文件IO就是文件的读写。文件没有打开时是存放在块设备中的文件系统里的,这样的文件叫做静态文件

操作一个文件一般是先打开(open)一个文件,得到这个文件的文件描述符,然后对文件进行读写(read/write)或其他操作,最后关闭(close)文件。

当我们open一个文件的时候,内核在进程中建立一个打开文件的数据结构来记录我们打开的文件,然后在内存中申请一段内存,将静态文件的内容读取到内存中特定地址管理存放,此时内存中的就是动态文件

之后的读写等操作都是针对这份内存中的动态文件,当close关闭动态文件后,内核将内存中动态文件的内容同步更新到静态文件中。

文件描述符的概念:一个程序打开一个文件就会得到一个文件描述符(整数),该数字用来区分一个程序打开的多个文件。文件描述符的作用域就是当前进程。

1.Linux七种文件类型

普通文件类型
Linux中最多的一种文件类型, 包括 纯文本文件(ASCII);二进制文件(binary);数据格式的文件(data);各种压缩文件.第一个属性为 [-]

目录文件
就是目录, 能用cd 命令进入的。第一个属性为 [d],例如 [drwxrwxrwx]

块设备文件
块设备文件 : 就是存储数据以供系统存取的接口设备,简单而言就是硬盘。例如一号硬盘的代码是 /dev/hda1等文件。第一个属性为 [b]

字符设备
字符设备文件:即串行端口的接口设备,例如键盘、鼠标等等。第一个属性为 [c]

套接字文件
这类文件通常用在网络数据连接。可以启动一个程序来监听客户端的要求,客户端就可以通过套接字来进行数据通信。第一个属性为 [s],最常在 /var/run目录中看到这种文件类型

管道文件
FIFO也是一种特殊的文件类型,它主要的目的是,解决多个程序同时存取一个文件所造成的错误。FIFO是first-in-first-out(先进先出)的缩写。第一个属性为 [p]

链接文件
类似Windows下面的快捷方式。第一个属性为 [l],例如 [lrwxrwxrwx]

Linux中文件扩展名
windows里通过扩展名来区分文件类型的。linux里文件扩展名和文件类型没有关系。但为了容易区分和兼容用户使用windows的习惯,还是会用扩展名来表示文件类型。举例如下:
● 源码.tar、.tar.gz、.tgz、.zip、.tar.bz表示压缩文件,创建命令一般为tar,gzip,zip等。
● .sh表示shell脚本文件,通过shell语言开发的程序。
● .pl表示perl语言文件,通过perl语言开发的程序。
● .py表示python语言文件,通过python语言开发的程序。
● .html、.htm、.php、.jsp、.do表示网页语言的文件。
● .conf表示系统服务的配置文件。
● .rpm表示rpm安装包文件。
 

2.Linux常用文件IO接口(API)

2.1 open :open and possibly create a file·

#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);

返回值:open函数的返回值如果操作成功,它将返回一个文件描述符,如果操作失败,它将返回-1。

pathname:在open函数中第一个参数pathname是指向想要打开的文件路径名,或者文件名。我们需要注意的是,这个路径名是绝对路径名。文件名则是在当前路径下的。

flags:flags参数表示打开文件所采用的操作,我们需要注意的是:必须指定以下三个常量的一种,且只允许指定一个

  • O_RDONLY:只读模式
  • O_WRONLY:只写模式
  • O_RDWR:可读可写

以下的常量是选用的,这些选项是用来和上面的必选项进行按位或起来作为flags参数。

  • O_APPEND 表示追加,如果原来文件里面有内容,则这次写入会写在文件的最末尾。
  • O_CREAT 表示如果指定文件不存在,则创建这个文件
  • O_EXCL 表示如果要创建的文件已存在,则出错,同时返回 -1,并且修改 errno 的值。
  • O_TRUNC 表示截断,如果文件存在,并且以只写、读写方式打开,则将其长度截断为0。
  • O_NOCTTY 如果路径名指向终端设备,不要把这个设备用作控制终端。
  • O_NONBLOCK 如果路径名指向 FIFO/块文件/字符文件,则把文件的打开和后继 I/O设置为非阻塞模式(nonblocking mode)

以下三个常量同样是选用的,它们用于同步输入输出

  • O_DSYNC 等待物理 I/O 结束后再 write。在不影响读取新写入的数据的前提下,不等待文件属性更新。
  • O_RSYNC read 等待所有写入同一区域的写操作完成后再进行
  • O_SYNC 等待物理 I/O 结束后再 write,包括更新文件属性的 I/Omode:

mode:表示设置文件访问权限的初始值,和用户掩码umask有关,比如0644表示-rw-r–r–,也可以用S_IRUSR、S_IWUSR等宏定义按位或起来表示,详见open(2)的Man Page。

文件权限由open的mode参数和当前进程的umask掩码共同决定。

第三个参数是在第二个参数中有O_CREAT时才作用,如果没有,则第三个参数可以忽略

mode 的 具体 参数:

S_IRWXU
00700 允许 文件 的 属主 读 , 写 和 执行 文件
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 允许 其他 用户 执行 文件

2.2 read : read from a file descriptor

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

返回值:读到文件末尾返回0;正常则返回读到的字节数;当有错误发生时则返回-1,错误代码存入errno中。

fd:文件描述符,buf:读取数据存放位置,count:需要读取的数据大小

2.3 write : write to a file descriptor

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

返回值:如果顺利write()会返回实际写入的字节数(len)。当有错误发生时则返回-1,错误代码存入errno中。

fd:文件描述符,buf:待写入数据,count:待写入数据大小

2.4 close :close a file descriptor

#include <unistd.h>
int close(int fd);

2.5 lseek: reposition read/write file offset

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);

(1)文件指针:当我们要对一个文件进行读写时,一定需要先打开文件,所以我们读写的所有文件都是动态文件。动态文件在内存中的形态就是文件流的形式。

(2)文件流很长,里面有很多个字节。那我们当前正在操作的是哪个位置?GUI模式下的软件用光标来识别这个当前正在操作的位置,这个给人看的

(3)在动态文件中,通过文件指针来表征这个正在操作的位置。所谓文件指针,就是我们文件管理表这个结构体里面的一个指针。所以文件指针其实是vnode中的一个元素。这个指针表示当前我们正在操作文件流的那个位置。这个指针不能被直接访问,Linux系统用lseek函数来访问这个文件指针。

(4)当我们打开一个空文件时,默认情况下文件指针指向文件流的开始。所以这个时候去write时写入就是从文件开头开始的。write和read函数本身自带移动文件指针的功能,所以当我write了n个字节后,文件指针会自动向后移动n位。如果需要人为的随意更改文件指针,那就只能通过lseek函数了

(5)read和write函数都是从当前文件指针处开始操作的,所以当我们用lseek显示的将文件指针移动后,那么再去read/write时就是从移动过后的位置开始的。

返回值:成功返回当前位置到开始的长度,失败返回-1并设置errno

fd:文件描述符,offset:偏移量

whence:位置
SEEK_SET:The offset is set to offset bytes. offset为0时表示文件开始位置
SEEK_CUR:The offset is set to its current location plus offset bytes. offset为0时表示当前位置
SEEK_END:The offset is set to the size of the file plus offset bytes. offset为0时表示结尾位置
 

lseek返回的是偏移量,所以如下其实就是返回文件长度

ret = lseek(fd,0,SEEK_END);

3. 应用层io进入内核发生了什么

这里不作深入讲解,只需知道基本内容:

Linux应用程序调用的open()、read()等函数时,触发内部(32位cpu:swi,64位cpu:svc)指令,触发异常(在触发异常时还会传入不同的参数给内核,根据参数来分辨),然后调用内核中对应的sys_open()、sys_read()等函数。

会分辨目标文件到底是七种文件中的哪一种,例如普通文件,就去调用文件系统对应的驱动代码,读取块设备上的文件。例如目标文件是我们想驱动的字符设备文件,就会去调用们自己写的字符设备驱动程序中的read(),write()等。

4.小练习;自己写个copy复制文件

挺简单的,直接上代码了

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char **argv)
{int src;int dst;int buf[1024];int read_len,write_len;if(argc!=3){printf("Input Error\n");return -1;}src=open(argv[1],O_RDONLY);if(src<=0){printf("open %s error\n",argv[1]);return -1;}dst=open(argv[2],O_RDWR|O_CREAT,S_IRWXU);if(dst<=0){printf("open %s error\n",argv[2]);return -1;}while(1){read_len=read(src,buf,1024);if(read_len<0){printf("read %s error\n",argv[1]);return -1;}if(read_len>0){write_len=write(dst,buf,read_len);if(write_len<0){printf("read %s error\n",argv[1]);return -1;}}elsebreak;}close(src);close(dst);return 0;
}

把源代码编译

gcc -o copy copy.c

使用vi命令随便写点东西

vi test1

 使用我们自己的copy命令

./copy test1 test2

成功。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_4381.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[PostgreSQL的 SPI_接口函数]

Server Programming Interface&#xff08;SPI&#xff09;是PostgreSQL内核中的一个模块&#xff0c;这个模块让内核开发者可以在C函数中执行SQL语句&#xff0c;并具备管理事务的能力。通过它我们可以用C语言去调用数据库里的各种SQL。 这个SPI_比较便利的一点在于&#xff…

如何使用 Bootstrap 处理 CSS

如何使用 Bootstrap 处理 CSS 大家好!如果您像我一样开始使用 CSS 编码并使用它进行任何大型项目,那么您肯定会因为响应式布局、溢出和选择器特异性而感到数不清的头痛。这就是几周前我决定学习 Bootstrap 的原因,这里是它的文档和主要功能的简短描述,所以你也可以。引导程…

一、Azkaban简明笔记

1、azkaban部署 主要是集群部署安装。 1.1 准备安装包Downloads (azkaban.github.io)1.2 配置MySQL启动mysql mysql -uroot -proot创建azkaban数据库 create database azkaban;创建azkaban用户并赋予权限(可以不设置账号,继续使用root账号) -- 显示相关变量 SHOW VARIABLES …

实体店主最爱的中秋活动方案,直接照搬就能轻松爆单!

中秋将至&#xff0c;传统佳节和营销好时机一起到了&#xff01;利用氛围浓厚的节日进行营销活动&#xff0c;是吸引客户、增粉卖货的最佳手段之一&#xff0c;商户老板们可千万不能错过&#xff01; 但是&#xff0c;活动人人都能做&#xff0c;如何在一片节日促销中脱颖而出&…

JVM详解

1. 源文件 源文件就是我们编写Java代码的文件。文件扩展名为.java 2. 字节码文件 字节码文件是源文件编译后的文件。字节码文件是二进制文件&#xff0c;需要通过特定的工具才能查看。里面存放了源文件编译后的字节码指令。 3. 类加载器 Class Loader Java 程序运行时会由…

USB转GPIO应用方案

概述 沁恒提供的多款USB转接系列芯片均提供GPIO引脚功能&#xff0c;各引脚支持独立的输出输入&#xff0c;GPIO功能的使用需要与计算机端厂商驱动程序和应用软件配合使用。各芯片的默认GPIO引脚状态有所区别&#xff0c;可查阅芯片技术手册或参考方案中附表。 型号 CH344Q …

基于神经网络的图像识别,人工神经网络图像识别

如何通过人工神经网络实现图像识别 。 人工神经网络&#xff08;ArtificialNeuralNetworks&#xff09;&#xff08;简称ANN&#xff09;系统从20世纪40年代末诞生至今仅短短半个多世纪&#xff0c;但由于他具有信息的分布存储、并行处理以及自学习能力等优点&#xff0c;已经…

Jmeter(五) - 从入门到精通 - 测试计划(Test Plan)的元件(详解教程)

一.测试计划&#xff08;Test Plan&#xff09;要素 1.JMeter中一个脚本就是一个测试计划&#xff08;Test Plan&#xff09;&#xff0c;也是一个管理单元。JMeter 的请求模拟与并发数(设置线程数&#xff0c;一个线程代表一个虚拟用户)设置都在脚本文件中一起设置。JMeter 不…

雨夜赶长路,房企必经的三场“价值战事”

今年上半年&#xff0c;地产行业一直在高压下运行。市场周期震荡叠加疫情等因素&#xff0c;为房企的销售、土拍、融资带来不确定性。 下半年以来&#xff0c;虽然不确定性和高压仍在&#xff0c;但市场有望恢复&#xff0c;下行趋势似乎已到拐点。 面对高压&#xff0c;不同…

安装 ZooKeeper 并配置服务

官网 访问官方下载页面安装 # 注意替换一下新的链接 curl -sSLO https://dlcdn.apache.org/zookeeper/zookeeper-3.8.0/apache-zookeeper-3.8.0-bin.tar.gz tar -zxvf apache-zookeeper-3.8.0-bin.tar.gz -C /opt/ cd /opt ln -s zookeeper-3.4.10 ./zookeepercd zookeeper m…

微服务项目:尚融宝(8)(后端接口:积分等级CRUD)

认清现实&#xff0c;放弃幻想&#xff0c;准备斗争 一、积分等级列表接口 1、编写积分等级管理接口 在controller中添加admin包&#xff0c;添加AdminIntegralGradeController类CrossOrigin RestController RequestMapping("/admin/core/integralGrade") public cl…

Mac中无法运行旧版本印象笔记:版本太旧 你的本地印象笔记数据是由新版印象笔记管理

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是「奇点」&#xff0c;江湖人称 singularity。刚工作几年&#xff0c;想和大家一同进步&#x1f91d;&#x1f91d; 一位上进心十足的【Java ToB端大厂…

算法设计与分析作业——递归循环

用循环实现&#xff1a; 1、 求级数 求&#xff1a;1/1!-1/3!1/5!-1/7!…(-1)n1/(2n-1)! #include <bits/stdc.h> using namespace std; int main( ) {int i,n,j,sign1; float s,t1; cin>>n; s1; for(i2;i<n;ii1){t1; /*求阶乘*/for(j1;j<2*i-1;…

(11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】

&#xff08;1&#xff09;工业界推荐系统-小红书推荐场景及内部实践【业务指标、链路、ItemCF】 &#xff08;2&#xff09;工业界推荐系统-小红书推荐场景及内部实践【UserCF、离线特征处理】 &#xff08;3&#xff09;工业界推荐系统-小红书推荐场景及内部实践【矩阵补充、…

推荐10款好用的数据可视化工具,赶紧收藏

写在前面的话&#xff1a;没有十全十美的工具&#xff0c;但是如果确立&#xff08;可视化&#xff09;目标&#xff0c;就能找到合适的工具去实现。 数据分析过程可以分为&#xff1a;确定目标数据、数据采集、数据清洗、数据存储、数据分析、结果可视化及结果支持和决策等步骤…

文字转音频软件哪个好用?这几个方法你值得拥有

不知道你有没有发现一个现象&#xff0c;现在越来越多的人会把自己制作好的视频发布到各个社交平台上&#xff0c;分享自己的日常。有的人还会用自己的声音来做配音旁白&#xff0c;而有的人因为自己声音和视频不搭&#xff0c;会使用配音软件&#xff0c;把文字转换成语音。可…

FRED应用:真实玻片设置

简介 FRED具备通过光学系统模拟光线偏振的能力。光源可以是随机偏振、圆偏振或线偏振。过滤或控制偏振的光学元件&#xff0c;如双折射波片和偏振片&#xff0c;可以准确的模拟。FRED偏振模型中一些简单例子包括吸收二向色性和线栅偏振片&#xff0c;方解石半波片&#xff0…

最近在学日语

对比了一些B站的日语教学视频,觉得这个挺不错: 视频在这里昨天开始学的,50音图平假名全记住了,片假名还有点磕巴。 现在开始学语法了。 【动力这种东西,真是来得莫名奇妙。】手打一遍50音图,练习~ (键盘手打刻意练习了一下,熟练多了。) a i u e o あ ア い イ う…

Magisk如何针对性隐藏Root避免被检测

如果这篇文章对你有帮助,欢迎点赞关注收藏三联,这对我有帮助,谢谢小伙伴们,你们的支持是我认真分享的动力。 关于Magisk有一个有趣的故事,Magisk的作者老吴,国内人,妥妥的大牛,主攻Root领域,目前在Google里卖弄当工程师,在去Google之前,老吴还去苹果公司实习过,就在…

HTML5新特性 day_05(8.11)上传头像、webSocket

一、文件上传经典业务流程 -- 上传头像 在注册业务&#xff0c;填写表单的过程中&#xff0c;需要选择头像&#xff0c;上传头像&#xff0c;填写基本信息&#xff08;用户名、密码等&#xff09;后&#xff0c;点击注册按钮&#xff0c;完成用户注册。当下次登录时需要看到以…