文件IO编程

文章目录

    • 文件描述符
    • 相关系统调用
    • 文件有关的系统调用
      • 文件操作函数--creat函数
      • 文件操作函数--open函数
      • 文件操作函数--read函数
      • 文件操作函数--write函数
      • 文件操作函数--close函数
      • 文件操作函数--lseek函数
      • 缓冲区的大小对性能的影响
    • 实验:调用系统函数,实现文件的复制功能

文件描述符

对于内核而言,所有打开文件都由文件描述符引用

  • 文件描述符是一个非负整数
  • 打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。

当读,写一个文件时,用open或creat返回的文件描述符标识该文件,然后将其作为参数传送给read或write.

  • 按照惯例,linux shell使文件描述符0与进程的标准输入相结合,文件描述符1标准输出相结合,文件描述符2与标准出错输出相结合。
  • 文件描述符的本质是一个非负整数,当打开一个文件时,该整数由系统来分配。文件描述符的范围是0-OPEN_MAX 早期的UNIX版本OPEN_MAX=19,即允许每个进程同时打开20个文件,现在很多系统则将其增加至1024.

  • 静态文件
    • 未打开时,存放在块设备中的文件系统中的文件

  • 动态文件
    • 当打开文件时,Linux内核会在进程中建立一个该文件的数据结构,记录该文件已被打开,同时申请一段内存空间,再将静态文件的内容从块设备中读取到内存中特定的地址管理存放

    • 当关闭动态文件时,close内部内核将内存中的动态文件更新至静态文件。

相关系统调用

  • 系统调用是指操作系统提供给用户程序调用的一组“特殊”接口,用户程序可以通过这组“特殊”接口来获得操作系统内核提供的服务。

    • 例如用户可以通过进程控制相关的系统调用创建进程实现进程调度进程管理等。
  • 为什么用户程序不能直接访问系统内核提供的服务呢?
    为了更好地保护内核空间,将程序的运行空间分为内核空间用户空间(内核态和用户态)。

  • 用户进程在通常情况下不允许访问内核数据,也无法使用内核函数,它们只能在用户空间操作用户数据,调用用户空间的函数。

  • 在有些情况下,用户空间的进程需要获得一定的系统服务(调用内核空间程序),这时操作系统就必须利用系统提供给用户的“特殊接口”——系统调用规定用户进程进入内核空间的具体位置

  • 进行系统调用时,程序运行空间需要从用户空间进入内核空间,处理完后再返回到用户空间。

  • 系统调用按照按照功能逻辑可分为:

    • 进程控制
    • 进程间通信
    • 文件系统控制
    • 系统控制
    • 存储管理
    • 网络管理
    • socket控制
    • 用户管理

    系统调用并不是直接与程序员进行交互的,它仅仅是一个通过软中断机制向内核提交请求,以获取内核服务的接口。
    在实际使用中程序员调用的通常是用户编程接口——API
    系统命令相对API更高了一层,它实际上一个可执行程序,它的内部引用了用户编程接口(API)来实现相应的功能。
    在这里插入图片描述

文件有关的系统调用

  • creat
  • open
  • read
  • write
  • lseek
  • close
  • perror
#include <fcntl.h>
#include <unistd.h>int fd = creat(char *filename, mode_t mode)
int  fd = open(char *name, int how)
ssize_t numread = read(int fd, void *buf, size_t qty)
ssize_t result = write(int fd, void *buf, size_t amt)
off_t oldpos = lseek(int fd, off_t dist, int base)
int resule = close(int fd)

文件操作函数–creat函数

在这里插入图片描述

  • creat告诉内核创建一个名为filename的文件,如果这个文件不存在,就创建它,如果已存在,就把它的内容清空,把文件的长度设为0

在这里插入图片描述

  • 如果内核成功地创建了文件,文件的许可权限将被设置为由mode指定的值。
    如:fd = creat(“test”,0644);
    名为test的文件权限被设为-rw-r--r--

文件操作函数–open函数

在这里插入图片描述

  • O_RDONLY, O_WRONLY, O_RDWR分别对应:只读、只写、可读可写
  • 在这里插入图片描述

