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

Linux 文件

1.操作系统的文件函数

我们以一个操作系统的文件函数为例 其它是差不多的

open函数

const char *pathname(必选)

作用:指定要打开 / 创建的文件路径(绝对路径或相对路径)。

关键说明: 支持绝对路径(如 /home/user/test.txt)和相对路径(如 test.txt、data/log.csv);

若路径是符号链接,默认会跟随链接指向的真实文件(可通过 O_NOFOLLOW 标志禁用此行为);

路径长度不能超过系统限制(Linux 中默认最大路径长度为 PATH_MAX,通常是 4096 字节)。

2. int flags(必选,核心控制位)

作用:通过「标志位组合」指定文件的访问模式、创建 / 修改行为、IO 特性等,是系统调用 open() 最关键的参数。

标志位分类(需用按位或 | 组合): 标志位是预定义的宏(如 O_RDONLY),本质是整数,不同标志位的二进制位互不冲突,因此可用 | 组合多个行为。

访问模式标志(必选,且互斥,只能选一个) 控制文件的读写权限,是 flags 中必须包含的核心标志:

open 函数的 flag 参数由一系列宏组成,每个宏对应一个独立的二进制位。

例如:

O_RDONLY:二进制 000...0001(最低位为 1),表示只读。

O_WRONLY:二进制 000...0010(第二位为 1),表示只写。

O_RDWR:二进制 000...0100(第三位为 1),表示读写。

O_CREAT:二进制 000...10000000(第 8 位为 1),表示创建文件。

O_APPEND:二进制 000...100000000(第 9 位为 1),表示追加写入。

3.mode_t mode(可选,仅 O_CREAT/O_TMPFILE 时有效)

作用:指定「新建文件」的权限位(文件所有者、组用户、其他用户的读 / 写 / 执行权限)。

关键说明: 仅当 flags 包含 O_CREAT(创建普通文件)或 O_TMPFILE(创建临时文件)时,该参数才生效;

否则会被忽略; mode 是八进制整数(必须以 0 开头,如 0644,而非 644),对应文件权限的 rwx 组合(r=4、w=2、x=1);

实际文件权限 = mode & ~umask:系统会用「默认掩码 umask」过滤 mode 的权限位(umask 默认为 0022,即禁用组用户和其他用户的写权限)。

常用 mode 取值(八进制):

