name_to_handle_at函数和open_by_handle_at函数

本文详细介绍了Linux系统调用name_to_handle_at和open_by_handle_at的功能和使用,包括它们如何分开完成openat(2)的部分功能,以及struct file_handle结构体的使用。这两个调用涉及到文件句柄的获取和打开,同时讨论了挂载ID、文件句柄的透明性、符号链接处理和错误情况,如EOVERFLOW。文章提供了调用的参数解析和应用场景,适合Linux驱动和系统开发者阅读。
函数原型:
#define _GNU_SOURCE         /* See feature_test_macros(7) */
#include <fcntl.h>

int name_to_handle_at(int dirfd, const char *pathname,
                      struct file_handle *handle,
                      int *mount_id, int flags);
int open_by_handle_at(int mount_fd, struct file_handle *handle,
                      int flags);

name_to_handle_at()和open_by_handle_at()系统调用将openat(2)的功能分为两部分:

        name_to_handle_at(): 返回一个对应于指定文件的不透明句柄;

        open_by_handle_at(): 打开与前面调用name_to_handle_at()返回的句柄对应的文件,并返回一个打开的文件描述符。

struct file_handle结构体如下:

struct file_handle {
    unsigned int  handle_bytes;   /* Size of f_handle [in, out] */
    int           handle_type;    /* Handle type [out] */
    unsigned char f_handle[0];    /* File identifier (sized by
                                     caller) [out] */
};

调用者有责任分配一个足够大的结构来容纳f_handle返回的句柄。

在调用之前,应该初始化handle_bytes字段以包含为f_handle分配的大小。

(常量MAX_HANDLE_SZ在<fcntl.h>中定义,指定文件句柄的最大期望大小。由于未来的文件系统可能需要更多的空间,因此不能保证这个上限。)

成功返回后,handle_bytes字段被更新为包含实际写入f_handle的字节数。

调用者可以通过handle->handle_bytes为零,来发现file_handle结构所需的大小;

在这种情况下,调用失败并出现EOVERFLOW错误,handle->handle_bytes设置为指示所需的大小;

然后调用者可以使用这些信息来分配正确大小的结构。

这里需要注意的是,EOVERFLOW还可能表明,在通常支持文件句柄查找的文件系统中,这个特定名称没有可用的文件句柄。当返回EOVERFLOW错误而没有增加handle_bytes时,可以检测到这种情况。

除了使用handle_bytes字段之外,调用者应该将file_handle结构视为不透明的数据类型:

handle_type和f_handle字段可以在随后对open_by_handle_at()的调用中使用。

调用者还可以使用不透明的file_handle来比较在不同时间和可能在不同路径上查询的文件系统对象的标识

你当前的 `connect_to_wifi_task` 函数完成了从用户输入中获取 WiFi SSID 密码,并尝试连接的功能。但该函数存在一些可以优化的地方,比如: - **错误处理不够完善** - **缺乏重试机制** - **未清理之前可能存在的连接尝试** - **没有提供失败后重新进入 AP 模式的逻辑** --- ## ✅ 改进目标 我们希望改进后的 `connect_to_wifi_task` 函数具备以下特性: 1. 清理之前的 WiFi 配置(如果存在) 2. 正确设置新的配置并尝试连接 3. 如果连接失败,重新启动 AP 模式供用户重新配置 4. 增加详细的日志输出便于调试 --- ## ✅ 改进后的 `connect_to_wifi_task` 函数代码如下: ```c static void connect_to_wifi_task(void *pvParameters) { ESP_LOGI(TAG, "Delaying for 1 second to allow client to receive success page..."); vTaskDelay(pdMS_TO_TICKS(1000)); // 先停止可能运行的WiFi esp_wifi_stop(); vTaskDelay(pdMS_TO_TICKS(500)); // 等待关闭完成 // 设置为 Station 模式 ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); wifi_config_t wifi_config = {0}; strncpy((char *)wifi_config.sta.ssid, wifi_config_storage.ssid, sizeof(wifi_config.sta.ssid)); strncpy((char *)wifi_config.sta.password, wifi_config_storage.password, sizeof(wifi_config.sta.password)); wifi_config.sta.threshold.authmode = WIFI_AUTH_OPEN; // 可根据需要调整认证方式 ESP_LOGI(TAG, "Setting WiFi configuration for SSID: %s", wifi_config.sta.ssid); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); ESP_LOGI(TAG, "Starting WiFi connection..."); ESP_ERROR_CHECK(esp_wifi_start()); ESP_ERROR_CHECK(esp_wifi_connect()); // 等待连接结果或超时 EventBits_t bits = xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, pdTRUE, // Clear on exit pdFALSE, // Don't wait all bits pdMS_TO_TICKS(20000)); // 20秒超时 if (bits & WIFI_CONNECTED_BIT) { ESP_LOGI(TAG, "WiFi connected successfully!"); // 保存配置到 NVS nvs_handle_t nvs_handle; esp_err_t err = nvs_open("wifi_config", NVS_READWRITE, &nvs_handle); if (err == ESP_OK) { nvs_set_str(nvs_handle, "ssid", wifi_config_storage.ssid); nvs_set_str(nvs_handle, "password", wifi_config_storage.password); nvs_commit(nvs_handle); nvs_close(nvs_handle); ESP_LOGI(TAG, "WiFi configuration saved to NVS"); } else { ESP_LOGE(TAG, "Failed to open NVS for writing: %s", esp_err_to_name(err)); } vTaskDelete(NULL); return; } else { ESP_LOGE(TAG, "WiFi connection failed after timeout"); // 重启 AP 模式供用户重新配置 ESP_LOGI(TAG, "Restarting AP mode for reconfiguration..."); esp_wifi_stop(); vTaskDelay(pdMS_TO_TICKS(500)); init_wifi_ap(); xEventGroupWaitBits(wifi_event_group, AP_STARTED_BIT, pdFALSE, pdTRUE, portMAX_DELAY); start_webserver(); } vTaskDelete(NULL); } ``` --- ## 🔍 改进点详解 | 功能 | 描述 | |------|------| | `esp_wifi_stop()` | 在开始新连接前,确保之前的 WiFi 被正确关闭 | | 日志详细 | 输出关键步骤信息,方便调试分析问题 | | 连接失败后重启 AP 模式 | 用户无需手动复位设备即可重新配置 WiFi | | NVS 写入检查 | 增加了写入失败的日志提示 | | 使用 `pdMS_TO_TICKS(20000)` | 更合理的等待时间(20 秒)以避免过早判断失败 | --- ## 🧪 使用建议 你可以将此函数直接替换你原来的 `connect_to_wifi_task` 函数。 > ⚠️ 注意:确保你的全局变量 `wifi_config_storage`、`wifi_event_group` 事件标志 `WIFI_CONNECTED_BIT` 已经正确定义。 --- ##
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值