先获取存储类设备再找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 "/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", §or_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盘的正确大小(以字节为单位)。文章来源:https://www.toymoban.com/news/detail-682683.html
请注意,代码中的udev库函数仅适用于Linux系统,并假定系统中存在U盘设备。在其他操作系统或特定环境中,可能需要使用不同的方法来获取U盘大小。文章来源地址https://www.toymoban.com/news/detail-682683.html
到了这里,关于Linux通过libudev获取挂载路径、监控U盘热拔插事件、U盘文件系统类型的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!