C语言——文件描述符、系统调用操作文件

文件描述符

在Unix-like操作系统中,文件描述符(file descriptor)是一个用于标识打开文件或I/O设备的整数值。它是对底层文件系统的抽象,用于在应用程序和操作系统之间传递文件信息。

文件描述符是一个非负整数,通常是一个小整数。在C语言中,文件描述符被表示为int类型。

每个进程在其打开的文件或设备上都有一组文件描述符,它们是连续的、非重复的整数值。当一个文件或设备被打开时,操作系统会为该文件分配一个文件描述符,并将其返回给应用程序。

常见的文件描述符包括:

  • 标准输入(stdin):文件描述符为0,宏为STDIN_FILENO,通常用于接收应用程序的输入。
  • 标准输出(stdout):文件描述符为1,宏为STDOUT_FILENO,通常用于输出应用程序的结果。
  • 标准错误(stderr):文件描述符为2,宏为STDERR_FILENO,通常用于输出应用程序的错误信息。
应用程序可以使用文件描述符进行各种文件和I/O操作,例如读取文件内容、写入数据、关闭文件等。文件描述符作为操作系统和应用程序之间的桥梁,允许应用程序与文件系统和其他设备进行交互。

在Linux的世界里,一切设备皆文件。我们可以调用系统中 的 I/O函数,对文件进行相应的操作( open()、close()、write() 、read() 等)。

打开现有文件或新建文件时,系统(内核)会返回一个文件描述符,文件描述符用来指定已打开的文件。这个文件描述符相当于这个已打开文件的标号。文件描述符是非负整数,是文件的标识,操作这个文件描述符相当于操作这个描述符所指定的文件。

程序运行起来后(每个进程)都有一张文件描述符的表,标准输入、标准输出、标准错误输出设备文件被打开,对应的文件描述符 0、1、2 记录在表中。程序运行起来后这三个文件描述符是默认打开的。

#define STDIN_FILENO  0 //标准输入的文件描述符
#define STDOUT_FILENO 1 //标准输出的文件描述符
#define STDERR_FILENO 2 //标准错误的文件描述符

在程序运行起来后打开其他文件时,系统会返回文件描述符表中最小可用的文件描述符,并将此文件描述符记录在表中。
在这里插入图片描述
最大打开的文件个数
Linux中一个进程最多只能打开NR_OPEN_DEFAULT(即1024)个文件,故当文件不再使用时应及时调用 close() 函数关闭文件。
• 查看当前系统允许打开最大文件个数:

cat /proc/sys/fs/file-max

• 当前默认设置最大打开文件个数1024

ulimit -a

• 修改默认设置最大打开文件个数为4096

ulimit -n 4096

16. 常用文件IO函数(以下均为系统调用)

Linux的man手册共有以下几个章节:

  1. Standard commands (标准命令)
  2. System calls (系统调用)
  3. Library functions (库函数)
  4. Special devices (设备说明)
  5. File formats (文件格式)
  6. Games and toys (游戏和娱乐)
  7. Miscellaneous (杂项)
  8. Administrative Commands (管理员命令)
    使用系统调用函数依然是需要引入头文件的,要引入哪些可以通过man命令查看
man 2 命令

16.1 open函数

man 2 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:打开文件的行为标志,用于指定文件的打开方式和操作选项。必选项O_RDONLY\O_WRONLY\O_RDWRmode:权限参数,用于指定新创建文件的访问权限,只有在使用O_CREAT标志创建文件时才有效。
返回值:成功:成功返回打开的文件描述符失败:-1

open()函数返回一个非负整数的文件描述符(file descriptor),用于后续对文件的读写操作。如果打开文件失败,函数返回-1,并可以使用errno全局变量获取具体的错误码。
flags详细说明
必选项:

取值含义
O_RDONLY以只读的方式打开
O_WRONLY以只写的方式打开
O_RDWR以可读、可写的方式打开

可选项,和必选项按位或起来

