【linux编程】linux文件IO的系统函数(close/read/fcntl/dup/dup2)

2023-11-06 04:44

本文主要是介绍【linux编程】linux文件IO的系统函数(close/read/fcntl/dup/dup2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

close函数

  • 函数原型:
#include <unistd.h>
int close(int fd);
  • 参数:fd:要关闭的文件描述符

  • 返回值:成功返回0,失败返回-1并设置errno

  • 功能:关闭一个已经打开的文件,释放相关的资源。在Linux中,文件包括普通文件,目录,设备文件,管道,套接字等。每个打开的文件都有一个唯一的文件描述符,用来标识该文件。当不再需要使用一个文件时,应该调用close函数来关闭文件,否则可能会导致资源泄露,文件被占用,或者达到打开文件的上限。close函数会将文件描述符和文件表项的关联解除,如果该文件表项的引用计数变为0,表示没有其他文件描述符指向该文件,那么该文件表项也会被释放。如果该文件是一个套接字,那么close函数还会发送一个FIN包给对方,表示结束通信。close函数通常会在文件操作完成后调用,或者在程序退出前调用。

  • 代码示例:打开一个名为test.txt的文件,读取文件内容,然后关闭文件。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>int main()
{int fd; //定义一个文件描述符char buffer[100]; //定义一个缓冲区fd = open("test.txt", O_RDONLY); //以只读方式打开文件if (fd == -1) //判断文件是否打开成功{perror("open"); //打印错误信息exit(1); //退出程序}read(fd, buffer, 10); //从文件中读取10个字节到缓冲区printf("读取的数据是: %s\n", buffer); //打印缓冲区内容close(fd); //关闭文件return 0;
}

read函数

函数原型:

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

参数:

  • fd:要读取的文件的描述符
  • buf:指定的缓冲区的地址
  • count:指定的要读取的字节数

返回值:

实际读取的字节数,如果出错则返回-1并设置errno,如果到达文件末尾则返回0

功能:

从一个打开的文件中读取数据,将数据存储到指定的缓冲区中。read函数通常会从文件的当前偏移量处开始读取数据,并使偏移量增加读取的字节数。如果读取的字节数小于指定的字节数,可能是因为到达文件末尾,或者遇到了中断,或者读取的是一个管道或套接字等非常规文件。

代码示例:

打开一个名为test.txt的文件,读取10个字节的数据到缓冲区,并打印出来。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>int main()
{int fd; //定义一个文件描述符char buffer[100]; //定义一个缓冲区fd = open("test.txt", O_RDONLY); //以只读方式打开文件if (fd == -1) //判断文件是否打开成功{perror("open"); //打印错误信息exit(1); //退出程序}read(fd, buffer, 10); //从文件中读取10个字节到缓冲区printf("读取的数据是: %s\n", buffer); //打印缓冲区内容close(fd); //关闭文件return 0;
}

fcntl函数

函数原型:

#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );

参数:

  • fd:要操作的文件的描述符
  • cmd:要执行的控制命令
  • arg:可选的,根据不同的命令有不同的含义

fcntl函数支持的控制命令有很多,这里只介绍一些常用的,更多的可以参考[fcntl(2)的手册页]:

F_DUPFD:复制文件描述符fd,并返回一个新的文件描述符,该描述符的值是大于或等于arg的最小值。新的文件描述符和原来的文件描述符共享同一个文件表项,但是有自己的文件描述符标志,且默认设置为FD_CLOEXEC。这个命令相当于dup函数的功能,但是可以指定新的文件描述符的最小值。

F_GETFD:获取文件描述符fd的文件描述符标志,返回该标志的值。目前只有一个标志FD_CLOEXEC,表示在执行exec类函数时,关闭该文件描述符。

F_SETFD:设置文件描述符fd的文件描述符标志,arg参数是要设置的标志的值。目前只能设置FD_CLOEXEC标志。

F_GETFL:获取文件描述符fd的文件状态标志,返回该标志的值。文件状态标志包括文件的访问模式(O_RDONLY,O_WRONLY,O_RDWR)和文件的打开方式(O_APPEND,O_NONBLOCK,O_SYNC等)。

F_SETFL:设置文件描述符fd的文件状态标志,arg参数是要设置的标志的值。注意,只能改变文件打开方式的标志,不能改变文件的访问模式。

F_GETLK,F_SETLK,F_SETLKW:这些命令用来获取、设置或释放文件的记录锁。arg参数是一个指向struct flock结构体的指针,该结构体定义了锁的类型、起始位置、长度和持有者等信息。F_GETLK命令用来检测是否能够对文件加上指定的锁,如果能够加锁,返回0,如果不能加锁,返回-1并设置errno为EACCES或EAGAIN,并且将arg指向的结构体填充为已存在的锁的信息。F_SETLK命令用来对文件加上或释放指定的锁,如果能够加锁或解锁,返回0,如果不能加锁或解锁,返回-1并设置errno为EACCES或EAGAIN。F_SETLKW命令和F_SETLK命令类似,但是如果不能立即加锁或解锁,会阻塞直到能够完成操作或被信号中断。文件的记录锁可以用来实现对文件的互斥访问或协调访问,更多的细节可以参考[文件锁的手册页]。

返回值:根据不同的命令有不同的含义,一般来说,成功时返回非负值,失败时返回-1并设置errno功能:对已经打开的文件进行各种控制操作,比如改变文件的访问模式,获取或设置文件的状态标志,获取或设置文件的锁等。

代码示例:打开一个名为test.txt的文件,获取其文件状态标志,将其设置为非阻塞模式,然后复制一个新的文件描述符,该描述符的值不小于10。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>int main()
{int fd; //定义一个文件描述符int flag; //定义一个文件状态标志int fd2; //定义一个新的文件描述符fd = open("test.txt", O_RDWR); //以读写方式打开文件if (fd == -1) //判断文件是否打开成功{perror("open"); //打印错误信息exit(1); //退出程序}flag = fcntl(fd, F_GETFL); //获取文件状态标志if (flag == -1) //判断是否获取成功{perror("fcntl"); //打印错误信息exit(1); //退出程序}printf("文件状态标志是: %d\n", flag); //打印文件状态标志flag |= O_NONBLOCK; //将文件状态标志设置为非阻塞模式if (fcntl(fd, F_SETFL, flag) == -1) //设置文件状态标志{perror("fcntl"); //打印错误信息exit(1); //退出程序}printf("文件状态标志已设置为非阻塞模式\n"); //打印提示信息fd2 = fcntl(fd, F_DUPFD, 10); //复制文件描述符,指定新的文件描述符的最小值为10if (fd2 == -1) //判断是否复制成功{perror("fcntl"); //打印错误信息exit(1); //退出程序}printf("新的文件描述符是: %d\n", fd2); //打印新的文件描述符//后续的读写操作//...close(fd); //关闭文件close(fd2); //关闭新的文件描述符return 0;
}

dup函数

  • 函数原型:
#include <unistd.h>
int dup(int oldfd);
  • 参数:oldfd:要复制的文件描述符

  • 返回值:新的文件描述符,如果出错则返回-1并设置errno

  • 功能:复制一个文件描述符,并返回一个新的文件描述符,该描述符的值是当前可用的最小值。新的文件描述符和原来的文件描述符共享同一个文件表项,但是有自己的文件描述符标志,且默认设置为FD_CLOEXEC。dup函数相当于调用fcntl函数并传入F_DUPFD命令和0作为arg参数,但是更简洁。dup函数可以用来重定向标准输入、输出或错误,或者创建一个和已有文件描述符功能相同但值不同的文件描述符。

  • 代码示例:打开一个名为test.txt的文件,复制一个新的文件描述符,将标准输出重定向到该文件,然后打印一些信息。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>int main()
{int fd; //定义一个文件描述符int fd2; //定义一个新的文件描述符fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666); //以写入、创建、截断的方式打开文件if (fd == -1) //判断文件是否打开成功{perror("open"); //打印错误信息exit(1); //退出程序}fd2 = dup(fd); //复制文件描述符if (fd2 == -1) //判断是否复制成功{perror("dup"); //打印错误信息exit(1); //退出程序}close(fd); //关闭原来的文件描述符dup2(fd2, STDOUT_FILENO); //将标准输出重定向到新的文件描述符printf("这些信息将被写入到文件中\n"); //打印一些信息printf("新的文件描述符是: %d\n", fd2); //打印新的文件描述符close(fd2); //关闭新的文件描述符return 0;
}

dup2函数

  • 函数原型:
#include <unistd.h>
int dup2(int oldfd, int newfd);
  • 参数:

    • oldfd:要复制的文件描述符
    • newfd:要指定的新的文件描述符
  • 返回值:新的文件描述符,如果出错则返回-1并设置errno

  • 功能:和dup函数类似,也可以用来复制一个文件描述符,并返回一个新的文件描述符,但是可以指定新的文件描述符的值。如果新的文件描述符已经打开,则先关闭它。dup2函数相当于调用close函数和fcntl函数并传入F_DUPFD命令和newfd作为arg参数,但是更简洁。dup2函数也可以用来重定向标准输入、输出或错误,或者创建一个和已有文件描述符功能相同但值不同的文件描述符。

  • 代码示例:打开一个名为test.txt的文件,将标准输出重定向到该文件,然后打印一些信息。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>int main()
{int fd; //定义一个文件描述符fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666); //以写入、创建、截断的方式打开文件if (fd == -1) //判断文件是否打开成功{perror("open"); //打印错误信息exit(1); //退出程序}dup2(fd, STDOUT_FILENO); //将标准输出重定向到文件描述符printf("这些信息将被写入到文件中\n"); //打印一些信息printf("文件描述符是: %d\n", fd); //打印文件描述符close(fd); //关闭文件描述符return 0;
}

这篇关于【linux编程】linux文件IO的系统函数(close/read/fcntl/dup/dup2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/354541

相关文章

MySQL的JDBC编程详解

《MySQL的JDBC编程详解》:本文主要介绍MySQL的JDBC编程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、前置知识1. 引入依赖2. 认识 url二、JDBC 操作流程1. JDBC 的写操作2. JDBC 的读操作总结前言本文介绍了mysq

防止Linux rm命令误操作的多场景防护方案与实践

《防止Linuxrm命令误操作的多场景防护方案与实践》在Linux系统中,rm命令是删除文件和目录的高效工具,但一旦误操作,如执行rm-rf/或rm-rf/*,极易导致系统数据灾难,本文针对不同场景... 目录引言理解 rm 命令及误操作风险rm 命令基础常见误操作案例防护方案使用 rm编程 别名及安全删除

Linux下MySQL数据库定时备份脚本与Crontab配置教学

《Linux下MySQL数据库定时备份脚本与Crontab配置教学》在生产环境中,数据库是核心资产之一,定期备份数据库可以有效防止意外数据丢失,本文将分享一份MySQL定时备份脚本,并讲解如何通过cr... 目录备份脚本详解脚本功能说明授权与可执行权限使用 Crontab 定时执行编辑 Crontab添加定

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

JWT + 拦截器实现无状态登录系统

《JWT+拦截器实现无状态登录系统》JWT(JSONWebToken)提供了一种无状态的解决方案:用户登录后,服务器返回一个Token,后续请求携带该Token即可完成身份验证,无需服务器存储会话... 目录✅ 引言 一、JWT 是什么? 二、技术选型 三、项目结构 四、核心代码实现4.1 添加依赖(pom

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

基于Python实现自动化邮件发送系统的完整指南

《基于Python实现自动化邮件发送系统的完整指南》在现代软件开发和自动化流程中,邮件通知是一个常见且实用的功能,无论是用于发送报告、告警信息还是用户提醒,通过Python实现自动化的邮件发送功能都能... 目录一、前言:二、项目概述三、配置文件 `.env` 解析四、代码结构解析1. 导入模块2. 加载环

linux系统上安装JDK8全过程

《linux系统上安装JDK8全过程》文章介绍安装JDK的必要性及Linux下JDK8的安装步骤,包括卸载旧版本、下载解压、配置环境变量等,强调开发需JDK,运行可选JRE,现JDK已集成JRE... 目录为什么要安装jdk?1.查看linux系统是否有自带的jdk:2.下载jdk压缩包2.解压3.配置环境

Linux搭建ftp服务器的步骤

《Linux搭建ftp服务器的步骤》本文给大家分享Linux搭建ftp服务器的步骤,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录ftp搭建1:下载vsftpd工具2:下载客户端工具3:进入配置文件目录vsftpd.conf配置文件4: