Linux通过libudev获取挂载路径、监控U盘热拔插事件、U盘文件系统类型

文章目录

先获取存储类设备再找USB设备,再获取挂载路径

udev_enumerate_add_match_subsystem函数的参数是用来设置子系统的过滤条件。通过添加不同的子系统过滤条件,可以过滤出指定子系统下的设备。

在示例代码中,udev_enumerate_add_match_subsystem(enumerate, “block”)用于添加"block"子系统的过滤条件,而udev_enumerate_add_match_subsystem(enumerate, “usb”)用于添加"usb"子系统的过滤条件。

"block"子系统:该子系统用于表示块设备,例如硬盘、分区和USB存储设备等。通过设置"block"子系统的过滤条件,可以获取已挂载的块设备的信息,包括已挂载的USB存储设备的信息。

"usb"子系统:该子系统用于表示USB设备。通过设置"usb"子系统的过滤条件,可以获取所有与USB相关的设备信息,包括已挂载的USB设备的信息,如USB打印机、USB网卡和其他USB外设。

因此,如果你只想获取已挂载的USB设备的信息,应该使用udev_enumerate_add_match_subsystem(enumerate, “usb”)来设置过滤条件。

#include <stdio.h>
#include <libudev.h>

int main() {
    struct udev *udev;
    struct udev_enumerate *enumerate;
    struct udev_list_entry *devices, *entry;

    // 创建udev上下文
    udev = udev_new();
    if (!udev) {
        printf("Failed to create udev context\n");
        return 1;
    }

    // 创建udev枚举器
    enumerate = udev_enumerate_new(udev);
    if (!enumerate) {
        printf("Failed to create udev enumerator\n");
        udev_unref(udev);
        return 1;
    }

    // 设置枚举器过滤器为"block"子系统
    udev_enumerate_add_match_subsystem(enumerate, "block");
    udev_enumerate_scan_devices(enumerate);

    // 获取设备列表
    devices = udev_enumerate_get_list_entry(enumerate);

    // 遍历设备列表
    udev_list_entry_foreach(entry, devices) {
        const char *syspath = udev_list_entry_get_name(entry);
        struct udev_device *device = udev_device_new_from_syspath(udev, syspath);

        // 通过父设备的父设备来判断是否为USB设备
        struct udev_device *parent = udev_device_get_parent_with_subsystem_devtype(device, "usb", "usb_device");
        if (parent) {
            // 获取设备的类别信息
            const char *devclass = udev_device_get_property_value(device, "DEVTYPE");

            // 获取设备的挂载路径
            const char *devnode = udev_device_get_devnode(device);

            if (devclass && devnode) {
                printf("USB Device class: %s, Mount Path: %s\n", devclass, devnode);
            }
        }

        udev_device_unref(device);
    }

    // 释放资源
    udev_enumerate_unref(enumerate);
    udev_unref(udev);

    return 0;
}

“USB Device class: partition” 表示这个USB设备是一个分区。通常情况下,当一个USB存储设备(例如USB闪存驱动器或移动硬盘)被连接到计算机时,它会被分为一个或多个分区。每个分区都会被系统视为一个独立的设备。这里的 “USB Device class: partition” 提示你当前所参考的USB设备是一个分区。

每个分区都会拥有自己的挂载路径,并且可以像独立的存储设备一样使用。通过访问分区的挂载路径,你可以读取和写入分区上的数据。通常,分区将被命名为类似 “/dev/sdXn” 的路径,其中 “X” 表示设备号,“n” 表示分区号。举个例子,“/dev/sdb1” 表示设备号为 “sdb” 的USB设备上的第一个分区。

在这里插入图片描述

#include <stdio.h>
#include <libudev.h>

