Linux-基础IO

news2024/9/20 5:33:30

一、C语言文件IO

1、C库函数介绍

  • 打关文件fopen/fclose:
FILE * fopen(const char* filename, const char* mode);
int fclose (FILE* stream );
  • 文件打开方式:

  • 读写函数fread/fwrite:
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
  • 格式化读写fscanf/fprintf: 
int fscanf( FILE *stream, const char *format [, argument ]... );
int fprintf( FILE *stream, const char *format [, argument ]...);
  • 示例1:输出使用
#include <stdio.h>
#include <string.h>
int main()
{
    const char *msg = "hello fwrite\n";
    fwrite(msg, strlen(msg), 1, stdout);
    printf("hello printf\n");
    fprintf(stdout, "hello fprintf\n");
    return 0;
}
  • 示例2:文件读写
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
    FILE* fp=fopen("cole.txt","w+");//以写读方式打开文件
    if(fp==NULL)
    {
        perror("fopen");
        exit(1);
    }
    char msg[]="linux so easy!\n";
    int len=strlen(msg);
    int cnt=5;
    while(cnt--)
    {
        fwrite(msg,len,1,fp);//写入
    }
    fseek(fp,0,SEEK_SET);//指针回到起始位置
    char buf[128];
    while(1)
    {
        ssize_t s=fread(buf,1,len,fp);
        if(s>0)
        {
            buf[s]=0;//设置结束符
            fwrite(buf,len+1,1,stdout);
        }
        else//读取结束
            break;
    }
    fclose(fp);
    return 0;
}

2、stdin/stdout/stderr

  • 文件原型:
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
  • 概念:
  1. 任何C程序运行都会默认打开三个输入输出流,分别是:stdin, stdout, stderr

  2. 分三个文件流分别对应键盘文件,显示器文件,显示器文件

  • 为什么这里的文件流和外设关联上了:
  1. 对于所有外设硬件来说,其本质对应的操作不外乎是读操作和写操作,对于不同外设也就有不同的读写方式
  2. OS要管理硬件设备无非是先描述再组织,由此将属性以及读写操作构成一个结构体,而文件其本身也是属性加读写操作,这样就由文件结构体同一管理文件(包括外设)
  3. 在C语言中虽然没有多态,但是结构体中可以储存函数指针,初始化结构体时,将属性写入的同时也将对应的读写函数给写入;对于外设来说,通过对应的文件结构体使用函数指针调用对应的读写函数,也就将数据刷新到对于设备上/从设备上读取数据
     

由此将普通文件和硬件设备管理组织好,所以对于Linux来说:一切皆文件

  • 为什么C语言默认打开这三个输入输出流:
  1. 不仅仅是C语言会默认打开这三个输入输出流文件,几乎是任何语言都会这样,而这就不仅仅是语言层面上的功能了,也是由操作系统所支持的

  2. 对于任何语言来说,都有输入输出的需求,而不打开这三个输入出输出流文件,则无法使用这些接口

二、系统文件IO

1、系统调用介绍

操作文件,除了上述C接口(当然C++也有接口,其他语言也有),还可以使用系统接口

  • 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);
  • 参数解释:
  1. pathname: 要打开或创建的目标文件

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

  3. mode_t:如果没有对应文件需要进行创建的话,就需要指定创建文件的八进制访问权限值

参数选项含义
O_RDONLY以只读的方式打开文件
O_WRNOLY以只写的方式打开文件
O_APPEND以追加的方式打开文件
O_RDWR以读写的方式打开文件
O_CREAT当目标文件不存在时,创建文件

注:这里的参数选项是依靠不同的比特位来标识对应的功能设定,所以这里的异或操作就是将对应比特位置为1,同时函数也是通过对每个比特位进行与操作检查是否该比特位置为了1

  • 原型示例:
#define O_RDONLY         00
#define O_WRONLY         01
#define O_RDWR           02
#define O_CREAT        0100

注:open 函数具体使用哪个,和具体应用场景相关,如目标文件不存在,需要open创建,则第三个参数表示创建文件的默认权限,否则,使用两个参数的open

  • 其他接口:
int close(int fd);
//使用close函数时传入需要关闭文件的文件描述符fd即可,若关闭文件成功则返回0,若关闭文件失败则返回-1
ssize_t write(int fd, const void *buf, size_t count);
//使用write函数,将buf位置开始向后count字节的数据写入文件描述符为fd的文件当中
//如果数据写入成功,实际写入数据的字节个数被返回;如果数据写入失败,-1被返回
ssize_t read(int fd, void *buf, size_t count);
//使用read函数,从文件描述符为fd的文件读取count字节的数据到buf位置当中
//如果数据读取成功,实际读取数据的字节个数被返回;如果数据读取失败,-1被返回
  • 结果:

  

2、系统调用和库函数

  • 概念:
  1. 对于上面的 fopen fclose fread fwrite 都是C标准库当中的函数,我们称之为库函数(libc);而 open close read write lseek 都属于系统提供的接口,称之为系统调用接口
  2. 对于系统调用来说,接近底层,使用成本较高,并且不具备可移植性,只在本系统下可以,其他系统不行
  3. 对于库函数来说,是在系统暴露的接口上的一个二次开发(最终调用系统调用),在兼容自己语法的特性的同时,具有可移植性(自动根据平台选择自己底层对应的接口)
  4. 即可以认为库函数是对系统调用的封装,减低人工学习成本,方便二次开发
  • 示图:

三、文件描述符

1、open返回值

  • 文件描述符fd:

文件描述符就是一个小整数

  • 0 & 1 & 2:

Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0, 标准输出1, 标准错误2

  • 示例1:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
int main()
{
    char buf[1024];
    ssize_t s = read(0, buf, sizeof(buf));//标准输入
    if(s > 0){
        buf[s] = 0;
        write(1, buf, strlen(buf));//标准输出
        write(2, buf, strlen(buf));//标准错误
    }
    return 0;
}
  • 结果:

  • 示例2:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
int main()
{
    int fd1=open("fd1.txt",O_WRONLY|O_CREAT,0644);
    int fd2=open("fd1.txt",O_WRONLY|O_CREAT,0644);
    int fd3=open("fd1.txt",O_WRONLY|O_CREAT,0644);
    int fd4=open("fd1.txt",O_WRONLY|O_CREAT,0644);
    int fd5=open("fd1.txt",O_WRONLY|O_CREAT,0644);
    printf("%d\n",fd1);
    printf("%d\n",fd2);
    printf("%d\n",fd3);
    printf("%d\n",fd4);
    printf("%d\n",fd5);
    return 0;
}
  • 结果:

注:从示例中可见,文件描述符就是从0开始的小整数:默认打开0,1,2,再打开则是从后递增

  • 分析:
  1. 当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件
  2. 于是就有了file结构体,表示一个已经打开的文件对象。而进程执行open系统调用,所以必须让进程和文件关联起来。
  3. 每个进程都有一个指针*files, 指向一张表files_struct,该表最重要的部分就是包涵一个指针数组,每个元素都是一个指向打开文件的指针
  4. 所以本质上,文件描述符就是该数组的下标。只要拿着文件描述符,就可以通过PCB到file_struct的指针数组找到对应的文件结构体地址
  • 示图:

2、fd分配规则

  • 文件描述符分配规则:

在files_struct数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述符

  • 示例1:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
    int fd = open("myfile", O_RDONLY);
    if(fd < 0){
        perror("open");
        return 1;
    }
    printf("fd: %d\n", fd);
    close(fd);
    return 0;
}

结果:输出3

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

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

相关文章

刷题day66:目标和

题意描述&#xff1a; 给你一个整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 或 - &#xff0c;然后串联起所有整数&#xff0c;可以构造一个 表达式 &#xff1a; 例如&#xff0c;nums [2, 1] &#xff0c;可以在 2 之前添加 &#xff0c;在 1 之前添…

Kibana 的安装

1. 简介 Kibana 是一个开源的分析与可视化平台&#xff0c;可以用 Kibana 搜索、查看存放在 Elasticsearch 中的数据&#xff0c;就跟谷歌的 elasticsearch head 插件类似&#xff0c;但 Kibana 与 Elasticsearch 的交互方式是各种不同的图表、表格、地图等&#xff0c;直观的…

物联网和边缘计算:如何将数据处理和决策推向设备边缘

第一章&#xff1a;引言 当我们谈论物联网&#xff08;IoT&#xff09;时&#xff0c;我们通常指的是将各种设备连接到互联网&#xff0c;并通过数据交换来实现智能化的网络。然而&#xff0c;传统的物联网模型通常涉及将数据发送到云端进行处理和分析。然而&#xff0c;随着技…

5月第2周榜单丨飞瓜数据B站UP主排行榜(哔哩哔哩平台)发布!

飞瓜轻数发布2023年5月8日-5月14日飞瓜数据UP主排行榜&#xff08;B站平台&#xff09;&#xff0c;通过充电数、涨粉数、成长指数三个维度来体现UP主账号成长的情况&#xff0c;为用户提供B站号综合价值的数据参考&#xff0c;根据UP主成长情况用户能够快速找到运营能力强的B站…

【js】原生input框及下拉框数据联动( 列如: 输入框输入 3,下拉框里的选项值则为:1,2,3)

需求 输入框输入 数字 下拉框要显示对应的数字 列如: 输入框输入 13 下拉框里的选项值则为&#xff1a;1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6&#xff0c;7&#xff0c;8&#xff0c;9&#xff0c;10&#xff0c;11&#xff0c;12&#xff0c;…

【数据结构 -- C语言】 双向带头循环链表的实现

目录 1、双向带头循环链表的介绍 2、双向带头循环链表的接口 3、接口实现 3.1 开辟结点 3.2 创建返回链表的头结点 3.3 判断链表是否为空 3.4 打印 3.5 双向链表查找 3.6 双向链表在pos的前面进行插入 3.6.1 头插 3.6.2 尾插 3.6.3 更新头插、尾插写法 3.7 双向链…