取值含义
O_CREAT文件不存在则创建文件,使用此选项时需使用mode说明文件的权限
O_EXCL与O_CREAT一起使用,用于确保创建文件时文件不存在。如果同时指定了O_CREAT,且文件已经存在,则出错
O_TRUNC如果文件存在,则清空文件内容
O_APPEND写文件时,数据添加到文件末尾
O_NONBLOCK对于设备文件, 以O_NONBLOCK方式打开可以做非阻塞I/O

mode补充说明

  1. 文件最终权限:mode & ~umask
  2. shell进程的umask掩码可以用umask命令查看

Ø umask:查看掩码(补码)
Ø umask mode:设置掩码,mode为八进制数
Ø umask -S:查看各组用户的默认操作权限

取值八进制含义
S_IRWXU00700文件所有者的读、写、可执行权限
S_IRUSR00400文件所有者的读权限
S_IWUSR00200文件所有者的写权限
S_IXUSR00100文件所有者的可执行权限
S_IRWXG00070文件所有者同组用户的读、写、可执行权限
S_IRGRP00040文件所有者同组用户的读权限
S_IWGRP00020文件所有者同组用户的写权限
S_IXGRP00010文件所有者同组用户的可执行权限
S_IRWXO00007其他组用户的读、写、可执行权限
S_IROTH00004其他组用户的读权限
S_IWOTH00002其他组用户的写权限
S_IXOTH00001其他组用户的可执行权限

16.2 close函数

在这里插入图片描述

#include <unistd.h>
int close(int fd);
功能关闭已打开的文件
参数:fd: 文件描述符,open()的返回值
返回值:成功:0失败:-1, 并设置errno

需要说明的是,当一个进程终止时,内核对该进程所有尚未关闭的文件描述符调用close关闭,所以即使用户程序不调用close,在终止时内核也会自动关闭它打开的所有文件。

但是对于一个长年累月运行的程序(比如网络服务器),打开的文件描述符一定要记得关闭,否则随着打开的文件越来越多,会占用大量文件描述符和系统资源。

16.3 write函数

在这里插入图片描述

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
功能:把指定数目的数据写到文件(fd),将buf指向的数据写入到文件描述符fd所指向的文件或设备中。
参数:fd: 文件描述符,可以是标准输出(STDOUT_FILENO,值为1)、标准错误(STDERR_FILENO,值为2),或者是通过open函数打开的文件描述符。buf: 数据首地址,要写入数据的缓冲区的指针。count: 写入数据的长度(字节)
返回值:成功:实际写入数据的字节个数失败: - 1

write() 函数返回一个 ssize_t 类型的值,表示成功写入的字节数。返回值有以下几种情况:

  • 如果返回值大于等于 0,则表示成功写入了指定字节数。
  • 如果返回值为 -1,则表示发生了错误。此时,可以通过 errno 全局变量来获取具体的错误代码。
  • 如果返回值为 0,则表示没有写入任何数据。这通常发生在写入到非阻塞文件描述符时,当写入缓冲区已满或遇到信号中断时。
需要注意的是,write() 函数可能不会一次性写入所有请求的字节数。在某些情况下,它可能会写入部分数据并返回写入的字节数。如果需要确保全部数据写入,可能需要多次调用 write() 直到写入的字节数达到预期。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>//write file
int main(void) {int fd=-1;int ret=-1;char *str="hello test";
//打开或者创建一个文件,返回文件描述符。文件名就叫做txtfd=open("txt",O_WRONLY | O_CREAT,0644);if(-1==fd){perror("open");return 1;}printf("fd=%d\n",fd);
//往文件中写入内容ret=write(fd,str,strlen(str));if (-1==ret){perror("write");return 1;}
//长度应该是hello test共10个char占10个字节printf("write len:%d\n",ret);close(fd);return 0;
}

16.4 read函数

