Linux文件系统调用接口

文件=内容+属性

所有对文件的操作就是对 1.文件内容  2.文件属性。

内容是数据,属性也是数据,存储文件,必须既存储内容,也要存储属性。

文件没有被访问时,一般在磁盘中。对文件访问时,由冯诺依曼体系结构知,需要将文件加载到内存中,才能被操作。

加载磁盘上的文件到内存中,是由OS来完成,必然存在许多的文件等待被加载,操作系统需要对这些已经加载文件的管理。管理的方式就是先描述、在组织

描述组织方法

描述:创建文件描述结构体 struct file{属性   文件指针  }

组织:将文件描述的结构体,以某种数据结构链接。对文件的管理,就转化为对结构体的增删查改。

C语言接口

回忆完文件的预备知识后,就来回忆一下C语言的文件操作IO接口

文件操作函数    功能
fopen    打开文件
fclose    关闭文件
fputc    写入一个字符
fgetc    读取一个字符

fputs    写入一个字符串
fgets    读取一个字符串
fprintf    格式化写入数据
fscanf    格式化读取数据
fwrite    向二进制文件写入数据
fread    从二进制文件读取数据
fseek    设置文件指针的位置
ftell    计算当前文件指针相对于起始位置的偏移量
rewind    设置文件指针到文件的起始位置
ferror    判断文件操作过程中是否发生错误
feof    判断文件指针是否读取到文件末尾

fopen()

FILE* fopen(const char* path ,const char* mode)

函数参数为  文件路径  和打开方式

返回参数为文件指针,打开成功返回指针,失败返回NULL

fputs()

int fputs(const char *s ,FILE*stream)

将字符串写入特定流中,成功则返回字符串个数,失败返回-1

fprintf()

int fprintf(FILE*stream ,const char* format ,......)

向某个流中,格式化写入

fopen()的写入方式

文件使用方式    含义    如果指定文件不存在
"r"(只读)    为了输入数据,打开一个已经存在的文本文件    出错
"w"(只写)    为了输出数据,打开一个文本文件            建立一个新的文件
"a"(追加)    向文本文件尾添加数据                               建立一个新的文件
"rb"(只读)    为了输入数据,打开一个二进制文件        出错
"wb"(只写)    为了输出数据,打开一个二进制文件       建立一个新的文件
"ab"(追加)    向一个二进制文件尾添加数据                    出错
"r+"(读写)    为了读和写,打开一个文本文件                 出错
"w+"(读写)    为了读和写,建立一个新的文件               建立一个新的文件
"a+"(读写)    打开一个文件,在文件尾进行读写            建立一个新的文件
"rb+"(读写)    为了读和写打开一个二进制文件              出错
"wb+"(读写)    为了读和写,新建一个新的二进制文件    建立一个新的文件
"ab+"(读写)    打开一个二进制文件,在文件尾进行读和写    建立一个新的文件

部分演示:
1、写"w"形式打开一个文件

效果等同 >

  1 #include<stdio.h>2 #include<unistd.h>3 4 int main()5 {6   FILE* fp=fopen("log.txt","w");7   if(fp==NULL)8   {9     perror("open file");10     return 1;11   }12   const char* msg="hello world";13   int cnt=1;14   while(cnt<=10)15   {16     fprintf(fp,"%s:%d\n",msg,cnt);                                                                          17     cnt++;18   }19   fclose(fp);20   return 0;21 }
~

上述代码以w(只写权限)打开一个文件,在当前路径低下,没有存在log.txt文件,w形式会创建一个名为log.txt的空文件。对文件的操作是写入10条hellow world

编译运行后

会在当前路径底下生成log.txt文件  利用cat重定向,将文件内容打印到显示器上


2、在"a"追加形式打开

效果等同于  >>

将1.的代码做修改,在将”w“修改成a ,在循环体中,打印内容为hellow linux

在第一步的log.txt文件下已存在内容的情况下,在编译运行。

"a"是追加,则不会清空文件,cat重定向到显示器后

三个默认流

Linux下的经典话是“一切皆文件”。

在linux下显示器和键盘也能看作文件。我们在显示器上看到文件内容,实际上就是往"显示器文件"写入文件。电脑获得我们在键盘敲击的字符,实际上就是往"键盘文件"读取了数据。