int main() {
    struct udev *udev;
    struct udev_enumerate *enumerate;
    struct udev_list_entry *devices, *entry;

    // 创建udev上下文
    udev = udev_new();
    if (!udev) {
        printf("Failed to create udev context\n");
        return 1;
    }

    // 创建udev枚举器
    enumerate = udev_enumerate_new(udev);
    if (!enumerate) {
        printf("Failed to create udev enumerator\n");
        udev_unref(udev);
        return 1;
    }

    // 设置枚举器过滤器为"block"子系统
    udev_enumerate_add_match_subsystem(enumerate, "block");
    udev_enumerate_scan_devices(enumerate);

    // 获取设备列表
    devices = udev_enumerate_get_list_entry(enumerate);

    // 遍历设备列表
    udev_list_entry_foreach(entry, devices) {
        const char *syspath = udev_list_entry_get_name(entry);
        struct udev_device *device = udev_device_new_from_syspath(udev, syspath);

        // 通过父设备的父设备来判断是否为USB设备
        struct udev_device *parent = udev_device_get_parent_with_subsystem_devtype(device, "usb", "usb_device");
        if (parent) {
            // 获取设备的类别信息
            //const char *devclass = udev_device_get_property_value(device, "DEVTYPE");
            const char *devclass = udev_device_get_property_value(device, "ID_FS_TYPE");

            // 获取设备的挂载路径
            const char *devnode = udev_device_get_devnode(device);

            if (devclass && devnode) {
                printf("USB Device class: %s, Mount Path: %s\n", devclass, devnode);
            }
        }

        udev_device_unref(device);
    }

    // 释放资源
    udev_enumerate_unref(enumerate);
    udev_unref(udev);

    return 0;
}

在这里插入图片描述
udev_device_get_property_value(device, “ID_FS_TYPE”) 和 udev_device_get_property_value(device, “DEVTYPE”) 是用于获取设备属性值的函数。

udev_device_get_property_value(device, “ID_FS_TYPE”) 用于获取设备的文件系统类型(例如ext4、NTFS等)。该属性通常用于识别设备上的文件系统。

udev_device_get_property_value(device, “DEVTYPE”) 用于获取设备的类型,它可能会返回与设备相关的特定类型,例如 disk、partition、usb_device 等。这个属性可以用于确定设备的大致类型。

在使用这两个函数时,请确保 device 是有效的 struct udev_device 对象。你可以在循环遍历设备列表时使用这些函数,例如在之前的示例代码中。

下面是一个例子,演示如何使用这两个函数来获取设备的文件系统类型和设备类型:

const char *fs_type = udev_device_get_property_value(device, "ID_FS_TYPE");
if (fs_type) {
    printf("File System Type: %s\n", fs_type);
}

const char *devtype = udev_device_get_property_value(device, "DEVTYPE");
if (devtype) {
    printf("Device Type: %s\n", devtype);
}

以上代码中,我们首先使用 udev_device_get_property_value 获取设备的文件系统类型,然后打印出来。接着,我们使用 udev_device_get_property_value 获取设备的类型,同样打印出来。

请注意,这些函数返回的属性值是动态分配的内存,使用后需要进行适当的释放,以防止内存泄漏。

获取挂载路径

#include <stdio.h>
#include <libudev.h>
#include <string.h>

int main() {
    struct udev *udev;
    struct udev_enumerate *enumerate;
    struct udev_list_entry *devices, *entry;

    // 创建udev上下文和设备枚举器
    udev = udev_new();
    if (!udev) {
        printf("Failed to create udev context\n");
        return 1;
    }

    enumerate = udev_enumerate_new(udev);
    if (!enumerate) {
        printf("Failed to create udev enumerate\n");
        udev_unref(udev);
        return 1;
    }

    // 添加匹配过滤器以选择块设备(U盘)
    udev_enumerate_add_match_subsystem(enumerate, "block");
    udev_enumerate_scan_devices(enumerate);
    devices = udev_enumerate_get_list_entry(enumerate);

    // 遍历设备列表并获取设备信息
    udev_list_entry_foreach(entry, devices) {
        const char *sys_path = udev_list_entry_get_name(entry);
        struct udev_device *dev = udev_device_new_from_syspath(udev, sys_path);
        const char *devnode = udev_device_get_devnode(dev);

        printf("Device node path: %s\n", udev_device_get_devnode(dev));
#if 0
        // 检查设备是否是U盘,可以根据需求添加其他判断条件
        if (udev_device_get_devtype(dev) && strcmp(udev_device_get_devtype(dev), "disk") == 0) {
            printf("U盘挂载路径:%s\n", devnode);
        }
#endif
        udev_device_unref(dev);
    }
    
  

    // 清理资源
    udev_enumerate_unref(enumerate);
    udev_unref(udev);

    return 0;
}

编译指令

gcc your_code.c -o your_executable -ludev

在这里插入图片描述
在这里插入图片描述

监控U盘热拔插事件

#include <stdio.h>
#include <libudev.h>
#include <string.h>

