Linux-笔记---系统文件I/O

1. open函数和close函数

#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);#include <unistd.h>
int close(int fd);

open函数是一个用于打开或创建文件的系统调用,C语言的fopen函数就是对该函数的封装。

  1. pathname:要打开或创建的文件的路径名(相对路径或绝对路径)。
  2. flags:控制文件打开模式的标志,如只读、只写、读写、创建等。
  3. mode:当创建新文件时,指定文件的权限。这个参数是可选的,仅当在flags中设置了O_CREAT标志时使用。

close函数对应的自然就是fclose函数,将open函数的返回值作为参数传入即可关闭文件,就不过多解释了,重要的是open函数的使用。 

1.1 flag参数

该参数是一个整型值,通过一系列的宏来传递参数,常用的有:

  • O_RDONLY:只读模式打开。
  • O_WRONLY:只写模式打开。
  • O_RDWR:读写模式打开。
  • O_CREAT:如果文件不存在,则创建它。使用这个选项时,需要提供第三个参数mode,指定新文件的权限。
  • O_EXCL:与O_CREAT一起使用时,如果文件已存在,则返回错误。这用于测试文件是否存在。
  • O_TRUNC:如果文件已存在且为普通文件且以只写/读写方式打开,则其长度被截断为0。
  • O_APPEND:写入时将数据追加到文件末尾。

flags本质上是一个位图,而这些宏本质上都是只有一个比特位为1的整型值。

这样的设计方式,使得我们可以利用flags同时传递多条信息,例如:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main()
{int fd = open("test.txt", O_CREAT | O_WRONLY | O_TRUNC);close(fd);return 0;
}// open函数内部判定某个flag是否被选用的原理如下
if(flags & O_CREAT)
{// ...    
}
if(flags & O_WRONLY)
{// ...
}
if(flags & O_TRUNC)
// ...

 1.2 mode参数

mode参数指定新创建文件的权限(只有当flags参数中包含O_CREAT时使用),通常与umask的设置相结合来确定最终权限。

一些常见的权限包括:

  • S_IRUSRS_IWUSRS_IXUSR:分别表示文件所有者的读、写、执行权限。
  • S_IRGRPS_IWGRPS_IXGRP:分别表示用户组的读、写、执行权限。
  • S_IROTHS_IWOTHS_IXOTH:分别表示其他用户的读、写、执行权限。

传参的原理和方式与flags相同,但是使用上面的这些宏来传参太过麻烦了,这些宏的数值实际上是有规律的,分别与权限的八进制表示相对应。

不清楚权限的八进制表示方式的小伙伴可以参考我的这篇博文:Linux笔记---Linux权限理解_linxu用户权限的笔记-CSDN博客

例如,假设"test.txt"在当前目录下不存在,我们希望在创建该文件时将文件的读写权限全部放开:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main()
{int fd = open("test.txt", O_CREAT | O_WRONLY | O_TRUNC, 0666);close(fd);// 等价于// FILE* fp = fopen("test.txt", "w");// fclose(fp);return 0;
}

open函数新建文件时,如果我们没有传入mode,那么新文件的权限就会显示为乱码:

1.3 文件描述符

open函数的返回值是对应文件的文件描述符,即当前程序中已打开的文件在管理文件指针的数组(file* fd_array[])中的下标,从0开始依次递增。

但由于程序在启动时会默认打开stdin、stdout、stderr,所以我们自己打开的文件的文件描述符是从3开始递增的。 

分配下标的规则也很简单:当有文件被打开时,依次遍历fd_array数组,找到第一个为空的下标。

假如我们将1号文件关闭,再另打开一个文件,那么这个文件就会占据1号下标,同时被各种库函数当作标准输出:

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>int main()
{close(1);int fd = open("test.txt", O_CREAT | O_WRONLY | O_TRUNC, 0666);if(fd == 1)printf("喜欢stdout的小朋友你们好啊!我是test.txt,stdout已经被我干掉了!\n");fprintf(stdout, "fd: %d\n", fd);return 0;
}

可以看到,printf函数将内容输出到了test.txt而不是标准输出。 


2. write函数和read函数

2.1 write函数

write函数用于向文件描述符中写入数据。

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
  • fd:文件描述符,表示要写入的文件、管道、套接字等。
  • buf:指向要写入数据的缓冲区的指针。
  • count:要写入的数据的字节数。

write函数的返回值为实际写入的字节数,如果发生错误则返回 -1,并设置errno来指示错误原因。

2.2 read函数

read函数用于从文件描述符中读取数据。

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
  • fd:文件描述符,代表了需要读取的文件或设备。
  • buf:一个指向用户分配的缓冲区的指针,read函数将把读取到的数据写入该缓冲区。
  • count:需要读取的字节数,表示最多读取count字节数据。

read函数的返回值为实际读取到的字节数,如果到达文件末尾则返回0,如果发生错误则返回 -1,并设置errno来指示错误原因。