从刚才我们的回顾,就可以发现既然是从显示器文件中写入数据,那么文件一定是被打开的。


结论


任何进程运行时,都会打开三个输入输出流,即标准输入,标准输出,和标准错误流。

标准输入的默认是键盘。标准输出和错误默认是显示器。

在C语言中的三个默认流,是stdin ,stdout ,stderr 

在C++上也存在三个流,对应cin ,cout ,cerr

系统接口

在我们用的C语言文件接口,一定是封装了系统调用接口!

1、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);

open函数

pathname为要打开或者创建的文件名

如果是pathname给出路径,则在该路径下创建

如果是文件名,则在当前文件所在路径下创建名为pathname的文件

flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“”运算,构成

位图的操作

参数含义
O_RDNOLY只读方式打开 1
O_WRNOLY只写方式打开 2
O_RDWR读写方式打开 3  三者必须指定一种
O_CREAT

文件不存在,就创建文件

O_APPEND追加写
返回值:成功返回新的文件描述符,失败返回-1

对flags的说明  flags是位图的形式  每一个选项的二进制序列只有一个1   在运算中,我们可以通过或运算  open函数内部通过与运算得到每一个选项

举例:

想以读的方式打开文件,在没有文件存在就创建文件  通过 | 运算符

open(pathname,O_RDNOLY | O_CREAT)

下面通过代码验证:创建一个log.txt(不存在) 以只写的方式打开

  1 #include<stdio.h>                                                                                           2 #include<sys/stat.h>3 #include<fcntl.h>4 5 6 int main()7 {8   int fd = open("log.txt",O_WRONLY|O_CREAT);9   if(fd<0)10   {11     perror("open fail");12     return -1;13   }14   printf("fd 是%d\n",fd);15   return 0;16 }

编译运行后,在当前路径下得到log.txt

得到fd 是 3  我们关心fd为什么会是3,而不是0 1  2呢?在下面将会谈到!

谈一下mode参数

mode参数是文件默认权限的16进制

0666代表 u g o 对应所有者 所属组 其它  rwx  011就是6对应 wx权限 

创建文件的时候得到是0664 受到权限掩码的影响,权限掩码是0002 


2、close () 

用于关闭文件 ——fclose就是封装了close

通过查阅man手册,了解close的用法

close()的参数是 fd(open被打开文件的返回值)

成功关闭文件返回0,失败返回-1


3、write()

查阅2号手册

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

fd 是文件描述符

buff表示缓冲区

count字节数

write是将缓冲区count大小的数据写入fd中。

返回值是一个可为负的值,表示实际写入多少字节。

4、read()

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

read与write类似

fd是文件描述符

buff是缓冲区

count是字节数

read是从缓冲区读取count字节大小值到fd中

注意:

读取缓冲区的大小是strlen(s )  需要+1吗?

不需要。如果strlen(s)+1  则再打开log.txt文件时会出现乱码,因为\0是C语言的规定,在文件中没有要求。会被OS译为乱码。

演示

利用snprintf函数将hollow Linux写入缓冲区buff,write函数从buff中读取数据,并写入到log.txt文件

cat重定向到显示器

  1 #include<stdio.h>2 #include<sys/stat.h>3 #include<fcntl.h>4 #include<string.h>5 #include<unistd.h>6 int main()7 {8   umask(0);9   int fd = open("log.txt",O_WRONLY|O_CREAT,0666);10   if(fd<0)11   {12     perror("open fail");13     return -1;14   }15   printf("fd :%d\n",fd);16   const char* s="hellow Linux!";17   int cnt=1;18   while(cnt<=5)19   {20     char buff[128];21     snprintf(buff,sizeof(buff),"msg:%s,cnt:%d\n",s,cnt);                                                    22     write(fd,buff,strlen(buff));23     cnt++;24   }25   close(fd);26   return 0;27 }
~

read的函数用法与write类似,就不做过多介绍。


注意:O_WRONLY|O_CREAY 默认是不会对文件内容清空的,如果需要清空,就要加上O_TRUNC

这时候我们的open调用就非常类似C语言的fopen()


这时,我们就可以猜测C语言文件就是封装了系统调用接口。

OS不信任用户,OS就给用户提供系统调用,程序员通过C语言调用文件接口,必然间接调用系统调用。