int main() {
    struct udev *udev;
    struct udev_enumerate *enumerate;
    struct udev_list_entry *devices, *entry;

    // 创建udev上下文和设备枚举器
    udev = udev_new();
    if (!udev) {
        printf("Failed to create udev context\n");
        return 1;
    }

struct udev_monitor *mon = udev_monitor_new_from_netlink(udev, "udev");
int fd = udev_monitor_get_fd(mon);

udev_monitor_filter_add_match_subsystem_devtype(mon, "block", NULL);
udev_monitor_enable_receiving(mon);

while (1) {
    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(fd, &fds);

    // 使用select函数等待设备事件
    if (select(fd+1, &fds, NULL, NULL, NULL) > 0) {
        if (FD_ISSET(fd, &fds)) {
            struct udev_device *dev = udev_monitor_receive_device(mon);
            if (dev) {
                const char *action = udev_device_get_action(dev);

                // 判断事件类型,处理U盘插入和移除事件
                if (strcmp(action, "add") == 0) {
                    printf("U盘插入\n");
                } else if (strcmp(action, "remove") == 0) {
                    printf("U盘移除\n");
                }

                udev_device_unref(dev);
            }
        }
    }
}

    // 清理资源
    udev_enumerate_unref(enumerate);
    udev_unref(udev);

    return 0;
}

在这里插入图片描述

libusb

#include <stdio.h>
#include <stdlib.h>
#include <libusb-1.0/libusb.h>
 static int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
        printf("device insert  \n");   
}  
int main(int argc, char **argv)
{
        libusb_hotplug_callback_handle hp;
        libusb_init (NULL);
        libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY,
                LIBUSB_HOTPLUG_MATCH_ANY, 0, hotplug_callback, NULL, &hp);
        while(1)
        {
                libusb_handle_events(NULL);
        }
        //libusb_hotplug_deregister_callback(hp);
} 

 
 

可以可检测设备热插拔

static int running = 1; // 控制主循环的全局变量  
  
// 热插拔回调函数  
static void LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data) {  
    switch (event) {  
        case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:  
            printf("Device inserted\n");  
            break;  
        case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:  
            printf("Device removed\n");  
            // 可以选择在这里设置running为0来退出主循环  
            // 但为了示例的连续性,我们保持运行  
            break;  
        default:  
            printf("Unknown hotplug event\n");  
            break;  
    }  
}  
  
int main(int argc, char **argv) {  
    libusb_context *ctx = NULL;  
    libusb_hotplug_callback_handle hp;  
    int r;  
  
    // 初始化libusb  
    r = libusb_init(&ctx);  
    if (r < 0) {  
        fprintf(stderr, "Failed to initialize libusb: %s\n", libusb_error_name(r));  
        return 1;  
    }  
  
    // 注册热插拔回调  
    r = libusb_hotplug_register_callback(ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,  
                                         LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,  
                                         LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL, &hp);  
    if (r < 0) {  
        fprintf(stderr, "Failed to register hotplug callback: %s\n", libusb_error_name(r));  
        libusb_exit(ctx);  
        return 1;  
    }  
  
    // 主循环,处理事件  
    printf("Waiting for hotplug events...\n");  
    while (running) {  
        libusb_handle_events(ctx);  
        // 这里添加sleep是为了减少CPU使用率,可以根据需要调整时间  
        sleep(1);  
    }  
  
    // 清理  
    libusb_hotplug_deregister_callback(ctx, hp);  
    libusb_exit(ctx);  
  
    return 0;  
} 

循环检测热插拔

static int running = 1; // 控制主循环的全局变量  
 
