我想使用C ++挂载文件系统。我应该使用mount()
系统调用,还是只执行mount
二进制文件?
显然系统调用会更快,并且我将浪费更少的时间来构建命令行参数并解析错误消息和内容。但是,在读取mount(2)后,我不清楚对参数有什么限制(如果有的话)。
我特别希望能够安装磁盘映像文件以及实际的物理磁盘。我还希望能够通过指定设备/图像开头的偏移来安装单个文件系统。我不知道你是否可以通过一次调用mount()
来做到这一点,或者你是否需要先手动创建循环设备。 (我也不知道创建一个循环设备有多难 - 我推测它相当容易......)
如果正确设置这些内容相当复杂,那么调用mount
二进制文件可能更简单,更容易。但如果它只是一个系统调用,则直接调用mount()
似乎更清晰。那么哪一个可能会给我最少的问题?
答案 0 :(得分:1)
嗯,Nayden建议运行strace mount
,这不是一个坏主意。
完成此操作后,似乎mount
正在做很多工作的地狱。看起来它确实创建了一个循环设备并安装它。 (这意味着它需要弄清楚下一个未使用的循环设备号是什么,等等。)听起来你可能还需要手动找出文件系统类型。
简而言之,在我看来,对mount
二进制文件的简单调用可能比尝试重新创建程序所做的一切要少得多。我原以为智能在内核中,但显然不是。
答案 1 :(得分:0)
我的建议是使用系统调用。 如果您想知道需要进行的确切调用,请通过strace或gdb下的shell运行mount。
答案 2 :(得分:0)
系统调用mount():
优点:
-非阻塞(即您的进程仍然响应)。
-更快,因为您无需花费时间来创建新进程,线程。
缺点:
-您需要指定文件系统类型,安装标志,数据(某些文件系统使用的某些特殊内容,也许为NULL)。
-您可以挂载映像文件,但是有必要注意使用自由循环设备并将其与映像相关联。
-查看您的代码是否需要涵盖所有可能的用例,您可以使用自行编写的挂载工具:)
安装工具:
优点:
-易于使用,因为默认情况下需要指定较少的参数。
-无需创建循环设备,将其与图像关联等(如果安装了图像)。
缺点:
-当通过系统,fork-exec等从c ++代码调用安装工具时,如果使用wait(),则将阻止您的进程。某些应用程序很容易受到此类阻碍(例如,有人可能会依赖您的应用程序并等待答案,而安装正在进行中)
如果您对如何通过挂载系统调用挂载映像感兴趣,这是一个简单的概念证明,基于:
http://man7.org/linux/man-pages/man4/loop.4.html
https://linux.die.net/man/2/mount
请注意,不要在生产中使用此类代码,因为不会对返回值,异常等进行单独检查:)。无论如何,它都能编译并在我的机器上运行。应该以root用户身份运行。
#include <sys/mount.h> //mount
#include <sys/ioctl.h> //ioctl
#include <sys/stat.h> //open
#include <linux/loop.h> //LOOP_SET_FD
#include <fcntl.h> //open
#include <cstdio> // declaration of ::fileno
#include <cstdint> //int32_t
#include <sstream> //std::stringstream
#include <string>
constexpr char IMAGE_NAME[] = "image.img"; //of course we need this file to be present in same folder as built tool
constexpr char MOUNT_POINT[] = "/tmp/image_mnt"; //of course we need this folder already created
constexpr char FILESYSTEM_TYPE[] = "ext4";
constexpr char DEV_LOOP_CONTROL[] = "/dev/loop-control";
constexpr char DEV_LOOP_PREFIX[] = "/dev/loop";
constexpr int32_t MOUNT_FLAGS = MS_RDONLY;
int main()
{
const auto loop_control = std::fopen(DEV_LOOP_CONTROL, "r");
const auto loop_control_fd = fileno(loop_control);
const auto devnr = ioctl(loop_control_fd, LOOP_CTL_GET_FREE);
std::stringstream loopname;
loopname << DEV_LOOP_PREFIX << devnr;
const auto loop_device_name = loopname.str();
const auto loop_device = std::fopen(loop_device_name.c_str(), "r");
const auto loop_device_fd = fileno(loop_device);
const auto image = std::fopen(IMAGE_NAME, "r");
const auto image_fd = fileno(image);
//Associate the loop device with the open file whose file descriptor is passed as the (third) ioctl(2) argument.
ioctl(loop_device_fd, LOOP_SET_FD, image_fd);
const auto result = mount(loop_device_name.c_str(), MOUNT_POINT, FILESYSTEM_TYPE, MOUNT_FLAGS, NULL);
ioctl(loop_device_fd, LOOP_CLR_FD, 0);
return result;
}