当前位置: 首页 > news >正文

Linux操作系统--基础I/O(上)

目录

1.回顾C文件接口

stdin、stdout、stderr

2.系统文件I/O

3.接口介绍

4.open函数返回值

5.文件描述符fd

5.1 0&1&2


1.回顾C文件接口

hello.c写文件

#include<stdio.h>
#include<string.h>int main()
{FILE *fp = fopen("myfile","w");if(!fp){printf("fopen error!\n");}const char *msg = "hello friend!\n";int count = 5;while(count--){fwrite(msg,strlen(msg),1,fp);}fclose(fp);return 0;
}

hello.c读文件

#include<stdio.h>
#include<string.h>int main()
{FILE *fp = fopen("myfile","r");if(!fp){printf("fopen error!\n");}char buf[1024];const char *msg = "hello friend!\n";while(1){//size_t s = fread(buf,strlen(msg),1,fp);if(s>0){buf[s] = 0;printf("%s",buf);}if(feof(fp)){//用于检测文件是否读到末尾break;}}fclose(fp);return 0;
}

输出信息到显示器

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

stdin、stdout、stderr

stdin(0):键盘文件 

stdout(1):显示器文件

stderr(2):显示器文件。(错误信息输出)
进程会默认打开键盘、显示器

三个流的类型都是FILE* ,fopen返回值类型,文件指针

2.系统文件I/O

操作文件,除了上述C接口,我们还可以采用系统接口来进行文件访问。(文件其实是在磁盘上的,磁盘是外部设备,访问磁盘文件其实是访问硬件。几乎所有的库只要是访问硬件设备,必定要封装系统调用,因为之前讲到过,操作系统并不相信用户,不会与用户直接接触,所以提供了接口给用户)

先来直接以代码的形式,实现上面一模一样的代码:

hello.c写文件

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>int main()
{umask(0);//修改默认权限掩码int fd = open("myfile",O_WRONLY|O_CREAT,0644);if(fd<0){perror("open");return 1;}int count = 5;const char *msg = "hello friend\n";int len = strlen(msg);while(count--){write(fd,msg,len);//fd:后面讲, msg:缓冲区首地址, len:本次读取,期望写入多少个字节的数据, //返回值:实际写了多少字节数据}close(fd);return 0;
}

hello.c读文件

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>int main()
{int fd = open("myfile",O_RDONLY);if(fd<0){perror("open");return 1;}const char *msg = "hello friend\n";char buf[1024];while(1){size_t s = read(fd,buf,strlen(msg));if(s>0){printf("%s",buf);}else{break;}}close(fd);return 0;
}

3.接口介绍

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

pathname:要打开或创建的目标文件

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

参数:

        O_RDONLY:只读打开

        O_WRONLY:只写打开

        O_RDWR:读、写打开

                这三个常量,必须指定一个且只能指定一个

        O_CREAT:若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限

        O_APPEND:追加写

返回值:

        成功:新打开的文件描述符

        失败:-1

4.open函数返回值

在认识返回值之前,下来认识两个概念:

  1. 系统调用:系统调用是操作系统提供给用户程序的一种接口,用于让用户程序请求操作系统内核提供的服务。当用户程序需要执行一些特权操作(如文件操作、进程管理等),无法直接访问硬件资源,需要通过系统调用向操作系统内核发出请求。系统调用是通过中断或异常机制实现的,可以看作是用户程序与操作系统内核之间的桥梁。

  2. 库函数:库函数是一组提供特定功能的函数,被封装在软件库中以供程序开发者使用。库函数通常是由编程语言或第三方开发者编写的,用于简化开发过程、提高代码的可重用性和可维护性。库函数可以包含在标准库或第三方库中,程序可以通过链接库函数的方式来调用其中的功能
  • 上面的fopen fclose fread fwrite都是C标准库当中的函数,我们称之为库函数(libc)。
  • 而,open close read write lseek都属于系统提供的接口,称之为系统调用接口

系统调用接口和库函数的关系一目了然

所以,可以认为,f#系列的函数,都是对系统调用的封装,方便二次开发

5.文件描述符fd

文件描述符就是一个整数

5.1 0&1&2

  • Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0,标准输出1,标准错误2.
  • 0,1,2对应的物理设备一般是:键盘,显示器,显示器                        

所以输入输出还可以采用如下方式:

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.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;
}

而现在知道,文件描述符就是从0开始的整数。当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。于是就有了file结构体。表示一个已经打开的文件对象。而进程执行open系统调用,所以必须让进程和文件关联起来。每个进程都有一个指针*files,指向一张表files_struct,该表最重要的部分就是包含一个指针数组,每个元素都是一个指向打开文件的指针。所以,本质上,文件描述符就是数组的下标。所以,只要拿着文件描述符,就可以找到对应的文件。

http://www.xdnf.cn/news/117505.html

相关文章:

  • Freertos----软件定时器
  • WPS右键菜单中“上传到云文档”消失,使用命令行注册解决
  • LeetCode-Hot100
  • 数据集-目标检测系列- F35 战斗机 检测数据集 F35 plane >> DataBall
  • 【安全扫描器原理】网络扫描算法
  • 【c++】【STL库】vector类详解
  • C语言基础(day0424)
  • Java基础系列-HashMap源码解析4-基本概念
  • 各种插值方法的Python实现
  • BERT BERT
  • 精益数据分析(21/126):剖析创业增长引擎与精益画布指标
  • 4.3 工具调用与外部系统集成:API调用、MCP(模型上下文协议)、A2A、数据库查询与信息检索的实现
  • 实战交易策略 篇十九:君山居士熊市交易策略
  • 如何自己电脑上部署DeepSeek,并且接口访问?
  • 摘要 | 李录在北大光华管理学院的演讲《价值投资》
  • express的介绍,简单使用
  • ES6 模块化 与 CommonJS 的核心概念解析
  • java 富文本转pdf
  • 《100天精通Python——基础篇 2025 第1天:从编程语言到计算机基础,开启你的学习之旅》
  • 数据仓库建设全解析!
  • 【动手学大模型开发】什么是大语言模型
  • Crawl4AI 部署安装及 n8n 调用,实现自动化工作流(保证好使)
  • Redis LRU策略深度解析
  • 深度理解spring——BeanFactory的实现
  • # 代码随想录算法训练营Day37 | Leetcode300.最长递增子序列、674.最长连续递增序列、718.最长重复子数组
  • 民锋视角下的节奏判断与资金行为建模
  • 自动化测试常见面试题(上)
  • Oracle数据库巡检脚本
  • 怎么配置一个kubectl客户端访问多个k8s集群
  • MySQL 安装配置教程(含性能优化)