2.3 示例代码

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>int main() {int fd;char buffer[1024];// 打开文件fd = open("test.txt", O_RDWR | O_CREAT, 0666);if (fd == -1) {perror("open");return 1;}// 写入数据const char *data = "Hello, World!";ssize_t bytes_written = write(fd, data, strlen(data));if (bytes_written == -1) {perror("write");close(fd);return 1;}// 移动文件指针到文件开头lseek(fd, 0, SEEK_SET);// 读取数据ssize_t bytes_read = read(fd, buffer, sizeof(buffer));if (bytes_read == -1) {perror("read");close(fd);return 1;}// 输出读取的数据buffer[bytes_read] = '\0';printf("Read: %s\n", buffer);// 关闭文件close(fd);return 0;
}

首先使用open函数以读写方式打开一个文件,如果文件不存在则创建它。然后使用write函数向文件中写入数据,接着使用lseek函数将文件指针移动到文件开头,再使用read函数从文件中读取数据,最后关闭文件。

3. 重定向

我们在命令行当中可以使用">"、">>"、"<"来进行重定向,即将一个程序的结果输出到文件中,或者从一个文件中读取程序的输入。

重定向的类型

  • [>]输出重定向:将本来应该输出到标准输出(终端屏幕)的数据重定向到一个文件中。
  • [<]输入重定向:将本来应该从标准输入(键盘)读取的数据重定向到一个文件中。
  • [>>]追加重定向:将数据追加到一个文件的末尾,而不是覆盖文件的内容。

那么,重定向的本质是什么呢? 

还记得我们在文件描述符那里举得例子吗?这就是重定向的本质,即修改文件描述符所指向的内容,也是我们在代码层面进行重定向的方式之一。

但是,利用下标分配的机制来进行重定向未免有点繁琐,而且不够精确,可读性,可维护性都较差。

在代码层面,我们常用的重定向的方式是使用dup2系统调用。

dup2函数

int dup2(int oldfd, int newfd);

它的作用是将oldfd所指的文件描述符复制到newfd,并且返回newfd

如果newfd已经打开,则先关闭newfd,再进行复制。该函数成功时返回新的文件描述符,失败时返回 -1,并设置相应的错误码。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main()
{int fd = open("test.txt", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);dup2(fd, 1);printf("喜欢stdout的小朋友你们好啊!我是test.txt,stdout已经被我干掉了,这条消息不会写到标准输出啦!\n");return 0;
}

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

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

相关文章

红日靶场vulnstark 4靶机的测试报告[细节](一)

目录 一、测试环境 1、系统环境 2、注意事项 3、使用工具/软件 二、测试目的 三、操作过程 1、信息搜集 2、漏洞利用Getshell ①Struts 2 s2-045漏洞 手工利用s2-45漏洞 Msf综合利用 ②Tomcat框架(CVE-2017-12615) ③phpMyAdmin(CVE-2018-12613) 构造语句写入冰蝎木…

利用 360 安全卫士极速版关闭电脑开机自启动软件教程

在使用电脑的过程中&#xff0c;过多的开机自启动软件会严重拖慢电脑的开机速度&#xff0c;影响我们的使用体验。本教程中简鹿办公将详细介绍如何使用 360 安全卫士极速版关闭电脑开机自启动软件&#xff0c;让您的电脑开机更加迅速流畅。 一、打开 360 安全卫士极速版 在电…

计算机毕业设计Spark股票推荐系统 股票预测系统 股票可视化 股票数据分析 量化交易系统 股票爬虫 股票K线图 大数据毕业设计 AI

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

本文介绍麒麟信安服务器系统(kylinsec)的安装。

本文介绍麒麟信安服务器系统&#xff08;kylinsec&#xff09;的安装。 下载 在开源欧拉官方找到商业版本的介绍找到相关产品&#xff1a; https://www.openeuler.org/zh/download/commercial-release/ 麒麟信安kylinsec下载地址&#xff1a; https://mirrors.kylinsec.com…

并发专题(10)之FutureTask源码剖析

一、FutureTask介绍 Java创建线程的方式&#xff0c;一般常用的是Thread&#xff0c;Runnable&#xff0c;如果需要处理当前的任务有返回结果的话&#xff0c;需要使用Callable。Callable运行需要配合Future来使用。 Future是一个接口&#xff0c;一般会使用FutureTask实现类去…

ssh远程升级Ubuntu20.04到Ubuntu 22.04

ssh远程升级Ubuntu20.04到Ubuntu 22.04 陈拓 2024/10/16-2024/10/26 1. 简介 本文介绍了如何通过ssh将Ubuntu系统从20.04升级到22.04。 在进行系统升级之前&#xff0c;建议备份重要数据&#xff0c;以防升级过程中出现问题。 2. 更新当前系统 硬件系统架构 当前操作系统版…

新手SEO指南:如何从零开始优化网站实现流量增长

内容概要 在这一部分&#xff0c;我们将简要概述新手在进行SEO优化时需要掌握的一些关键内容。SEO&#xff08;搜索引擎优化&#xff09;是一个复杂而多层次的过程&#xff0c;对网站流量的提升至关重要。无论您是刚刚踏入这一领域的新手&#xff0c;还是希望进一步提升网站性…