读文件本质是将把文件从磁盘加载到内存中,这是冯诺依曼体系规定的。

写文件意味着可能修改文件,必然也要先把文件加载到内存中。

用户不能直接管理硬件,OS是硬件的直接管理者。


回忆文件,内容加属性。

要访问文件必须先把文件加载到内存。OS对文件的管理就是先描述再组织。

C语言必定封装了某种系统调用。

open的pathname是文件名,flag是一个32位的位图,在传参时通过或运算添加。

write和read非常的类似。从缓冲区buff写入/读到 fd对应的文件中。

O_WRNOLY|O_CREAY|O_TRUNC是清空文件的写入。


下面我们还有问题?

FILE是封装了fd吗

fd为什么默认从3开始

Linux下一切皆文件是为什么

重定向是如何理解


在下文将会详细介绍

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

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

相关文章

媒体捕捉-拍照

引言 在项目开发中&#xff0c;从媒体库中选择图片或使用相机拍摄图片是一个极为普遍的需求。通常&#xff0c;我们使用UIImagePickerController来实现单张图片选择或启动相机拍照。整个拍照过程由UIImagePickerController内部实现&#xff0c;无需我们关心细节&#xff0c;只…

【分布式微服务专题】SpringSecurity快速入门

目录 前言阅读对象阅读导航前置知识笔记正文一、Spring Security介绍1.1 什么是Spring Security1.2 它是干什么的1.3 Spring Security和Shiro比较 二、快速开始2.1 用户认证2.1.1 设置用户名2.1.1.1 基于application.yml配置文件2.1.1.2 基于Java Config配置方式 2.1.2 设置加密…

IBM介绍?

IBM&#xff0c;全名国际商业机器公司&#xff08;International Business Machines Corporation&#xff09;&#xff0c;是一家全球知名的美国科技公司。它成立于1911年&#xff0c;总部位于美国纽约州阿蒙克市&#xff08;Armonk&#xff09;&#xff0c;是世界上最大的信息…

一起学Elasticsearch系列-Query DSL

本文已收录至Github&#xff0c;推荐阅读 &#x1f449; Java随想录 微信公众号&#xff1a;Java随想录 文章目录 查询上下文相关度评分&#xff1a;scoreTF/IDF & BM25 源数据&#xff1a;source 源数据过滤全文检索match&#xff1a;匹配包含某个term的子句match_all&…

[Vulnhub靶机] DriftingBlues: 1

[Vulnhub靶机] DriftingBlues: 1靶机渗透思路及方法&#xff08;个人分享&#xff09; 靶机下载地址&#xff1a; https://download.vulnhub.com/driftingblues/driftingblues.ova 靶机地址&#xff1a;192.168.67.20 攻击机地址&#xff1a;192.168.67.3 一、信息收集 1.使…

mysql中按字段1去重,按字段2降序排序

数据举例 sql语句 按字段field4降序排序&#xff0c;按字段field1去重 SELECT tt1.name2,tt1.field1,tt1.field2,tt1.field4 from ( select tt2.name2,tt2.field1,tt2.field2,tt2.field4 from t2 tt2 ORDER BY tt2.field4 DESC ) tt1 GROUP BY tt1.field1执行结果

mysql的索引原理

目录 一、索引采用B树的优势二、为什么不使用其他数据结构2.1、哈希索引2.2平衡二叉树B树 参考 mysql索引采用B树 一、索引采用B树的优势 1可以进行范围查找&#xff0c;通过单向链表解决&#xff08;通过单向链表已经排好序&#xff09;。 2非叶子结点只存储key&#xff0c;不…

vue-vant组件库

组件库&#xff1a;第三方封装好了很多很多的组件&#xff0c;整合到一起就是一个组件库。 官网&#xff1a;Vant 2 - Mobile UI Components built on Vue vant支持vue2&#xff0c;也支持vue3&#xff1b;vant2支持vue2&#xff0c;vant3、vant4支持vue3 分类 vue的组件库…

老胡的周刊(第122期)

老胡的信息周刊[1]&#xff0c;记录这周我看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。 &#x1f3af; 项目 movie-web[2] 开源可自部署的简约在线电影搜…

ThreadLocal 是什么?它的实现原理是什么?

