尝试使用 cpp 程序在 Linux 中挂载一个 usb 分区
Trying to mount a usb partition in Linux using a cpp program
我想检测一个usb连接并挂载它对应的分区。
我尝试使用 udev.I 能够在 /dev/bus/usb/001 or/002 中找到设备。但是从这里我找不到它使用的分区。因此,我使用 udev 搜索块分区并在添加分区时挂载。eg/dev/sda1。但这是一个临时解决方案。
我想要的是使用 udev 或其他东西检测 usb 连接并找到它拥有的分区并挂载它。
我的代码:
#include <libudev.h>
#include <stdio.h>
#include "dmutil.h"
#include <pthread.h>
#include <unistd.h>
/*
Thread which detects devices.
*/
void * udev_listener(void * i)
{
struct udev *udev;
udev = udev_new();
if (!udev) {
printf("Can't create udev\n");
exit(1);
}
std::string mount_path_for_udev_listner = DEFAULT_MOUNT_PATH;
printf("\n\n **********\nUdev_listner is asked to mount usb to %s ....",mount_path_for_udev_listner.c_str());
struct udev_device *dev;
struct udev_monitor *mon;
mon = udev_monitor_new_from_netlink(udev, "udev");
assert(mon != NULL);
/* int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor,const char *subsystem, const char *devtype);
filters to select messages that get delivered to a listener.
On Success it returns an integer greater than, or equal to, 0. On failure, a negative error code is returned.
*/
assert(udev_monitor_filter_add_match_subsystem_devtype(mon, "block", NULL) >=0);
udev_monitor_enable_receiving(mon);
/* Get the file descriptor (fd) for the monitor.
This fd will get passed to select() */
int fd = udev_monitor_get_fd(mon);
/* Begin polling for udev events. Events occur when devices attached to the system are added, removed, or change state.
udev_monitor_receive_device() will return a device object representing the device which changed and what type of change occured.
The select() system call is used to ensure that the call to udev_monitor_receive_device() will not block.
This section will run continuously, calling usleep() at the end of each pass. This is to use udev_monitor in a non-blocking way. */
while (1)
{
/*
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
select() allows a program to monitor multiple file descriptors, waiting until one or more of the file descriptors
become "ready" for some class of I/O operation.
Set up the call to select(). In this case, select() will only operate on a single file descriptor, the one associated
with our udev_monitor. Note that the timeval object is set to 0, which will cause select() to not block. */
fd_set fds;
struct timeval tv;
int ret;
FD_ZERO(&fds); //clear fds
FD_SET(fd, &fds);// Add fd to fds
/*
The timeout argument specifies the interval that select() should block waiting for a file descriptor to become ready.
This interval will be rounded up to the system clock granularity, and kernel scheduling delays mean that the
blocking interval may overrun by a small amount. If both fields of the timeval structure are zero, then select()
returns immediately. (This is useful for polling.)If timeout is NULL (no timeout), select() can block indefinitely.
*/
tv.tv_sec = 0;
tv.tv_usec = 0;
/*
nfds specifies how big the list of file descriptors is because the total number can be vast.
So, if you want to monitor file descriptors 24-31, you'd set nfds to 32.
man - nfds is the highest-numbered file descriptor in any of the three sets, plus 1.
*/
ret = select(fd+1, &fds, NULL, NULL, &tv);
/* Check if our file descriptor has received data. */
if (ret > 0 && FD_ISSET(fd, &fds)) {
printf("\nselect() says there should be data\n");
/* Make the call to receive the device.
select() ensured that this will not block. */
dev = udev_monitor_receive_device(mon);
if (dev) {
printf("Got Device\n");
printf(" Node: %s\n", udev_device_get_devnode(dev));
printf(" Subsystem: %s\n", udev_device_get_subsystem(dev));
printf(" Devtype: %s\n", udev_device_get_devtype(dev));
printf(" syspath:%s\n",udev_device_get_syspath(dev));
printf(" sysname:%s\n",udev_device_get_sysname(dev));
printf(" devpath:%s\n",udev_device_get_devpath(dev));
printf(" subsystem:%s\n",udev_device_get_subsystem(dev));
printf(" Action: %s\n", udev_device_get_action(dev));
std::string devtype=udev_device_get_devtype(dev);
std::string action=udev_device_get_action(dev);
std::string devnode=udev_device_get_devnode(dev);
if(devtype.compare("partition")==0 && action.compare("add") == 0)
{
printf("A new partition detected at %s\nTrying to mount to %s",devnode.c_str(),mount_path_for_udev_listner.c_str());
int ret = mount_disk(devnode,mount_path_for_udev_listner);
if(ret == 0)
{
printf("\nSystem returns %d, Mounting success\n",ret);
}
else{
printf("\n*****Error no %d\n",errno);
}
}
if(devtype.compare("partition")==0 && action.compare("remove") == 0)
{
printf("Partition removal detected, trying to unmount...\n");
int ret=umount_disk();
if(ret==0){
printf("\nSystem returns %d\n",ret);
printf("unmount successfull\n");
}
else{
printf("\nThe partition unmounting FAILED:\n ");
}
}
udev_device_unref(dev);
}
else {
printf("No Device from receive_device(). An error occured.\n");
}
}
usleep(250*1000);
printf(".");
fflush(stdout);
}
pthread_exit(NULL);
}
我从 https://askubuntu.com/questions/285539/detect-and-mount-devices
复制了这个
sudo lsusb
将告诉您 Linux 检测到了哪些 USB 设备。 USB 存储设备是否安装或被检测到是不同的问题。 sudo lsusb -v
将给出详细的输出,如果 OS 确实没有,可能会提供比您想要的更多的信息'识别设备。
或者,您可以在插入 USB 设备之前和之后比较 /dev
中的设备列表。有很多方法可以做到;我可能只会使用:
ls -l /dev/* | wc -l
这将为您提供一些可识别的设备。在插入设备之前和之后执行此操作将告诉您 OS 是否在 /dev/
.
中分配了设备
另一种选择是在插入 USB 设备时查看 dmesg 中发生的情况。 dmesg
可能会告诉您类似设备如何失败。
如果您在安装时遇到问题的 USB 设备在 lsusb 列表中,那么您可以尝试安装该设备。此时最好知道文件系统类型。 sudo fdisk -l
将以 ID 的形式告诉您文件系统类型。您可能需要查找身份证号码。网上有很多参考资料。知道设备列表后,即 /dev/hda1
和文件系统类型,您可以尝试使用 mount 命令手动安装设备。
sudo mount /dev/hda1 /home/user/Desktop/whereEver
您可能必须确保要安装设备的位置存在。如果 OS 识别文件系统,那么如果文件系统不是本机文件系统类型,则挂载可能会正常工作;您可能必须指定挂载标志。
Post 从 dmesg
返回你的输出(不是全部,只有当 USB 设备插入时), 和 sudo lsusb
.
您可能会发现 Linux/UNIX:设备文件有助于确定设备类型。
我写这篇文章时假设您所有无法识别的设备都是块类型设备。有很多方法可以解决这类问题和许多可能的解决方案。需要更具体的信息才能提供解决方案。
还有很多 GUI 应用程序可以做同样的事情。您可以尝试在 "Disk Utility".
中查找插入的硬件
另一种检测连接的 USB 设备的方法是 DBus 或 HAL(但 Hal 被认为已弃用),请参阅此 How to detect inserted USB and linux hotplugging
我得到了答案。我只需要为 usb-device 添加一个过滤器。如果我得到一个同时作为 usb 和 block 的设备,我可以使用分区并挂载它。
assert(udev_monitor_filter_add_match_subsystem_devtype(mon, "block", NULL)>=0);
assert(udev_monitor_filter_add_match_subsystem_devtype(mon, "usb","usb-device") >=0);
我想检测一个usb连接并挂载它对应的分区。 我尝试使用 udev.I 能够在 /dev/bus/usb/001 or/002 中找到设备。但是从这里我找不到它使用的分区。因此,我使用 udev 搜索块分区并在添加分区时挂载。eg/dev/sda1。但这是一个临时解决方案。 我想要的是使用 udev 或其他东西检测 usb 连接并找到它拥有的分区并挂载它。
我的代码:
#include <libudev.h>
#include <stdio.h>
#include "dmutil.h"
#include <pthread.h>
#include <unistd.h>
/*
Thread which detects devices.
*/
void * udev_listener(void * i)
{
struct udev *udev;
udev = udev_new();
if (!udev) {
printf("Can't create udev\n");
exit(1);
}
std::string mount_path_for_udev_listner = DEFAULT_MOUNT_PATH;
printf("\n\n **********\nUdev_listner is asked to mount usb to %s ....",mount_path_for_udev_listner.c_str());
struct udev_device *dev;
struct udev_monitor *mon;
mon = udev_monitor_new_from_netlink(udev, "udev");
assert(mon != NULL);
/* int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor,const char *subsystem, const char *devtype);
filters to select messages that get delivered to a listener.
On Success it returns an integer greater than, or equal to, 0. On failure, a negative error code is returned.
*/
assert(udev_monitor_filter_add_match_subsystem_devtype(mon, "block", NULL) >=0);
udev_monitor_enable_receiving(mon);
/* Get the file descriptor (fd) for the monitor.
This fd will get passed to select() */
int fd = udev_monitor_get_fd(mon);
/* Begin polling for udev events. Events occur when devices attached to the system are added, removed, or change state.
udev_monitor_receive_device() will return a device object representing the device which changed and what type of change occured.
The select() system call is used to ensure that the call to udev_monitor_receive_device() will not block.
This section will run continuously, calling usleep() at the end of each pass. This is to use udev_monitor in a non-blocking way. */
while (1)
{
/*
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
select() allows a program to monitor multiple file descriptors, waiting until one or more of the file descriptors
become "ready" for some class of I/O operation.
Set up the call to select(). In this case, select() will only operate on a single file descriptor, the one associated
with our udev_monitor. Note that the timeval object is set to 0, which will cause select() to not block. */
fd_set fds;
struct timeval tv;
int ret;
FD_ZERO(&fds); //clear fds
FD_SET(fd, &fds);// Add fd to fds
/*
The timeout argument specifies the interval that select() should block waiting for a file descriptor to become ready.
This interval will be rounded up to the system clock granularity, and kernel scheduling delays mean that the
blocking interval may overrun by a small amount. If both fields of the timeval structure are zero, then select()
returns immediately. (This is useful for polling.)If timeout is NULL (no timeout), select() can block indefinitely.
*/
tv.tv_sec = 0;
tv.tv_usec = 0;
/*
nfds specifies how big the list of file descriptors is because the total number can be vast.
So, if you want to monitor file descriptors 24-31, you'd set nfds to 32.
man - nfds is the highest-numbered file descriptor in any of the three sets, plus 1.
*/
ret = select(fd+1, &fds, NULL, NULL, &tv);
/* Check if our file descriptor has received data. */
if (ret > 0 && FD_ISSET(fd, &fds)) {
printf("\nselect() says there should be data\n");
/* Make the call to receive the device.
select() ensured that this will not block. */
dev = udev_monitor_receive_device(mon);
if (dev) {
printf("Got Device\n");
printf(" Node: %s\n", udev_device_get_devnode(dev));
printf(" Subsystem: %s\n", udev_device_get_subsystem(dev));
printf(" Devtype: %s\n", udev_device_get_devtype(dev));
printf(" syspath:%s\n",udev_device_get_syspath(dev));
printf(" sysname:%s\n",udev_device_get_sysname(dev));
printf(" devpath:%s\n",udev_device_get_devpath(dev));
printf(" subsystem:%s\n",udev_device_get_subsystem(dev));
printf(" Action: %s\n", udev_device_get_action(dev));
std::string devtype=udev_device_get_devtype(dev);
std::string action=udev_device_get_action(dev);
std::string devnode=udev_device_get_devnode(dev);
if(devtype.compare("partition")==0 && action.compare("add") == 0)
{
printf("A new partition detected at %s\nTrying to mount to %s",devnode.c_str(),mount_path_for_udev_listner.c_str());
int ret = mount_disk(devnode,mount_path_for_udev_listner);
if(ret == 0)
{
printf("\nSystem returns %d, Mounting success\n",ret);
}
else{
printf("\n*****Error no %d\n",errno);
}
}
if(devtype.compare("partition")==0 && action.compare("remove") == 0)
{
printf("Partition removal detected, trying to unmount...\n");
int ret=umount_disk();
if(ret==0){
printf("\nSystem returns %d\n",ret);
printf("unmount successfull\n");
}
else{
printf("\nThe partition unmounting FAILED:\n ");
}
}
udev_device_unref(dev);
}
else {
printf("No Device from receive_device(). An error occured.\n");
}
}
usleep(250*1000);
printf(".");
fflush(stdout);
}
pthread_exit(NULL);
}
我从 https://askubuntu.com/questions/285539/detect-and-mount-devices
复制了这个sudo lsusb
将告诉您 Linux 检测到了哪些 USB 设备。 USB 存储设备是否安装或被检测到是不同的问题。 sudo lsusb -v
将给出详细的输出,如果 OS 确实没有,可能会提供比您想要的更多的信息'识别设备。
或者,您可以在插入 USB 设备之前和之后比较 /dev
中的设备列表。有很多方法可以做到;我可能只会使用:
ls -l /dev/* | wc -l
这将为您提供一些可识别的设备。在插入设备之前和之后执行此操作将告诉您 OS 是否在 /dev/
.
另一种选择是在插入 USB 设备时查看 dmesg 中发生的情况。 dmesg
可能会告诉您类似设备如何失败。
如果您在安装时遇到问题的 USB 设备在 lsusb 列表中,那么您可以尝试安装该设备。此时最好知道文件系统类型。 sudo fdisk -l
将以 ID 的形式告诉您文件系统类型。您可能需要查找身份证号码。网上有很多参考资料。知道设备列表后,即 /dev/hda1
和文件系统类型,您可以尝试使用 mount 命令手动安装设备。
sudo mount /dev/hda1 /home/user/Desktop/whereEver
您可能必须确保要安装设备的位置存在。如果 OS 识别文件系统,那么如果文件系统不是本机文件系统类型,则挂载可能会正常工作;您可能必须指定挂载标志。
Post 从 dmesg
返回你的输出(不是全部,只有当 USB 设备插入时), 和 sudo lsusb
.
您可能会发现 Linux/UNIX:设备文件有助于确定设备类型。
我写这篇文章时假设您所有无法识别的设备都是块类型设备。有很多方法可以解决这类问题和许多可能的解决方案。需要更具体的信息才能提供解决方案。
还有很多 GUI 应用程序可以做同样的事情。您可以尝试在 "Disk Utility".
中查找插入的硬件另一种检测连接的 USB 设备的方法是 DBus 或 HAL(但 Hal 被认为已弃用),请参阅此 How to detect inserted USB and linux hotplugging
我得到了答案。我只需要为 usb-device 添加一个过滤器。如果我得到一个同时作为 usb 和 block 的设备,我可以使用分区并挂载它。
assert(udev_monitor_filter_add_match_subsystem_devtype(mon, "block", NULL)>=0);
assert(udev_monitor_filter_add_match_subsystem_devtype(mon, "usb","usb-device") >=0);