在这里插入图片描述

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
功能:把指定数目的数据读到内存(缓冲区)。从文件描述符fd所指向的文件或设备中读取数据,并将其存储到buf所指向的缓冲区中。
参数:fd: 文件描述符,它可以是标准输入(STDIN_FILENO,值为0)、标准输出(STDOUT_FILENO,值为1)、标准错误(STDERR_FILENO,值为2),或者是通过open函数打开的文件描述符。buf: 内存首地址,用于存储读取数据的缓冲区的指针count: 读取的字节个数
返回值:成功:实际读取到的字节个数失败: - 1

read函数返回实际读取的字节数,如果返回值为0,则表示已到达文件末尾,如果返回值为-1,则表示出现错误。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>//read file
#define SIZE 128
int main(void) {int fd=-1;int ret=-1;char *str="hello test";//打开或者创建一个文件,返回文件描述符。文件名就叫做txtfd=open("txt",O_RDONLY);if(-1==fd){perror("open");return 1;}printf("fd=%d\n",fd);//读取文件中内容char buf[SIZE];memset(buf,0,SIZE);ret=read(fd,buf,SIZE);if (-1==ret){perror("read");return 1;}//长度应该是hello test共10个char占10个字节printf("read len:%d\n",ret);close(fd);return 0;
}

阻塞和非阻塞的概念
读常规文件是不会阻塞的,不管读多少字节,read一定会在有限的时间内返回。

从终端设备或网络读则不一定,如果从终端输入的数据没有换行符,调用read读终端设备就会阻塞,如果网络上没有接收到数据包,调用read从网络读就会阻塞,至于会阻塞多长时间也是不确定的,如果一直没有数据到达就一直阻塞在那里。

同样,写常规文件是不会阻塞的,而向终端设备或网络写则不一定。

【注意】阻塞与非阻塞是对于文件而言的,而不是指read、write等的属性。

以非阻塞方式打开文件程序示例:

#include <unistd.h> //read
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h> //EAGAINint main() {// /dev/tty --> 当前终端设备// 以不阻塞方式(O_NONBLOCK)打开终端设备,0 1 2进程启动就被占用了,所以最小fd为3int fd = open("/dev/tty", O_RDONLY | O_NONBLOCK);char buf[10];int n;n = read(fd, buf, sizeof(buf));if (n < 0) {// 如果为非阻塞,但是没有数据可读,此时全局变量 errno 被设置为 EAGAINif (errno != EAGAIN) {perror("read /dev/tty");return -1;}printf("没有数据\n");}return 0;
}
#include <stdio.h>
int main(void) {//阻塞char ch=-1;ch=getchar();putchar(ch);
}

16.5 lseek函数

在这里插入图片描述

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
功能:改变文件的偏移量
参数:fd:文件描述符offset:根据whence来移动的位移数(偏移量),可以是正数,也可以负数,如果正数,则相对于whence往右移动,如果是负数,则相对于whence往左移动。如果向前移动的字节数超过了文件开头则出错返回,如果向后移动的字节数超过了文件末尾,再次写入时将增大文件尺寸。whence:其取值如下:SEEK_SET:从文件开头移动offset个字节SEEK_CUR:从当前位置移动offset个字节SEEK_END:从文件末尾移动offset个字节
返回值:若lseek成功执行, 则返回新的偏移量如果失败, 返回-1

所有打开的文件都有一个当前文件偏移量(current file offset),以下简称为 cfo。cfo 通常是一个非负整数,用于表明文件开始处到文件当前位置的字节数。

读写操作通常开始于 cfo,并且使 cfo 增大,增量为读写的字节数。文件被打开时,cfo 会被初始化为 0,除非使用了 O_APPEND 。

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

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

相关文章

FX110书籍推荐:如何快速成为一名专业股票投资人?

股票投资领域有一本神作《股票交易入门》&#xff0c;它是股票从业人员的入门必备书籍。 关于股票入门的书籍很多&#xff0c;但这本书涉及的知识面最全、实用性最强。从这本书里&#xff0c;我们可以领略到股票交易世界的跌宕起伏而又波澜壮阔的魅力。本书作者 本书的作者是美…

【自动驾驶|毫米波雷达】卡尔曼滤波