文件操作函数–read函数

在这里插入图片描述

  • 从文件描述符fd所指定的文件中读取qty个字节到buf所指向的缓冲区中,返回值为实际读取字节数
    • 1.如read成功,则返回读到的字节数。如已到达文件的尾端,则返回0。
    • 2.有多种情况可使实际读到的字节数少于要求读字节数:
      • 读普通文件时,在读到要求字节数之前已到达了文件尾端。例如,若在到达文件尾端之前还有30个字节,而要求读100个字节,则read返回30,下一次再调用read时,它将返回0 (文件尾端)。
      • 当从终端设备读时,通常一次最多读一行
      • 当从网络读时,网络中的缓冲机构可能造成返回值小于所要求读的字节数。
      • 某些面向记录的设备,例如磁带,一次最多返回一个记录。

文件操作函数–write函数

在这里插入图片描述

  • 把amt个字节从buf指向的缓冲区中写到文件描述符fd所指向的文件中,返回值为实际写入的字节数

文件操作函数–close函数

在这里插入图片描述

  • 不需要再对文件进行读写操作时,就要把文件关闭。
  • close会关闭进程和文件fd之间的连接。

文件操作函数–lseek函数

在这里插入图片描述

  • off_t oldpos = lseek(int fd, off_t dist, int base)
    offset可取负值,表示向前移动。
    如:lseek(fd, -5, SEEK_CUR)
    下述调用可将文件指针相对当前位置向前移动5个字节

缓冲区的大小对性能的影响

在这里插入图片描述

实验:调用系统函数,实现文件的复制功能

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>//用法:cp /etc/passwd /root/passwdmain(int argc, char *argv[])
{int read_fd, write_fd;unsigned char buf[128];int num_read;int write_result;//判断用户输入的字串是否为两个if(argc != 3){printf("Usage Error\n");exit(1);}	write_fd = creat(argv[2], 0644);if(write_fd == -1){printf('create file error!\n');exit(1);}printf("write_fd=%d\n",write_fd);read_fd = open(argv[1],O_RDONLY);	if(read_fd == -1){printf('open file error!\n');exit(1);}printf("read_fd=%d\n",read_fd);int x=0;while(1){num_read = read(read_fd, buf, 128);if(num_read==0){printf("all successful finished!\n");break;}if(num_read==-1){printf("read error!\n");break;}printf("num_read=%d\n",num_read);write_result = write(write_fd, buf, sizeof(buf));buf[0]='\0';printf("write_result=%d\n",write_result);}close(read_fd);close(write_fd);
}
  • 具体思路如下:

    • 1.实现复制第一步,我们需要打开我们要复制的文件,并获取其中的内容:
      • (1)因此我们调用int fd=open(charname,int how)来打开文件
        (2)再根据fd,使用read函数读取文件内容:read(int fd,void
        buf,size_t num);
        (3)读取的内容我们读取在了buf字符数组中。
    • 2.实现复制第二步,获取数据后我们要写入要复制到的文件中,而复制到的目标文件我们需要先创建,然后再写入数据:
      • (1)创建文件:creat(char*filename,mode_t mode);
      • (2)写入文件:write(int fd,void*buf,size_t amt);
    • 3.由于我们不知道要复制的文件中有多少个字节,因此我们可以加一个循环,由read函数系统调用后若返回0,代表读取完毕,此时我们就可以退出循环了。
  • 实验运行结果:
    我尝试将/etc/fstab文件copy到当前目录下来,并查看copy过来的文件,成功复制了过来,实验截图如下:
    在这里插入图片描述

    为再次确认其复制功能,我将/etc/passwd复制到wyl的家目录下,并查看复制过来的文件看是否正确。实验截图如下:
    在这里插入图片描述
    在这里插入图片描述

  • 我们发现内容成功复制!接下来我们对结果进行分析:

  • 在这里插入图片描述由上图我们发现最后复制的passwd文件发现了一个问题,对比两个文件发现行数不同,发现复制的文件比原来的文件多了以下数据:

nager:/var/lib/gdm3:/bin/false
wyl:x:1000:1000:Ubuntu18.04,,,:/home/wyl:/bin/bash
sshd:x:122:65534::/run/ssh

而fstab却不会出现此问题。

我总结推测这是因为当我们运行这个程序的时候,会创建一些系统用户来执行,会被记录在/etc/passwd中,而程序结束后,此记录又会消失,所以出现了行数不同,并多出了上方数据。

以上内容仅供参考,如有不对,欢迎指正!谢谢

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

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

相关文章

STM32 WDG看门狗

在大型项目中&#xff0c;BUG根本无法避免&#xff0c;因为可能的状态太多了&#xff0c;总有那么意想不到的情况发生&#xff0c; 所以&#xff0c;对于程序员&#xff0c;第一要要丰富的经验&#xff0c;避免一些常见的bug&#xff0c; 第二&#xff0c;程序要经常迭代&#…

集成学习(Ensembling Learning)

0. 来源 概念比较全&#xff0c;可以作为目录&#xff0c;前置知识讲得好&#xff0c;其他一般。 01.内容简介_哔哩哔哩_bilibili01.内容简介是集成学习&#xff1a;XGBoost, lightGBM的第1集视频&#xff0c;该合集共计19集&#xff0c;视频收藏或关注UP主&#xff0c;及时了…

【数据结构】排序算法系列——序言(附源码+图解)

作为基础算法的中流砥柱部分&#xff0c;排序算法一直都是计算机学习者们不可忽略的一部分。而其中的算法思想也蕴含着许多在今后的算法学习甚至是整个计算机技术的学习之中仍然熠熠生辉的算法思想&#xff0c;它们引领着我们不断探索算法的奥秘之处。所以&#xff0c;学习排序…

简单聊聊bait文件

场景&#xff1a;业务同事发现某云主机部署了企业主机安全&#xff0c;在该主机上发现了一个诱饵文件&#xff0c;显示注意&#xff1a;此文件是诱饵文件&#xff0c;用于防止重要文件被病毒加密。请勿修改或删除此文件。 解决方法&#xff1a;联系企业主机安全运维同事发现&am…

信号保存和处理

把上一篇回顾一下吧&#xff1a;共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间&#xff0c;这些进程间数据传递不再涉及到内核&#xff0c;进程不再通过执行进入内核的系统调用来传递彼此的数据 共享内存的数据结构&#xff1a; struct shmid_ds {…

QT实现TCP/UDP通信

服务器端&#xff1a; 客户端&#xff1a; 服务器&#xff1a; widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> #include <QTcpSocket> #include <QList> #include <QMessageBox> #include <QDebug&…

point transformer v3复现及核心代码详解

point transformer v3复现及核心代码详解 1. 复现1.1 复现1.2 数据预处理1.3 跑通 2. 核心代码详解2.1 读取数据2.2 dataloder2.3 模型读取数据的逻辑2.4 forward2.4.1 Point2.4.2 backbone2.4.2.1 point.serialization2.4.2.2 稀疏化2.4.2.3 embedding2.4.2.4 encoder 1. 复现…

Emlog程序屏蔽用户IP拉黑名单插件

插件介绍 在很多时候我们需要得到用户的真实IP地址&#xff0c;例如&#xff0c;日志记录&#xff0c;地理定位&#xff0c;将用户信息&#xff0c;网站数据分析等,其实获取IP地址很简单&#xff0c;感兴趣的可以参考一下。 今天给大家带来舍力写的emlog插件&#xff1a;屏蔽…

wakenet尾迹

1、数据集介绍SWIM_Dataset_1.0.0 1.1标注文件介绍 标注文件介绍&#xff0c; 第一种&#xff1a;角度和框的坐标 <annotation><folder>Positive</folder><filename>00001</filename>文件名字<format>jpg</format>图片后缀<s…

自掘坟墓?开源正在卷爆程序员!

前端训练营&#xff1a;1v1私教&#xff0c;终身辅导计划&#xff0c;帮你拿到满意的 offer。 已帮助数百位同学拿到了中大厂 offer Hello&#xff0c;大家好&#xff0c;我是 Sunday。 今天这篇文章其实我想了好久&#xff0c;因为这并不是一个 和光同尘 的话题&#xff0c;它…

第143天:内网安全-权限维持自启动映像劫持粘滞键辅助屏保后门WinLogon

案例一&#xff1a; 权限维持-域环境&单机版-自启动 自启动路径加载 路径地址 C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\StartMenu\Programs\Startup\ ##英文C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\开始菜单\程序\启动\ ##中文…

OpenHarmony鸿蒙( Beta5.0)智能窗户通风设备开发详解

鸿蒙开发往期必看&#xff1a; 一分钟了解”纯血版&#xff01;鸿蒙HarmonyOS Next应用开发&#xff01; “非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线&#xff01;&#xff08;从零基础入门到精通&#xff09; “一杯冰美式的时间” 了解鸿蒙HarmonyOS Next应用开发路…

如何逆转Instagram账号流量减少?实用技巧分享

Instagram作为全球十大社媒之一&#xff0c;不仅是个人分享生活的平台&#xff0c;还是跨境卖家进行宣传推广和客户开发的关键工具。在运营Instagram的过程中&#xff0c;稍有不慎就容易出现账号被限流的情况&#xff0c;对于账号状态和运营工作的进行都十分不利。 一、如何判断…

isis与ospf高级属性

文章目录 前言一、基础配置(配置各设备的IP地址)二、配置各设备的ospf与isis三、检查ospf与isis邻居是否建立成功1.实现快速重路由2.流量过滤方法3.引入默认路由4.配置等价路由 前言 在下面实验中&#xff0c;蓝色区域运行ospf&#xff0c;为了控制ospf的lsdb数量&#xff0c;…

vue页面使用自定义字体

一、准备好字体文件 一般字体问价格式为 .tff&#xff0c;可以去包图网等等网站去下载&#xff0c;好看的太多了&#xff01;&#xff01;&#xff01; 下载下来就是单个的 .tff文件&#xff0c;下载下来后可以进行重命名&#xff0c;但是不要改变他的后缀名&#xff0c;我把他…

【c++】类和对象详解

✅博客主页:爆打维c-CSDN博客​​​​​​ &#x1f43e; &#x1f539;分享c语言知识及代码 来都来了! 点个赞给博主个支持再走吧~&#xff01; 一.类的定义 &#xff08;1&#xff09;类定义格式 class为类定义的关键字&#xff0c;定义一个类格式如下: class 类名{//代码…

turtle.circle() 函数绘制弧形规律助记图 ← Python

【Python 之 turtle.circle() 函数定义】 定义&#xff1a;turtle.circle(radius, extent)作用&#xff1a;根据半径 radius 绘制 extent 角度的弧形参数&#xff1a;radius &#xff1a;弧形半径当 radius 值为正数时&#xff0c;圆心在当前位置/小海龟左侧。当 radius 值为负…

9月美联储决策前哨战——美国CPI数据来袭

随着本周关键CPI数据的即将发布&#xff0c;市场正翘首以待&#xff0c;这将是美联储在9月17日至18日议息会议前获取的最后一块重要经济拼图。鉴于美联储官员已进入传统的政策静默期&#xff0c;8月份的CPI报告无疑将成为交易员们评估未来货币政策走向的重要标尺。 欧洲央行降…

[000-01-002].第03节:Git基础命令

我的博客大纲 我的GIT学习大纲 1、Git的常用命令 2、Git操作步骤&#xff1a; 2.1.操作Git第一步&#xff1a;设置全局的用户签名 1.设置用户名&#xff1a; 格式&#xff1a;git config --global user.name 用户名命令&#xff1a;git config --global user.name root 2.设置…

Taro + Vue 的 CSS Module 解决方案

一、开启模块化配置 Taro 中内置了 CSS Modules 的支持&#xff0c;但默认是关闭的。如果需要开启使用&#xff0c;请先在编译配置中添加如下配置&#xff1a; weapp: {module: {postcss: {// css modules 功能开关与相关配置cssModules: {enable: true, // 默认为 false&…