Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
文件系统
关于DFS中CLOSE失败后处理方式的一些看法
5.00
发布于 2023-08-03 13:41:42 浏览:1180
订阅该版
前两天项目中出现一个情况: 运行过程中需要通过文件记录一些数据,这些文件是存在SD卡中的,而SD卡会被拔出然后再插入。然而再次插入后发现读不出数据了。经过排查发现是由于需要记录数据,设备开机会打开文件,并且保持打开的状态,一旦检测到SD卡被拔出会自动关闭文件。但是由于SD卡已经被拔出,所以关闭文件是必然失效的。所以导致读不出数据。 针对上述问题,第一个想到的方案就是文件系统被重新挂载(SD卡重新插入)的时候再次打开一次文件,这也是可行的,但是先前打开的 `fd` 呢,是否在调用 `close` 的时候就会被释放? 很不幸,当 `close` 失败时,`DFS` 并不会释放这个 `fd` 及其所占用的资源。**并且由于在上述情况下 `close` 永远不会成功,所以这部分资源永远不会被释放。** 这一点是很致命的,因为无论你做什么操作都无法释放这一部分的内存,即使通过新打开一个文件的方式可以避免无法读取数据,但是随着热插拔的次数增多,泄漏的 `fd` 也会增加,直到达到上限无法再打开新的文件,或者在这之前内存已经到达上限导致系统无法正常运行。 当然出现上述问题的根本原因是 `close` 失败了,因此我们应该思考当 `close` 失败的时候,分配的资源到底要不要释放。 在我遇到的情况中,`close` 失败后我除了记录一个错误或提示出来之外没有任何办法去做实际的处理,因为这个文件描述符无法再恢复,即使拔了SD卡再插入,也是无效的描述符,并不会被文件系统识别。此时我能做的也就是**抛弃原来的文件描述符**,并且重新打开。反应到程序里也就是我希望 `close` 不管能不能成功,都要释放资源,因为即使不成功,我也没办法再次让他成功。或者还有另一种方式,就是提供一个 `force close` 的接口,能够强制关闭并释放资源。但实际好像并没有类似的接口。 在查阅了关于 `close` 的一些资料后发现如下一段文字: > A careful programmer will check the return value of close(), since it is quite possible that errors on a previous write(2) operation are reported only on the final close() that releases the open file description. Failing to check the return value when closing a file may lead to silent loss of data. This can especially be observed with NFS and with disk quota. > Note, however, that a failure return should be used only for diagnostic purposes (i.e., a warning to the application that there may still be I/O pending or there may have been failed I/O) or remedial purposes (e.g., writing the file once more or creating a backup). > Retrying the close() after a failure return is the wrong thing to do, since this may cause a reused file descriptor from another thread to be closed. This can occur because the Linux kernel always releases the file descriptor early in the close operation, freeing it for reuse; the steps that may return an error, such as flushing data to the filesystem or device, occur only later in the close operation. 摘自:https://man7.org/linux/man-pages/man2/close.2.html 由上述文字的最后一段可以看到在 Linux 内核中 `close` 是不会根据操作是否成功来决定是否要释放资源的,只要调用 `close` 就会对文件描述符的资源进行释放。该操作和我设想的是一致的。 为了再次印证我的猜想,我查阅了 Linux 的内核代码,最终在 `open.c` 中发现: ```c int filp_close(struct file *filp, fl_owner_t id) { int retval = 0; if (CHECK_DATA_CORRUPTION(file_count(filp) == 0, "VFS: Close: file count is 0 (f_op=%ps)", filp->f_op)) { return 0; } if (filp->f_op->flush) retval = filp->f_op->flush(filp, id); if (likely(!(filp->f_mode & FMODE_PATH))) { dnotify_flush(filp, id); locks_remove_posix(filp, id); } fput(filp); return retval; } ``` 可以看到这里面不论 `flush` 成功或者失败,`filp` 都会被释放。也进一步证实了在 Linux 中 `close` 是通过强制释放资源来避免产生资源的泄漏的。 综上,在RTT中我认为也可以使用这种方式,无论 `close` 成功与否,都要释放资源,毕竟一旦失败,我也没有任何办法能使其恢复。 相关PR: https://github.com/RT-Thread/rt-thread/pull/7907
4
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
WKJay
wkjay.com
文章
10
回答
135
被采纳
24
关注TA
发私信
相关文章
1
【文件系统】目录查询
2
文件系统Posix 接口 的close API疑问
3
dfs_mount挂载文件系统路径的路径必须为‘/’才能成功
4
SD卡连续读写文件报错
5
文件系统挂载断言机制
6
文件系统是否支持挂载NFS网络文件系统
7
文件系统挂载失败!!!
8
dfs_filesystem_lookup() 返回NULL
9
webnet 是否可以做全动态网页,使用内存池来加快速度
10
“文件系统装在表”报错
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
cubemx
PWM
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
812
个答案
177
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
2
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部