目录 一. 滤波器分类 二.卡尔曼滤波&#xff08;Kalman Filter&#xff09;原理 &#xff08;1&#xff09;定性理解 &#xff08;2&#xff09;定量推导 1. 预测阶段 2. 更新阶段 3. 卡尔曼增益 1&#xff09;卡尔曼增益 2&#xff09;如何理解卡尔曼增益&#xff1f; 三…

省份数量00

题目链接 省份数量 题目描述 注意点 1 < n < 200isConnected[i][j] 为 1 或 0isConnected[i][i] 1isConnected[i][j] isConnected[j][i] 解答思路 最初想到的是广度优先遍历&#xff0c;当某个城市不属于省份&#xff0c;需要从该城市开始&#xff0c;根据isConne…

重大消息!软考高级论文单考,综合和案例连考

依据辽宁省信息技术教育中心&#xff08;辽宁省软考办&#xff09;发布《关于2024年上半年计算机技术与软件专业技术资格(水平)考试批次安排的通知》可知&#xff0c;2024年上半年软考有如下调整&#xff1a; 1.软考高级考试中&#xff0c;综合知识和案例分析连考&#xff08;…

【功耗仪使用】

一&#xff0c;功耗仪使用 1.1&#xff0c;功耗仪外观及与手机&#xff0c;电脑连接方式 power monitor设备图 同时power monitor设备的后端有一个方形插孔通过数据线与电脑主机USB接口相连接&#xff0c;圆形插孔为电源插孔&#xff0c;用来给power monitor设备通电 pow…

淘宝优惠券领取软件草柴返利APP想从淘宝粘贴提示怎么关闭?想从天猫粘贴、想从京东粘贴弹窗提示关闭

使用iPhone苹果手机想从淘宝点击分享复制链接&#xff0c;到草柴APP查询该商品内部大额隐藏优惠券和返利。可是&#xff0c;苹果iPhone手机每次将复制的商品链接&#xff0c;粘贴到草柴APP时都是提示&#xff1a;“草柴”想从“淘宝”粘贴&#xff0c;每次都需要点击允许粘贴后…

MT2049 运动会进行中

思路&#xff1a;使用a存前缀和。遇见女生-1&#xff0c;遇见男生1。之后遍历a的时候&#xff0c;如果a[i]a[j]&#xff0c;则说明ij这个区间里男女生数量是一样的。所以即求ij这个区间最大长为多少。可以用l[]r[]数组记录某个数第一次出现的位置和最后一次出现的位置。 例如样…

【XR806开发板试用】SPI驱动数码管显示

准备工作 安装repo 创建repo安装目录。 mkdir ~/bin下载repo wget https://storage.googleapis.com/git-repo-downloads/repo -P ~/bin/改变执行权限 chmod ax ~/bin/repo设置环境变量&#xff0c;在~/.bashrc文件的最后输入 export PATH~/bin:$PATH和export REPO_URLhttps://…

java项目+maven+sonarqube+githook 实现代码提交审查

java项目mavensonarqubegithook 实现代码提交审查 当在团队开发过程中, 由于开发人员技术和风格的不同,导致代码质量和风格各不相同, 为了减少合并时的工作量, 以及基础的一些bug 的避免, 可以使用 (sonarqube阿里巴巴开发规范) 实现代码质量的检测. 为了更加简便, 即在使用git…

武汉星起航:亚马逊年终促销新策略——强化营销,优化体验赢未来

年终节日是电商平台的黄金销售期&#xff0c;也是各大电商平台竞相展示自身实力与智慧的重要舞台。作为全球电商巨头的亚马逊&#xff0c;自然也不例外。每年的年终节日&#xff0c;亚马逊都会推出一系列精彩纷呈的促销活动&#xff0c;吸引全球消费者的目光&#xff0c;实现销…

终端安全管理措施有哪些?好用终端安全管理软件推荐(建议收藏)