springBoot中使用redis实现分布式锁实例demo

首先 RedisLockUtils工具类 package com.example.demo.utils;import org.junit.platform.commons.util.StringUtils; import org.springframework.context.annotation.Bean; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.red…

【最短路径 本质模板】【最短路径问题 本质 Dijkstra 和 spfa】收藏本篇,遇到最短路问题,来看看模板和思路

也就是走过的节点&#xff0c;还可以再走 但是dij走过的不能再走了 这是本章的精髓&#xff0c;大家往下看 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章…

关于deeplabv3的输出维度与类别预测的对应关系

这里用到的代码是&#xff1a;DeepLabV3源码讲解(Pytorch)_哔哩哔哩_bilibili 背景说明&#xff1a;自己做了一个数据集&#xff0c;已经训练完毕&#xff0c;一共7类零食&#xff0c;加背景算8类。 前面的代码省略了model.eval() # 进入验证模式with torch.no_grad():# init …

WordPress 技巧:WordPress设置媒体文件的默认链接本身方法

当我们在 WordPress 后台上传文件&#xff0c;并添加到内容中得时候&#xff0c;默认媒体文件是链接到文件本身&#xff0c;这个是很烦人的&#xff0c;有时候我们只是想在文章内容中插入一张图片&#xff0c;而不想给这张图片加上任何链接&#xff0c;我们怎么做呢&#xff1f…

动态主机配置协议 DHCP

文章目录 1 概述2 DHCP2.1 工作原理2.2 报文类型 3 扩展3.1 网工软考真题 1 概述 #mermaid-svg-ZESmHWHRC6kYroqm {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-ZESmHWHRC6kYroqm .error-icon{fill:#552222;}#merm…

Java EE 进阶--多线程(二)

目录 一、JUC(java.util.concurrent) 的常见类 1.1 信号量 Semaphore 1.2 CountDownLatch 1.3 CyclicBarrier -循环栅栏 二、线程安全的集合类 2.1 多线程环境使用 ArrayList 2.2 多线程环境使用队列 2.3 多线程环境使用哈希表 三、死锁 3.1 死锁是什么 3.2 如何避免死…

Linux文本三剑客之sed

Linux文本三剑客之sed 一、sed简介二、工作流程三、sed的常见用法1、常见的sed命令选项2、常见的操作3、基本用法实例3.1 sed查询3.2 sed删除3.3 sed替换sed ‘s/旧字符/新字符/’ &#xff1a;替换每行匹配到的第一个旧字符3.4 sed插入 一、sed简介 sed&#xff08;Stream ED…

Chrome浏览器竟然也可以用ChatGPT了!

最近这段时间想必 和我一样&#xff0c;都被chatGPT刷屏了。 在看到网上给出的一系列chatGPT回答问题的例子和自己亲自体验之后&#xff0c;的确发现它效果非常令人惊艳。 chatGPT的火热程度在开源社区也有很明显的体现&#xff0c;刚推出不久&#xff0c;围绕chatGPT的开源项…

Redis:发布订阅

发布订阅到底是什么功能&#xff1f; 在CSDN这个app中有一个关注的功能&#xff0c;其实这个功能与redis的发布订阅有着异曲同工之处 订阅就相当于关注&#xff0c;关注之后&#xff0c;就相当于加入博主的专属的频道里&#xff0c;只要博主在这个频道里发布了什么信息&#…

VMware虚拟机安装OpenEuler欧拉系统

原文地址&#xff1a;https://program-park.top/2023/05/17/linux_7/ OpenEuler 镜像下载&#xff1a;https://www.openeuler.org/zh/download/   我这里以x86_64架构为示例&#xff0c;使用的23.03版本&#xff1a; 准备好镜像文件&#xff1a; 创建新虚拟机&#xff1a; 选…

HBuilder开发uniapp添加android的模拟器的方法

我们知道使用uniapp开发多端app非常方便&#xff0c;开发过程中的模拟器也可以提高我们测试代码的效率。但我们按uniapp官网的方法&#xff0c;上google的官网下载模拟器&#xff0c;往往非常不方便。 下面我们来看一下使用其他模拟器的方法。 我们知道android开发中&#xf…

Java生成jni.h头文件,java调用C方法 图文详解

环境搭建 1. android studio2021.2.1 2. JDK版本1.8 一、创建一个android项目 File ——> New ——> New Project ——> Empty Activity 创建后如下图所示 二、创建一个java调用C的类 2.1 java类命名为JNITest&#xff0c;创建一个两数之和的方法sums 大概需求…

5.Golang、Java面试题—Spring Cloud、Docker、kubernets(k8s)

本文目录如下&#xff1a; Golang、Java面试题二十、Spring Cloud什么是微服务架构&#xff1f;服务拆分 有哪些注意事项&#xff1f;什么是分布式集群?分布式的 CAP 原则&#xff1f;组件 - Spring Cloud 哪几个组件比较重要&#xff1f;组件 - 为什么要使用这些组件&#xf…