// 热插拔回调函数  
static void LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data) {  
    if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {  
        struct libusb_device_descriptor desc;  
        int r;  
  
        // 获取设备描述符  
        r = libusb_get_device_descriptor(dev, &desc);  
        if (r < 0) {  
            fprintf(stderr, "Failed to get device descriptor: %s\n", libusb_error_name(r));  
            return;  
        }  
  
        // 打印PID和VID  
        printf("USB Device inserted: VID=0x%04X, PID=0x%04X\n", desc.idVendor, desc.idProduct);  
  
        // 获取并打印设备类(注意:这可能不是真正的设备类,因为复合设备可能报告为类9)  
        printf("Device Class: %d\n", desc.bDeviceClass);  
  
        // 获取并打印USB速度(注意:这需要打开设备)  
        libusb_device_handle *handle;  
        handle = libusb_open_device_with_vid_pid(ctx, desc.idVendor, desc.idProduct);  
        if (handle) {  
            int sspeed = libusb_get_device_speed(handle); 
            printf("USB Speed: %d   ",sspeed);  
            switch (sspeed) 
			{  
                case LIBUSB_SPEED_UNKNOWN:  
                    printf("Unknown\n");  
                    break;  
                case LIBUSB_SPEED_LOW:  
                    printf("Low Speed\n");  
                    break;  
                case LIBUSB_SPEED_FULL:  
                    printf("Full Speed\n");  
                    break;  
                case LIBUSB_SPEED_HIGH:  
                    printf("High Speed\n");  
                    break;  
                case LIBUSB_SPEED_SUPER:  
                    printf("SuperSpeed\n");  
                    break;  
                case LIBUSB_SPEED_SUPER_PLUS:  
                    printf("SuperSpeedPlus\n");  
                    break;  
            }  
            libusb_close(handle);  
        } 
		else 
		{  
            fprintf(stderr, "Failed to open device for speed check\n");  
        }  
    } 
	else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) 
	{  
        printf("USB Device removed\n");  
    }  
}  
  
int main(int argc, char **argv) {  
    libusb_context *ctx = NULL;  
    libusb_hotplug_callback_handle hp;  
    int r;  
  agin:
    // 初始化libusb  
    r = libusb_init(&ctx);  
    if (r < 0) {  
        fprintf(stderr, "Failed to initialize libusb: %s\n", libusb_error_name(r));  
        return 1;  
    }  
  
    // 注册热插拔回调  
    r = libusb_hotplug_register_callback(ctx,  
                                         LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,  
                                         LIBUSB_HOTPLUG_ENUMERATE,  
                                         LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,  
                                         LIBUSB_HOTPLUG_MATCH_ANY,  
                                         hotplug_callback, NULL, &hp);  
    if (r < 0) {  
        fprintf(stderr, "Failed to register hotplug callback: %s\n", libusb_error_name(r));  
        libusb_exit(ctx);  
        return 1;  
    }  
  
    // 主循环,处理事件  
    printf("Waiting for hotplug events...\n");  
    while (running) {  
        if(0==libusb_handle_events(ctx))
		{
			break;
		}  
        // 这里添加sleep是为了减少CPU使用率,可以根据需要调整时间  
        sleep(1);  
    }  
  
    // 清理  
    libusb_hotplug_deregister_callback(ctx, hp);  
    libusb_exit(ctx);  
  goto agin;
    return 0;  
} 

打印USB设备PIDVID

const char* speed_to_string(int speed) {  
    switch (speed) {  
        case LIBUSB_SPEED_LOW:  
            return "Low Speed";  
        case LIBUSB_SPEED_FULL:  
            return "Full Speed";  
        case LIBUSB_SPEED_HIGH:  
            return "High Speed";  
        case LIBUSB_SPEED_SUPER:  
            return "SuperSpeed";  
        case LIBUSB_SPEED_SUPER_PLUS:  
            return "SuperSpeedPlus";  
        default:  
            return "Unknown Speed";  
    }  
}  
  


void print_usb_device_info(libusb_device *dev) {  

    struct libusb_device_descriptor desc;  
    int r;  

    r = libusb_get_device_descriptor(dev, &desc);  
    if (r < 0) 
	{  
        fprintf(stderr, "Failed to get device descriptor\n");  
        return;  
    }  

  

    struct libusb_config_descriptor *config;  
    r = libusb_get_active_config_descriptor(dev, &config);  //获取活动状态

    if (r < 0) {  
        fprintf(stderr, "Failed to get active config descriptor\n");  
        return;
    }  

  

    printf("VID: 0x%04X, PID: 0x%04X, Class: %d, Speed: %s\n", desc.idVendor, desc.idProduct,desc.bDeviceClass,libusb_error_name(libusb_get_device_speed(dev)));
    // 在打印时使用这个函数  
    printf("Speed: %s\n", speed_to_string(libusb_get_device_speed(dev)));
    libusb_free_config_descriptor(config);  
 
}  

  