在当今数字化时代&#xff0c;信息安全已成为企业运营不可或缺的一部分。其中&#xff0c;终端安全为您详细介绍&#xff0c;并推荐几款好用的终端安全管理软件&#xff0c;帮助您更好地保护企业信息安全。管理是确保企业信息安全的重要环节。那么&#xff0c;终端安全管理措施…

JAVA智慧校园平台系统源码:基于前后端框架VUE2+Spring boot+Wed端原生小程序搭建的智慧校园平台

智慧校园平台是目前教育信息化领域的热点之一。随着数字化转型的加速&#xff0c;越来越多的学校开始寻求解决方案&#xff0c;以提高教育管理的效率和质量。 在使用智慧校园平台的过程中&#xff0c;一些功能特点是必要的。那么&#xff0c;究竟什么是智慧校园平台&#xff1…

[图解]SysML和EA建模住宅安全系统-02

1 00:00:00,900 --> 00:00:02,690 这个就是一个块定义图了 2 00:00:03,790 --> 00:00:04,780 简称BDD 3 00:00:05,610 --> 00:00:08,070 实际上就是UML里面的类图 4 00:00:08,080 --> 00:00:09,950 和组件图的一个结合体 5 00:00:13,150 --> 00:00:14,690 我…

C++-9

C 1.已知C风格的字符串&#xff0c;完成对字符串通过下标访问时的异常处理机制(越界访问) 2.写一个程序&#xff0c;程序包含两个类&#xff0c;类中实现一个成员函数&#xff0c;MyGetChar(), 类A中每调用一 次&#xff0c;按顺序得到一个数字字符&#xff0c;比如第-次调用得…

哪个品牌的开放式耳机好用?五款畅销拔尖爆款力荐!

在耳机市场上&#xff0c;开放式耳机正逐渐成为一股新的风潮。它们以其独特的设计和卓越的音质吸引着越来越多的耳机爱好者。相较于传统的蓝牙耳机&#xff0c;开放式耳机不仅在音质上更胜一筹&#xff0c;更在佩戴舒适度上取得了显著突破。传统的蓝牙耳机&#xff0c;由于多采…

LeetCode746:使用最小花费爬楼梯

题目描述 给你一个整数数组 cost &#xff0c;其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用&#xff0c;即可选择向上爬一个或者两个台阶。 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。 请你计算并返回达到楼梯顶部的最低花费。 代码 …

C/C++ BM33 二叉树的镜像

文章目录 前言题目解决方案一1.1 思路阐述1.2 源码 总结 前言 镜像说的好听&#xff0c;无非就是换下节点。 题目 操作给定的二叉树&#xff0c;将其变换为源二叉树的镜像。 数据范围&#xff1a;二叉树的节点数 0 ≤ n ≤ 1000 0≤n≤1000 0≤n≤1000&#xff0c; 二叉树每…

AIGC实战——多模态模型DALL.E 2

AIGC实战——多模态模型DALL.E 2 0. 前言1. 模型架构2. 文本编码器3. CLIP4. 先验模型4.1 自回归先验模型4.2 扩散先验模型 5. 解码器5.1 GLIDE5.2 上采样器 6. DALL.E 2 应用6.1 图像变体6.2 先验模型的重要性6.3 DALL.E 2 限制 小结系列链接 0. 前言 DALL.E 2 是 OpenAI 设计…

Apache Knox 2.0.0使用

目录 介绍 使用 gateway-site.xml users.ldif my_hdfs.xml my_yarn.xml 其它 介绍 The Apache Knox Gateway is a system that provides a single point of authentication and access for Apache Hadoop services in a cluster. The goal is to simplify Hadoop securit…

深圳比创达电子|EMI一站式解决方案:提升企业电磁兼容性的路径

随着电子技术的快速发展&#xff0c;电磁干扰&#xff08;EMI&#xff09;问题日益凸显&#xff0c;对电子设备的正常运行和性能稳定造成了严重影响。为了有效应对这一挑战&#xff0c;EMI一站式解决方案应运而生&#xff0c;成为众多企业和个人解决EMI问题的首选方案。 一、E…