应用开发中stat函数获取文件类型

问题描述:

在增加icm20608的驱动程序后,iio子系统中不只有ap3216c一个iio设备,(之前是直接通过绝对路径的iio:device0这个路径进行索引),这时候需要更改应用程序来扫描iio设备文件夹下的所有iio设备的name来进行路径匹配。

基本思路就是在iio驱动设备的路径中挨个进入,匹配name是不是设置好的“ap3216c”,为了提高效率,需要跳过“.”和“..”目录。程序如下:

bool find_ap3216c_device() {
     const char *base_path = "/sys/bus/iio/devices/";
     DIR *dir = opendir(base_path);
     if (dir == NULL) {
         printf("Cannot open directory: %s\n", base_path);
         return false;
     }
     
     struct dirent *entry;
     
     while ((entry = readdir(dir)) != NULL) {
         // 调试输出 d_type 的值
         printf("Entry: %s, d_type: %d\n", entry->d_name, entry->d_type);
 ​
         // 检查 d_type 是否为目录
         if (entry->d_type == DT_DIR && strncmp(entry->d_name, "iio:device", 10) == 0) {
             printf("Found iio:device directory: %s\n", entry->d_name);
             // 构建name文件的路径
             char name_file[256];
             snprintf(name_file, sizeof(name_file), "%s%s/name", base_path, entry->d_name);
 ​
             char name[50];
             if (file_data_read(name_file, name, sizeof(name)) == 0) {
                 printf("Device found: %s\n", name);  // 输出调试信息
                 if (strcmp(name, "ap3216c") == 0) {
                     // 找到设备,保存路径
                     snprintf(device_path, sizeof(device_path), "%s%s/", base_path, entry->d_name);
                     closedir(dir);
                     return true;
                 } else {
                     printf("name error: %s\n", name);  // 打印不匹配的设备名
                 }
             } else {
                 printf("name read error for %s!\n", name_file);
             }
         } else {
             printf("Skipping non-directory or non-iio:device entry: %s\n", entry->d_name);
         }
     }
     
     closedir(dir);
     return false;
 }

在匹配name的过程中,由于目标目录没有被成功识别为目录,导致一直无法进入构建name文件路径那一步,随后增加调试输出,在检查d_type是否正确前将d_type输出查看。

Entry: ., d_type: 4 Skipping non-directory or non-iio:device entry: . Entry: .., d_type: 4 Skipping non-directory or non-iio:device entry: .. Entry: iio:device0, d_type: 10 Skipping non-directory or non-iio:device entry: iio:device0 AP3216C device not found!

发现目标文件夹的类型为10,是符号链接 (DT_LNK),并不是我们设置的DT_DIR,导致原代码未能正确识别。

符号链接就类似于一个指针,它指向系统中的其他文件或目录。

问题解决:

解决就很简单了,可以使用stat函数来判断符号链接的指向是否为一个目录类型。

通过 stat 函数,可以获取文件或目录的元数据信息,包括文件的类型、大小、权限等。通过S_ISDIR(st.st_mode)这个宏,来判断 st_mode 字段中的文件类型信息是否表示目录。如果 stat 成功且目标是目录,S_ISDIR 将返回 true。另外无论是符号链接还是普通目录,stat 函数都可以用于判断文件或目录的类型,也就意味着如果目标文件是正常的目录stat函数也可以获得正确的结果。

正确代码:

bool find_ap3216c_device() {
    const char *base_path = "/sys/bus/iio/devices/";
    DIR *dir = opendir(base_path);
    if (dir == NULL) {
        printf("Cannot open directory: %s\n", base_path);
        return false;
    }

    struct dirent *entry;

    while ((entry = readdir(dir)) != NULL) {
        // 调试输出 d_type 的值
        printf("Entry: %s, d_type: %d\n", entry->d_name, entry->d_type);

        // 检查 d_type 是否为目录
        if (entry->d_type == DT_DIR && strncmp(entry->d_name, "iio:device", 10) == 0) {
            printf("Found iio:device directory: %s\n", entry->d_name);
            // 构建name文件的路径
            char name_file[256];
            snprintf(name_file, sizeof(name_file), "%s%s/name", base_path, entry->d_name);

            char name[50];
            if (file_data_read(name_file, name, sizeof(name)) == 0) {
                printf("Device found: %s\n", name);  // 输出调试信息
                if (strcmp(name, "ap3216c") == 0) {
                    // 找到设备,保存路径
                    snprintf(device_path, sizeof(device_path), "%s%s/", base_path, entry->d_name);
                    closedir(dir);
                    return true;
                } else {
                    printf("name error: %s\n", name);  // 打印不匹配的设备名
                }
            } else {
                printf("name read error for %s!\n", name_file);
            }
        } else {
            printf("Skipping non-directory or non-iio:device entry: %s\n", entry->d_name);
        }
    }

    closedir(dir);
    return false;
}

更改后,应用就可以快速的匹配iio驱动,并跳过“.”和“..”目录:

Skipping non-directory or non-iio:device entry: .
Skipping non-directory or non-iio:device entry: ..
Device found: ap3216c

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值