int main() {  

    libusb_context *ctx = NULL;  

    int r; // for return codes  

    r = libusb_init(&ctx); // Initialize the library  
    if (r < 0)  
        return r;  

    libusb_set_debug(ctx, 3); // Optional: Set verbosity level to 3  

    while (1) {  

        libusb_device_handle *handle;  

        libusb_device **devs;  

        ssize_t cnt = libusb_get_device_list(ctx, &devs); // Get the list of devices  找到的 USB 设备数量

        if (cnt < 0)  
            return (int)cnt;  

        ssize_t i = 0;  

        while ((size_t)i < cnt) {  
            libusb_device *dev = devs[i++];  
            print_usb_device_info(dev);  
        }  
        libusb_free_device_list(devs, 1); // Free the list, unref the devices in it  
        sleep(1); // Sleep for a second  
    }  

    libusb_exit(ctx); // Close the library  

    return 0;  
}

#include <stdio.h>
#include "/home/hty/Project/oneway_qt5/ui/oneway/onewaysendui_socket.new/libusb.h"
#include <assert.h>

#define VENDOR_ID        LIBUSB_HOTPLUG_MATCH_ANY  // U盘的厂商ID
#define PRODUCT_ID       LIBUSB_HOTPLUG_MATCH_ANY  // U盘的产品ID

#if 1
static int LIBUSB_CALL  usb_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data) 
{
   printf("\n\n12345235235\n\n");
   if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
            printf("U盘已插入\n");
            // 在这里执行U盘插入时的操作
        } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) {
            printf("U盘已拔出\n");
            // 在这里执行U盘拔出时的操作
        }
}


static int LIBUSB_CALL  usb_callback_in(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
   printf("\n\n12___________\n\n");

            printf("U盘已插入\n");
            // 在这里执行U盘插入时的操作
	fflush(stdout);
}

static int LIBUSB_CALL  usb_callback_out(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
   printf("\n\n12----------\n\n");

            printf("U盘已拔出\n");
            // 在这里执行U盘拔出
	fflush(stdout);
}

libusb_hotplug_callback_fn fn = usb_callback;
int main(void) 
{
    libusb_context *ctx = NULL;
    libusb_context *context = NULL;
    int rc = 0;

    rc = libusb_init(&ctx);

    assert(rc == 0);

    rc = libusb_has_capability( LIBUSB_CAP_HAS_HOTPLUG);

    if(rc!=0)
    {
     printf("capability\n");
    }
    //libusb_hotplug_callback_handle handle;
    //rc=libusb_hotplug_register_callback(ctx,  LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_ENUMERATE,VENDOR_ID, PRODUCT_ID, LIBUSB_HOTPLUG_MATCH_ANY, (libusb_hotplug_callback_fn)usb_callback, NULL, &handle);
    //rc=libusb_hotplug_register_callback(ctx,  LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_ENUMERATE,VENDOR_ID, PRODUCT_ID, 0, (libusb_hotplug_callback_fn)usb_callback, NULL, &handle);
      
      libusb_hotplug_callback_handle handle_in;
      libusb_hotplug_callback_handle handle_out;
      rc=libusb_hotplug_register_callback(ctx,  LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, LIBUSB_HOTPLUG_NO_FLAGS,LIBUSB_HOTPLUG_MATCH_ANY,LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, (libusb_hotplug_callback_fn)usb_callback_in, NULL, &handle_in);
      rc=libusb_hotplug_register_callback(ctx,  LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_NO_FLAGS, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, (libusb_hotplug_callback_fn)usb_callback_out, NULL, &handle_out);
//    libusb_exit(context);
    //    rc = libusb_hotplug_register_callback(handle);
    if (rc != 0) {
        fprintf(stderr, "Failed to register hotplug callback\n");
        libusb_exit(ctx);
        return rc;
    }
    printf("正在监听 U盘插拔事件...\n");

    while (1) 
    {
	rc =  libusb_handle_events(ctx);
	if (rc != LIBUSB_SUCCESS) 
	{
            fprintf(stderr, "libusb_handle_events() 出错:%s\n", libusb_strerror(rc));
            break;
        }
	printf("新事件产生了...\n");
     }
     //libusb_hotplug_deregister_callback(NULL,handle);
     libusb_hotplug_deregister_callback(NULL,handle_in);
     libusb_hotplug_deregister_callback(NULL,handle_out);
    return 0;
}

#else

static int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
        printf("device insert  \n");
}
int main(int argc, char **argv)
{
        libusb_hotplug_callback_handle hp;
        libusb_init (NULL);
        libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY,
                LIBUSB_HOTPLUG_MATCH_ANY, 0, hotplug_callback, NULL, &hp);
        while(1)
        {
                libusb_handle_events(NULL);
        }
        libusb_hotplug_deregister_callback(NULL,hp);
}