FPGA实战篇(呼吸灯实验)

1.呼吸灯简介 呼吸灯采用 PWM 的方式&#xff0c;在固定的频率下&#xff0c;通过调整占空比的方式来控制 LED 灯亮度的变化。 PWM&#xff08;Pulse Width Modulation &#xff09;&#xff0c;即脉冲宽度调制&#xff0c;它利用微处理器输出的 PWM 信号&#xff0c;实现对…

使用 OpenCV 进行 Android 开发

在本节中&#xff0c;我们将创建一个简单的应用程序&#xff0c;它除了加载 OpenCV 之外什么都不做。在下一节中&#xff0c;我们将扩展它以支持相机。 除了这个说明&#xff0c;你还可以使用一些视频指南&#xff0c;例如这个 打开 Android Studio 并选择Empty Views Activi…

项目实例_FashionMNIST_CNN

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…

Autosar FO时间分析和设计规范导读

一、规范功能概述 “Timing Analysis and Design AUTOSAR FO R24 - 11” 文档主要聚焦于汽车电子系统开发中的定时分析与设计&#xff0c;详细阐述了相关概念、方法、用例及涉及的各项要素&#xff0c;旨在为汽车电子系统的开发提供全面且系统的定时分析指导&#xff0c;以确保…

使用 libssh2_session_set_timeout 设置 SSH 会话超时时间

使用 libssh2_session_set_timeout 设置 SSH 会话超时时间 函数原型参数说明返回值示例代码注意事项libssh2_session_set_timeout 是 libssh2 库中的一个函数,用于设置 SSH 会话的超时时间。这对于防止网络延迟或连接中断导致的长时间挂起非常有用。 函数原型 int libssh2_se…

001 LVGL PC端模拟搭建

01 LVGL模拟器介绍 使用PC端软件模拟LVGL运行&#xff0c;而不需要任何嵌入式硬件 环境搭建&#xff1a;codeblocks-20.03mingw-setup 正常安装流程即可 工程获取&#xff1a;LVGL官网-> github仓库 本地安装包下载资源包 工程模版和软件安装包 补充&#xff1a;…

开源ISP介绍(2)————嵌入式Vitis搭建

Vivado搭建参考前一节Vivado基于IP核的视频处理框架搭建&#xff1a; 开源ISP介绍&#xff08;1&#xff09;——开源ISP的Vivado框架搭建-CSDN博客 导出Hardware 在vivado中导出Hardware文件&#xff0c;成功综合—实现—生成比特流后导出硬件.xsa文件。&#xff08;注意导…

人工智能-自动驾驶领域

目录 引言自动驾驶与人工智能的结合为什么自动驾驶领域适合发表文章博雅智信的自动驾驶辅导服务结语 引言 自动驾驶技术的崛起是当代交通行业的一场革命。通过结合先进的人工智能算法、传感器技术与计算机视觉&#xff0c;自动驾驶不仅推动了技术的进步&#xff0c;也使得未来…

Kubernetes 深入浅出系列 | 容器编排与作业调度之Deployment

目录 概述Deployment 的更新原理实验 概述 Kubernetes 中&#xff0c;Deployment 控制器是用于管理应用程序生命周期的核心对象。Deployment 通过管理 ReplicaSet 来间接控制 Pod&#xff0c;确保在任何时刻都能维持指定数量的 Pod 副本。这种间接管理使得 Deployment 功能比 …

Java——异常机制(上)

1 异常机制本质 (异常在Java里面是对象) (抛出异常&#xff1a;执行一个方法时&#xff0c;如果发生异常&#xff0c;则这个方法生成代表该异常的一个对象&#xff0c;停止当前执行路径&#xff0c;并把异常对象提交给JRE) 工作中&#xff0c;程序遇到的情况不可能完美。比如…

如何查看电脑的屏幕刷新率?

1、按一下键盘的 win i 键&#xff0c;打开如下界面&#xff0c;选择【系统】&#xff1a; 2、选择【屏幕】-【高级显示设置】 如下位置&#xff0c;显示屏幕的刷新率&#xff1a;60Hz 如果可以更改&#xff0c;则选择更高的刷新率&#xff0c;有助于电脑使用起来界面更加流…

WAT绕过姿势

一.空格字符绕过 两个空格代替⼀个空格&#xff0c;⽤ Tab 代替空格&#xff0c;%a0空格 %20 %09 %0a %0b %0c %0d %a0 %00 /**/ /*!*/ select * from users where id1 /*!union*//*!select*/1,2,3,4; %09 TAB 键&#xff08;⽔平&#xff09;%0a 新建⼀⾏%0c 新的⼀⻚%0d …

Ubuntu 环境美化

一、终端选择 zsh 参考文章使用 oh-my-zsh 美化终端 Oh My Zsh 是基于 zsh 命令行的一个扩展工具集&#xff0c;提供了丰富的扩展功能。 先安装zsh再安装Oh My Zsh 1.zsh安装 sudo apt-get install zsh 2.设置默认终端为 zsh chsh -s /bin/zsh 3.安装 oh-my-zsh 官网&…