链路如下:
storage/sdcard0--->/sdcard
/sdcard -> /storage/self/primary
/storage/self/primary -> /mnt/user/0/primary
/mnt/user/0/primary -> /storage/emulated/0
最终都是链接到/storage/emulated/0目录下。那么代码逻辑是如何链接的?
第一步:/sdcard -> /storage/self/primary
在system//core/rootdir/init.rc代码中
#创建链接
118 # Symlink to keep legacy apps working in multi-user world
119 symlink /storage/self/primary /sdcard
120 symlink /storage/self/primary /mnt/sdcard
121 symlink /mnt/user/0/primary /mnt/runtime/default/self/primary
在系统的时候init.rc会被解析,并最终调用代码中的do_symlink接口
static Result<Success> do_symlink(const BuiltinArguments& args) {
if (MakeSymlink(args[1], args[2]) < 0) {
// The symlink builtin is often used to create symlinks for older devices to be backwards
// compatible with new paths, therefore we skip reporting this error.
if (errno == EEXIST && android::base::GetMinimumLogSeverity() > android::base::DEBUG) {
return Success();
}
//注意这里的的log是不会打印出来的,因为向后兼容,难免有一些链接不到,所以安卓就跳过链接出错的log
return ErrnoError() << "symlink() failed";
}
return Success();
}
static int MakeSymlink(const std::string& target, const std::string& linkpath) {
std::string secontext;
// Passing 0 for mode should work.
if (SelabelLookupFileContext(linkpath, 0, &secontext) && !secontext.empty()) {
setfscreatecon(secontext.c_str());
}
int rc = symlink(target.c_str(), linkpath.c_str());
if (!secontext.empty()) {
int save_errno = errno;
setfscreatecon(nullptr);
errno = save_errno;
}
return rc;
}
最终会调用symlink接口来完成,这里注意一个点就是symlink进行符号连接时,当目标target不存在时也会连接上并且不会报错,因为一开始/storage/self/primary在init.rc阶段并不存在,但是后续该目录被链接或者被创建的时候,/sdcard便自动能访问/storage/self/primary。
第二步:/storage/self/primary -> /mnt/user/0/primary
在init.rc当中,会有如下的初始化链接。
/system/core/rootdir/init.rc
symlink /mnt/user/0/primary /mnt/runtime/default/self/primary
.......
on post-fs
......
# Mount default storage into root namespace
mount none /mnt/runtime/default /storage bind rec
这里因为/mnt/runtime/default/self/primary链接/mnt/user/0/primary,又有/mnt/runtime/default与/storage/相互挂载绑定,那么/stor

最低0.47元/天 解锁文章
5507

被折叠的 条评论
为什么被折叠?