#endif

文件系统类型

#include <stdio.h>
#include <libudev.h>
#include <stdlib.h>
#include <string.h>

int main() {
    struct udev *udev = udev_new();
    if (!udev) {
        printf("Failed to initialize udev\n");
        return 1;
    }

    struct udev_enumerate *enumerate = udev_enumerate_new(udev);
    udev_enumerate_add_match_subsystem(enumerate, "block");
    udev_enumerate_scan_devices(enumerate);

    struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
    struct udev_list_entry *entry;
    udev_list_entry_foreach(entry, devices) {
        const char *path = udev_list_entry_get_name(entry);
        struct udev_device *dev = udev_device_new_from_syspath(udev, path);
        const char *devnode = udev_device_get_devnode(dev);
/*********************************************************************************/
        const char *fs_type = udev_device_get_property_value(dev, "ID_FS_TYPE");

        // Output the device node and file system type
        if (devnode && fs_type) {
            printf("Device: %s\n", devnode);
            printf("File System Type: %s\n", fs_type);
        }
/**********************************************************************************/
        udev_device_unref(dev);
    }

    udev_enumerate_unref(enumerate);
    udev_unref(udev);

    return 0;
}

在这里插入图片描述
在这里插入图片描述
这段代码使用 libudev 库,通过遍历 U 盘设备列表获取设备节点和文件系统类型。首先,使用 udev_new()函数初始化 udev 上下文,然后创建一个 udev_enumerate 对象,并设置匹配子系统为 “block”。接下来,使用 udev_enumerate_scan_devices() 函数扫描设备。然后,获取设备列表,并使用 udev_list_entry_foreach() 函数遍历列表。在遍历过程中,通过调用 udev_device_new_from_syspath() 函数根据设备的 syspath 创建一个 udev_device 对象。然后,使用 udev_device_get_devnode() 函数获取设备节点和 udev_device_get_property_value() 函数获取文件系统类型。最后,输出设备节点和文件系统类型。
通过挂载点获取挂载路径

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_PATH 256

char* get_usb_device_path(const char* mount_point) {
    FILE* fp;
    char* line = NULL;
    size_t len = 0;
    ssize_t read;
    char* device_path = NULL;

    // 打开 /proc/mounts 文件
    fp = fopen("/proc/mounts", "r");
    if (fp == NULL) {
        printf("Failed to open /proc/mounts\n");
        return NULL;
    }

    // 逐行读取 /proc/mounts 文件
    while ((read = getline(&line, &len, fp)) != -1) {
        char* token;
        char* saveptr = NULL;
        char* mount;
        char* device;

        // 解析挂载点和设备路径
        token = strtok_r(line, " ", &saveptr);
        mount = token;
        
        token = strtok_r(NULL, " ", &saveptr);
        device = token;

        // 如果挂载点匹配,保存设备路径
        if (strcmp(mount, mount_point) == 0) {
            device_path = strdup(device); // 保存设备路径的副本
            break;
        }
    }

    // 关闭文件和释放资源
    fclose(fp);
    if (line) {
        free(line);
    }

    return device_path;
}

int main() {
    const char* mount_point = "/dev/sdb1"; // 替换为你的挂载点

    char* device_path = get_usb_device_path(mount_point);

    if (device_path) {
        printf("USB Device Path: %s\n", device_path);
        free(device_path);
    } else {
        printf("USB device not found\n");
    }

    return 0;
}

在这里插入图片描述
添libudev加库

sudo apt-get install libudev-dev

挂载到指定挂载点

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>

int main() {
    char* device = "/dev/sdb1";    // U盘设备路径
    char* mountPoint = "/mnt/usb";  // 挂载点路径

char rmCmd[100];
snprintf(rmCmd, sizeof(rmCmd), "rm -rf %s", mountPoint);
if (system(rmCmd) == -1) {
    perror("Failed to remove existing directory");
    exit(1);
}
    // 创建挂载点目录
    if (mkdir(mountPoint, 0777) == -1) {
        perror("Failed to create mount point directory");
        exit(1);
    }

    // 执行挂载命令
    char mountCmd[100];
    snprintf(mountCmd, sizeof(mountCmd), "mount %s %s", device, mountPoint);
    if (system(mountCmd) == -1) {
        perror("Failed to mount USB device");
        exit(1);
    }

    printf("USB device successfully mounted at %s\n", mountPoint);

    return 0;
}


