【linux编程】linux文件IO的系统函数(close/read/fcntl/dup/dup2)-CSDN博客
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
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_RDONLYO_WRONLYO_RDWR和文件的打开方式O_APPENDO_NONBLOCKO_SYNC等。
F_SETFL设置文件描述符fd的文件状态标志arg参数是要设置的标志的值。注意只能改变文件打开方式的标志不能改变文件的访问模式。
F_GETLKF_SETLKF_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); //复制文件描述符指定新的文件描述符的最小值为10
if (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;
}