解决方案说明
实施的解决方案涉及udev、poll、setmntent和getmntent。
这个想法是保留所有已挂载文件系统的列表(这不会占用内存,因为设备数量通常很少)并且该列表只需要创建一次。
在 "/proc/mounts" 上使用 poll(),您可以了解 何时 文件系统被挂载或卸载。然后使用 udev 你可以得到当时挂载的设备列表。因此,您可以与已有的列表进行比较,这样您就可以知道文件系统是挂载还是卸载,以及哪个文件系统受到影响。
灵魂相关代码示例
获取挂载节点的函数。
vector<string> get_mounted_storage_nodes()
{
vector<string> storage_nodes = get_storage_nodes(); // This uses udev.
vector<string> mounted_nodes;
struct mntent *mntent;
FILE *file;
file = setmntent("/etc/mtab", "r");
while ((mntent = getmntent(file)))
{
string mounted_node(mntent->mnt_fsname);
vector<string>::iterator it;
it = find(storage_nodes.begin(), storage_nodes.end(), mounted_node);
if (it != storage_nodes.end())
mounted_nodes.push_back(mounted_node);
}
return mounted_nodes;
}
确定文件系统是挂载还是卸载
简单的只是比较两个灯的大小。
// event is a convenience struct that holds the name of the affected
// filesystem and the action (mounted or unmounted).
vector<string> new_mounted_nodes = get_mounted_storage_nodes();
int new_size = new_mounted_nodes.size();
int curr_size = mounted_nodes.size();
if (new_size == curr_size)
event.action = NONE; // No partition was mount or unmounted.
// This case is very common when the poll
// is working as non-blocking because the timeout.
else
event.action = new_size > curr_size ? MOUNT : UMOUNT;
找出受影响的文件系统
vector<string> new_mounted_nodes = get_mounted_storage_nodes();
使用上一行,如果文件系统已挂载,您只需找到不在已挂载节点列表中的new_mounted nodes 元素。另一方面,如果文件系统被卸载,你必须找到你已经拥有但不在new_mounted_nodes的列表中的元素。
代码示例:
switch(event.action)
{
case MOUNT:
for (auto it = new_mounted_nodes.begin(); it != new_mounted_nodes.end(); ++it)
if (find(mounted_nodes.begin(), mounted_nodes.end(), *it) == mounted_nodes.end())
{
event.node = *it;
break;
}
break;
case UMOUNT:
for (auto it = mounted_nodes.begin(); it != mounted_nodes.end(); ++it)
if (find(new_mounted_nodes.begin(), new_mounted_nodes.end(), *it) == new_mounted_nodes.end())
{
event.node = *it;
break;
}
break;
default:
break;
}
重要提示:最新代码的复杂度是O(n^2),但是挂载设备的数量一般会(我不想absolute) 低于 20。因此,算法将运行得非常快。