在这里插入图片描述
读取光驱

#include <stdio.h>
#include <libudev.h>

int main() {
    struct udev *udev = udev_new();
    if (!udev) {
        printf("Failed to create udev context\n");
        return -1;
    }

    struct udev_enumerate *enumerate = udev_enumerate_new(udev);
    udev_enumerate_add_match_subsystem(enumerate, "block");
    udev_enumerate_add_match_property(enumerate, "ID_BUS", "usb");
    udev_enumerate_scan_devices(enumerate);

    struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
    struct udev_list_entry *dev_list_entry;
    udev_list_entry_foreach(dev_list_entry, devices) {
        const char *path = udev_list_entry_get_name(dev_list_entry);
        struct udev_device *dev = udev_device_new_from_syspath(udev, path);

        const char *device_type = udev_device_get_devtype(dev);
        if (device_type && strncmp(device_type, "disk", 4) == 0) {
            const char *devnode = udev_device_get_devnode(dev);
            const char *device_model = udev_device_get_property_value(dev, "ID_MODEL");
            
            // 根据设备的模型或其它属性来判断该设备是否为USB光驱
            if (device_model && strstr(device_model, "光驱")) {
                printf("USB光驱设备:%s\n", devnode);

                // 在这里进行光驱设备的读取操作
                // ...
            }
        }

        udev_device_unref(dev);
    }

    udev_enumerate_unref(enumerate);
    udev_unref(udev);

    return 0;
}

上述代码使用libudev遍历系统中的块设备,并通过属性过滤出USB设备。然后通过设备模型(ID_MODEL)来判断是否为USB光驱设备。

你可以根据实际需要进一步使用光驱设备进行读取操作。请注意,在进行读取操作之前,你可能需要使用相应的文件操作(如open、read等)来访问光驱设备的内容。

获取U盘大大小
非常抱歉,我误解了您的问题。实际上,udev库提供的udev_device_get_sysattr_value()函数返回的是设备的属性值,其单位为扇区。要计算U盘的实际大小,需要将扇区数乘以扇区大小(通常为512字节)。

以下是修订过的代码,以获取U盘的准确大小(以字节为单位):

#include <stdio.h>
#include <libudev.h>

#define SECTOR_SIZE 512

int main() {
    // 创建udev上下文
    struct udev *udev = udev_new();
    if (!udev) {
        printf("无法创建udev上下文\n");
        return -1;
    }

    // 创建并初始化udev监视器
    struct udev_monitor *monitor = udev_monitor_new_from_netlink(udev, "udev");
    if (!monitor) {
        printf("无法创建udev监视器\n");
        return -1;
    }

    udev_monitor_filter_add_match_subsystem_devtype(monitor, "block", "disk");
    udev_monitor_enable_receiving(monitor);
    int fd = udev_monitor_get_fd(monitor);

    // 设置循环监听udev事件
    while (1) {
        fd_set fds;
        FD_ZERO(&fds);
        FD_SET(fd, &fds);

        if (select(fd + 1, &fds, NULL, NULL, NULL) > 0) {
            struct udev_device *dev = udev_monitor_receive_device(monitor);
            if (dev) {
                if (udev_device_get_devtype(dev) && strcmp(udev_device_get_devtype(dev), "disk") == 0) {
                    const char *device_node = udev_device_get_devnode(dev);
                    const char *device_name = udev_device_get_property_value(dev, "ID_FS_LABEL");
                    const char *device_sectors = udev_device_get_sysattr_value(dev, "size");

                    printf("设备节点: %s\n", device_node);
                    printf("设备名称: %s\n", device_name);

                    if (device_sectors) {
                        // 将设备扇区数从字符串转换为整数
                        unsigned long long sector_count;
                        sscanf(device_sectors, "%llu", &sector_count);

                        // 计算U盘大小(字节)
                        unsigned long long device_size = sector_count * SECTOR_SIZE;
                        printf("设备大小: %llu bytes\n", device_size);
                    } else {
                        printf("无法获取设备大小\n");
                    }
                }
                udev_device_unref(dev);
            }
        }
    }

    // 清理资源
    udev_monitor_unref(monitor);
    udev_unref(udev);

    return 0;
}

此示例代码中添加了一个常量SECTOR_SIZE,用于指定扇区的大小。它将用于将扇区数转换为字节数。通过这种方式,您应该能够获取U盘的正确大小(以字节为单位)。