文章目录 ThreadLocal 是什么&#xff1f;它的实现原理是什么&#xff1f; ThreadLocal 是什么&#xff1f;它的实现原理是什么&#xff1f; ThreadLocal 是一种线程隔离机制&#xff0c;它提供了多线程环境下对于共享变量访问的安全性。 在多线程访问共享变量的场景中&#…

Android 跨进程之间通信(IPC)方式之BroadcastReceiver

Android 跨进程之间通信 Android 跨进程之间通信(IPC)方式之BroadcastReceiverAndroid 跨进程之间通信(IPC)方式之ContentProvider 文章目录 Android 跨进程之间通信前言一、关于系统广播二、如何利用BroadcastReceiver跨进程通信1.创建广播接收器2.清单文件中声明注册3.发送广…

论数据资源持有权(下)

四、数据资源持有权&#xff1a;数据流通体系与秩序运行的支柱 现代数字经济背景下的数据要素市场&#xff0c;主要是在动态的流通中实现数据财产价值&#xff0c;在明确数据资源持有权作为构建数据流通中的新型数据财产产权的基石后&#xff0c;就应该充分围绕数据资源持有权…

微信小程序开发系列-11组件间通信02

微信小程序开发系列目录 《微信小程序开发系列-01创建一个最小的小程序项目》 《微信小程序开发系列-02注册小程序》 《微信小程序开发系列-03全局配置中的“window”和“tabBar”》 《微信小程序开发系列-04获取用户图像和昵称》 《微信小程序开发系列-05登录小程序》 《…

【算法】哈希算法和哈希表

一、哈希算法 哈希算法是一种将任意长度的数据&#xff08;也称为“消息”&#xff09;转换为固定长度字符串&#xff08;也称为“哈希值”或简称“哈希”&#xff09;的数学函数或算法。这个固定长度的字符串是由输入数据通过一系列的运算得到的&#xff0c;并且具有一些重要…

算法通关村第二十关-白银挑战图的存储与遍历

大家好我是苏麟, 今天继续聊图 . 与前面的链表、树等相比&#xff0c;图的存储和遍历要复杂非常多 .所以理解就好 , 面试基本不会让写代码的 . 图的类型多、表示方式多&#xff0c;相关算法也很多&#xff0c;实现又过于复杂&#xff0c;多语言实现难度太大了。这些算法一般理…

C语言之scanf浅析

前言&#xff1a; 当有了变量&#xff0c;我们需要给变量输入值就可以使用scanf函数&#xff0c;如果需要将变量的值输出在屏幕上的时候可以使用printf函数&#xff0c;如&#xff1a; #include <stdio.h> int main() {int score 0;printf("请输⼊成绩:");sc…

软件工程总复习笔记

软件工程课程复习提纲 文章目录 软件工程课程复习提纲一、基本知识点1. 软件工程的概念及目标2. 软件危机的概念及典型表现3. 瀑布模型的概念及特点4. 快速原型模型的特点5. 螺旋模型的基本思想6. 软件生命周期的概念及划分为哪几个阶段7. 软件需求的定义8. 常见的软件需求获取…

Java位运算及移位运算

java中能表示整数数据类型的有byte、short、char、int、long&#xff0c;在计算机中占用的空间使用字节描述&#xff0c;1个字节使用8位二进制表示。 数据类型字节数二进制位数表示范围默认值byte18-27 – 27-10char2160 – 216-1\u0000 (代表字符为空 转成int就是0)short216-…

OpenCV-12绘制图像

OpenCV提供了许多绘制图像的API&#xff0c;可以在图像上绘制各种图形&#xff0c;例如直线&#xff0c;矩形&#xff0c;圆&#xff0c;椭圆等图形。 一、画直线 利用API line&#xff08;img, pt1, pt2, color, thickness, lineType, shift&#xff09;可以绘制直线。 其中…

玩转贝启科技BQ3588C开源鸿蒙系统开发板 —— 代码下载(1)

本文主要参考&#xff1a; BQ3588C_代码下载 1. 安装依赖工具 安装命令如下&#xff1a; sudo apt-get update && sudo apt-get install binutils git git-lfs gnupg flexbison gperf build-essential zip curl zlib1g-dev gcc-multilib g-multiliblibc6-dev-i386 l…