欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 资讯 > Android init阶段loop回环设备的使用

Android init阶段loop回环设备的使用

2025/2/26 13:06:17 来源:https://blog.csdn.net/weixin_43245753/article/details/145688328  浏览:    关键词:Android init阶段loop回环设备的使用

环回设备是一种特殊的块设备,它允许你将一个普通的文件当作块设备来使用。这种功能在需要将文件系统挂载到一个文件上时特别有用,比如在处理磁盘镜像文件时。

内核驱动:drivers/block/loop.c。 在内核驱动初始化时会自动创建一定数量的loop设备,上层在通过/dev/loop-control节点ioctrl LOOP_CTL_GET_FREE时,如果没有设备会自动创建。

在ramdisk init阶段需要创建/dev/loop-control和/dev/block/loop0-3节点,并绑定内核环回设备:

system/core$
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index d050ed783..b34003635 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -233,7 +233,7 @@ int FirstStageMain(int argc, char** argv) {CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1));// Get the basic filesystem setup we need put together in the initramdisk// on / and then we'll let the rc file figure out the rest.
-    CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"));
+    CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755,size=1024M"));CHECKCALL(mkdir("/dev/pts", 0755));CHECKCALL(mkdir("/dev/socket", 0755));CHECKCALL(mkdir("/dev/dm-user", 0755));
@@ -266,6 +266,12 @@ int FirstStageMain(int argc, char** argv) {// This is needed for log wrapper, which gets called before ueventd runs.CHECKCALL(mknod("/dev/ptmx", S_IFCHR | 0666, makedev(5, 2)));CHECKCALL(mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3)));
+    CHECKCALL(mknod("/dev/loop-control", S_IFCHR | 0666, makedev(10, 237)));
+    CHECKCALL(mkdir("/dev/block", 0755));
+    CHECKCALL(mknod("/dev/block/loop0", S_IFBLK | 0755, makedev(7, 0)));
+    CHECKCALL(mknod("/dev/block/loop1", S_IFBLK | 0755, makedev(7, 8)));
+    CHECKCALL(mknod("/dev/block/loop2", S_IFBLK | 0755, makedev(7, 16)));
+    CHECKCALL(mknod("/dev/block/loop3", S_IFBLK | 0755, makedev(7, 24)));
  • mknod(const char *pathname, mode_t mode, dev_t dev) 是一个系统调用,用于创建一个文件系统节点(文件、设备特殊文件或命名管道)。

  • 参数解释:

    • "/dev/block/loop0":这是要创建的设备文件的路径。
    • S_IFBLK | 0755:这是文件的模式。S_IFBLK 表示创建的是一个块设备,0755 是文件的权限(所有者可读、写、执行,其他用户可读和执行)。
    • makedev(7, 0):这是设备号,makedev 函数用于生成设备号,7 是主设备号,0 是次设备号。对于环回设备,主设备号通常是 7。 主从设备号需要从机器里面通过ls -la /dev/block/loop*查看,不同的内核版本可能不一样
rk3588_t:/ $ ls -l /dev/block/loop*
brwxr-xr-x 1 root root 7,   0 2025-01-13 00:17 /dev/block/loop0
brwxr-xr-x 1 root root 7,   8 2025-01-13 00:17 /dev/block/loop1
brw------- 1 root root 7,  80 2025-01-13 00:18 /dev/block/loop10
brw------- 1 root root 7,  88 2025-01-13 00:18 /dev/block/loop11
brw------- 1 root root 7,  96 2025-01-13 00:18 /dev/block/loop12
brw------- 1 root root 7, 104 2025-01-13 00:18 /dev/block/loop13
brw------- 1 root root 7, 112 2025-01-13 00:18 /dev/block/loop14
brw------- 1 root root 7, 120 2025-01-13 00:18 /dev/block/loop15
brwxr-xr-x 1 root root 7,  16 2025-01-13 00:17 /dev/block/loop2
brwxr-xr-x 1 root root 7,  24 2025-01-13 00:18 /dev/block/loop3
brw------- 1 root root 7,  32 2025-01-13 00:18 /dev/block/loop4
brw------- 1 root root 7,  40 2025-01-13 00:18 /dev/block/loop5
brw------- 1 root root 7,  48 2025-01-13 00:18 /dev/block/loop6
brw------- 1 root root 7,  56 2025-01-13 00:18 /dev/block/loop7
brw------- 1 root root 7,  64 2025-01-13 00:18 /dev/block/loop8
brw------- 1 root root 7,  72 2025-01-13 00:18 /dev/block/loop9

在init中编写代码将镜像文件绑定到loop设备上面

std::string setup_loop_device(const std::string& file_path) {std::string system_device;if (Loop::create(file_path, system_device) != 0) {LOG(ERROR) << "Failed to create loop device file_path";return nullptr;}LOG(INFO) << "created loop device: " << system_device;return system_device;
}int Loop::create(const std::string& target, std::string& out_device) {unique_fd ctl_fd(open("/dev/loop-control", O_RDWR | O_CLOEXEC));if (ctl_fd.get() == -1) {PLOG(ERROR) << "Failed to open loop-control";return -errno;}int num = ioctl(ctl_fd.get(), LOOP_CTL_GET_FREE);if (num == -1) {PLOG(ERROR) << "Failed LOOP_CTL_GET_FREE";for (size_t id = 0; id < 3; ++id) {int ret = ioctl(ctl_fd.get(), LOOP_CTL_ADD, id);LOG(INFO) << "LOOP_CTL_ADD ADD ID=" << id;if (ret < 0 && errno != EEXIST) {LOG(ERROR) << "Failed LOOP_CTL_ADD";return -errno;}}num = ioctl(ctl_fd.get(), LOOP_CTL_GET_FREE);if (num == -1) {PLOG(ERROR) << "Failed LOOP_CTL_GET_FREE";       return -errno;}}out_device = StringPrintf("/dev/block/loop%d", num);unique_fd target_fd;for (size_t i = 0; i != kLoopDeviceRetryAttempts; ++i) {target_fd.reset(open(target.c_str(), O_RDWR | O_CLOEXEC));if (target_fd.get() != -1) {break;}usleep(50000);}if (target_fd.get() == -1) {PLOG(ERROR) << "Failed to open " << target;return -errno;}if (!android::fs_mgr::WaitForFile(out_device, 2s)) {LOG(ERROR) << "Failed to find " << out_device;return -ENOENT;}unique_fd device_fd(open(out_device.c_str(), O_RDWR | O_CLOEXEC));if (device_fd.get() == -1) {PLOG(ERROR) << "Failed to open " << out_device;return -errno;}if (ioctl(device_fd.get(), LOOP_SET_FD, target_fd.get()) == -1) {PLOG(ERROR) << "Failed to LOOP_SET_FD";return -errno;}struct loop_info64 li;memset(&li, 0, sizeof(li));strlcpy((char*)li.lo_crypt_name, kVoldPrefix, LO_NAME_SIZE);if (ioctl(device_fd.get(), LOOP_SET_STATUS64, &li) == -1) {PLOG(ERROR) << "Failed to LOOP_SET_STATUS64";return -errno;}return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词