请注意,代码中的udev库函数仅适用于Linux系统,并假定系统中存在U盘设备。在其他操作系统或特定环境中,可能需要使用不同的方法来获取U盘大小。

libusb读指定扇区
要基于 libusb 读取 U 盘的指定扇区,您需要执行以下步骤:

初始化 libusb 库。
找到并打开目标 U 盘设备。
发送 USB 控制传输命令以读取指定扇区的数据。
处理读取到的数据。
关闭设备,释放资源。
以下是一个简单的示例代码,演示如何使用 libusb 读取 U 盘的指定扇区:

#include <stdio.h>
#include <stdlib.h>
#include <libusb.h>

#define SECTOR_SIZE 512
#define TARGET_SECTOR 0 // 指定要读取的扇区号

int main() {
    libusb_context *ctx = NULL;
    libusb_device_handle *handle = NULL;
    uint8_t buffer[SECTOR_SIZE];

    if (libusb_init(&ctx) != 0) {
        fprintf(stderr, "Error initializing libusb\n");
        return 1;
    }

    handle = libusb_open_device_with_vid_pid(NULL, VENDOR_ID, PRODUCT_ID); // 替换为目标 U 盘的 VID 和 PID
    if (handle == NULL) {
        fprintf(stderr, "Error opening USB device\n");
        libusb_exit(ctx);
        return 1;
    }

    // 发送 USB 控制传输命令以读取指定扇区的数据
    int transferred;
    int result = libusb_control_transfer(handle, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
                                          LIBUSB_REQUEST_GET_DESCRIPTOR, 0x01, TARGET_SECTOR, buffer, SECTOR_SIZE, 1000);

    if (result < 0) {
        fprintf(stderr, "Error reading sector\n");
    } else {
        // 处理读取到的数据,存储在 buffer 中
        for (int i = 0; i < SECTOR_SIZE; i++) {
            printf("%02X ", buffer[i]);
            if ((i + 1) % 16 == 0) {
                printf("\n");
            }
        }
    }

    libusb_close(handle);
    libusb_exit(ctx);
    
    return 0;
}

请注意,上述代码中的 VENDOR_ID 和 PRODUCT_ID 需要替换为目标 U 盘的厂商ID和产品ID。此外,要正确读取 U 盘的指定扇区,您需要了解目标 U 盘的命令格式和通讯协议。在实际应用中,您可能需要对其进行进一步的调试和优化。

希望这个示例能帮助您开始使用 libusb 读取 U 盘的指定扇区。如果您有任何问题或需要进一步帮助,请随时告诉我。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用libudev库在Linux环境下监控光盘的入和拔出,可以按照以下步骤进行操作: 1. 引入必要的头文件: ```c #include <libudev.h> ``` 2. 初始化udev库和udev监视器: ```c struct udev *udev; struct udev_monitor *monitor; udev = udev_new(); if (!udev) { // 错误处理 return -1; } monitor = udev_monitor_new_from_netlink(udev, "udev"); if (!monitor) { // 错误处理 udev_unref(udev); return -1; } ``` 3. 设置监视器的过滤规则,以匹配光盘设备: ```c udev_monitor_filter_add_match_subsystem_devtype(monitor, "block", "cdrom"); ``` 4. 启动监视器: ```c udev_monitor_enable_receiving(monitor); ``` 5. 进入监视循环,等待光盘入和拔出事件的发生: ```c while (1) { struct udev_device *device; // 获取下一个udev事件 device = udev_monitor_receive_device(monitor); if (device) { const char* action = udev_device_get_action(device); const char* devnode = udev_device_get_devnode(device); if (action && strcmp(action, "add") == 0) { // 光盘事件处理 printf("光盘已入:%s\n", devnode); // 在这里执行您的操作 } else if (action && strcmp(action, "remove") == 0) { // 光盘拔出事件处理 printf("光盘已拔出:%s\n", devnode); // 在这里执行您的操作 } udev_device_unref(device); } } ``` 6. 释放资源: ```c udev_monitor_unref(monitor); udev_unref(udev); ``` 以上代码片段演示了如何使用libudev库来监控光盘设备的入和拔出事件。您可以根据实际需求进行适当的修改和扩展,以满足您的应用程序需求。请注意,在实际使用中,您可能还需要添加错误处理和其他必要的逻辑来完善代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值