我们可以写几个代码试试

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>int main()
{umask(0);int fd = open("log.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);if(fd < 0){printf("open file error\n");return 1;}printf("fd: %d\n", fd);const char *message = "xxx";write(fd, message, strlen(message));close(fd);return 0;
}

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>int main()
{umask(0);int fd = open("log.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666);if(fd < 0){printf("open file error\n");return 1;}printf("fd: %d\n", fd);const char *message = "xxx\n";write(fd, message, strlen(message));close(fd);return 0;
}

2.open的返回值

open的返回值本质上是数组的下标

open 的返回值(文件描述符 FD),本质是 struct files_struct 所关联的「文件描述符表」数组的下标—— 更具体地说,是该结构中 fd_array(默认静态数组)或动态扩展的 fdtable->fd 数组的下标。

fd_array存放的是指针 每个指针 指向的是文件

我们可以来测试一下

int main()
{umask(0);int fd1 = open("log1.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);int fd2 = open("log2.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);int fd3 = open("log3.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);int fd4 = open("log4.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);if(fd1 < 0){printf("open file error\n");return 1;}printf("fd1: %d\n", fd1);printf("fd2: %d\n", fd2);printf("fd3: %d\n", fd3);printf("fd4: %d\n", fd4);return 0;
}

我们发现当我们open四个文件的时候

返回值是从3开始依次递增的

那么 数组0 1 2 的下标是什么

0 1 2是我们系统的三个流 一般是默认打开的

(这是操作系统的特性 并不是C语言的特性)

标准输入流            stdin: 键盘文件
标准输出流            stdout: 显示器文件
标准错误输出流     stderr: 显示器文件

分别是标准输入流 标准输出流  以及标准错误输出流

我们可以通过下面例子进行验证

#include <sys/stat.h>
#include <string.h>
#include <unistd.h>int main()
{const char *msg = "hello Linux\n";write(1, msg, strlen(msg));write(2, msg, strlen(msg));return 0;
}

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main()
{char buffer[1024];ssize_t s = read(0, buffer, sizeof(buffer));if(s < 0) return 1;buffer[s] = '\0';//read只按字节读取不管你是不是字符串有没有\0printf("echo: %s\n", buffer);return 0;
}

strlen 的作用是 计算字符串的 “有效字符数”,它从字符串起始位置开始计数,直到遇到 '\0' 为止,不包含 '\0' 本身。

对于操作系统而言它不知\0是字符串结束的标志 它只会把\0当作一个普通字节读入

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main()
{umask(0);int fd = open("log.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);if(fd < 0){printf("open file error\n");return 1;}printf("fd: %d\n", fd);const char *message = "xxx";write(fd, message, strlen(message)); // +1?close(fd);return 0;
}

write(read等操作系统调用的文件相关函数同理) 是系统调用,核心作用是 “把用户指定的‘有效数据’原封不动地写入文件 / 设备”,它完全不认识 '\0'

—— 对 write 来说,'\0' 只是一个普通的二进制字节(ASCII 码 0),不是 “结束标志”。

你的需求是把 message 的内容("xxx")写入文件 log.txt,那么: 用 strlen(message)(3):write 只写 3 个有效字符 'x'、'x'、'x',文件里的内容就是 xxx(正确);

用 strlen(message)+1(4):write 会写 4 个字节 'x'、'x'、'x'、'\0',文件里会多一个隐藏的 '\0' 字节(多余且无意义)。

当然我们也可以关闭其中某一个

#include <stdio.h>
#include <unistd.h>  // 提供 close 函数的声明int main()
{close(1);  // 关闭 stdout 对应的文件描述符(fd=1)int n = printf("stdin->fd: %d\n", stdin->_fileno);printf("stdout->fd: %d\n", stdout->_fileno);printf("stderr->fd: %d\n", stderr->_fileno);fprintf(stderr, "printf ret: %d\n", n);return 0;
}

close本质和C++智能指针类似

close的时候

引用计数--

再把指针置空

引用计数--后判断 如果为0系统回收 如果不为0(可能还有其他进程在用) 系统就停止操作 不回收

如果为0 系统就回收这个文件

3.操作系统文件函数和c语言文件函数的区别

C 语言的 fprintf 等文件函数是对操作系统 writeopen 等系统调用的上层封装,它通过添加缓冲、格式化、跨平台适配等逻辑,让开发者能更简单地进行文件操作;

而系统调用则是更底层、更直接的内核接口,适合需要精细控制的场景。这种分层设计既保证了易用性,又保留了底层灵活性。

但是我们知道操作系统文件函数的返回值类型是int

而c语言文件函数的返回值类型是FILE*

FILE* 类型(C 标准库): 它是C 标准库定义的一个结构体指针(你可以理解为一个 “包装器”)。

这个结构体里包含了文件描述符(即 open 返回的 int),还额外添加了缓冲区、读写位置、错误标志、EOF 标志等用户态的管理信息。

它的作用是在系统调用之上封装一层 “易用接口”,让开发者无需直接处理底层细节(比如缓冲、跨平台兼容)。

http://www.dtcms.com/a/594560.html

相关文章:

  • MCU 内存栈介绍和内存段
  • 如何配置Dev-C++的环境变量到系统路径?
  • 在网站和网页的区别哪里有培训网
  • 洪梅网站建设网站开发所需费用支出有哪些
  • 个人网站首页模板彩票网站开发演示
  • 企业网站未来发展趋势网站推广怎么推广
  • 芯伯乐3A降压稳压器XBLW LM2576/LM2596:高效、高可靠性开关电源解决方案
  • 30V N 沟道 MOSFET SP30N03BNK 规格解析与应用场景详解
  • JSON格式爬取淘宝/1688/京东商品详情API接口实战指南
  • 网站搭建推广优化知乎网页版
  • 02-Git Echarts
  • 网站 建设 申请报告广东专业网站优化制作公司
  • Kubernetes 第三章:深入掌握pod-基础
  • 介绍 一下 Pi3 (π³) 算法:排列等变视觉几何学习
  • 短网址生成站长工具网络推广和竞价怎么做
  • 个人主页空间申请新乡网站seo优化
  • vue弹出是否继续操作
  • 学校网站建设钉钉花桥网站建设
  • 网站微商城的建设网站关键词建设
  • 企业网站建设的原则做公众号一个月挣多少钱
  • yum 源无法访问及DNS 解析失败问题
  • 咸阳网站开发wordpress作者插件
  • STM32配置注意事项
  • 做中国菜的外国网站网站建设与设计ppt模板下载
  • 东莞模板网站制作哪家好江苏省造价信息工程网
  • 常用数学函数详解:从基础运算到图形学应用
  • 杭州网站改版公司兰州网站设计公司排名
  • vcpkg安装包报错 错误 TRK0005: 未能找到: rc.exe ,系统找不到指定的文件问题解决
  • 旅游网站模板免费室内设计联盟论坛官网
  • wordpress 用户名 密码合肥seo网站多少钱