长沙营销型网站建设公司网站建设里怎么写文章

web/2025/9/26 10:54:18/文章来源:
长沙营销型网站建设公司,网站建设里怎么写文章,怎么制作公司网页教程,企业注册在哪个网站申请android版本#xff1a;android-11.0.0_r21http://aospxref.com/android-11.0.0_r21 android手机的挂载非常复杂。这篇文章针对emulated存储#xff0c;介绍它的挂载过程。 一、为什么emulted存储要用很复杂的挂载方式 1#xff0c; emulted存储是什么 android早期#…android版本android-11.0.0_r21http://aospxref.com/android-11.0.0_r21 android手机的挂载非常复杂。这篇文章针对emulated存储介绍它的挂载过程。 一、为什么emulted存储要用很复杂的挂载方式 1 emulted存储是什么 android早期手机内部flash容量比较小为了能让手机存放更多的文件需要通过外部存储如SD卡来扩展存储容量。随着技术的进步大容量flash的价格变便宜了手机内置大容量flash已经成常态。在大容量的flash中划出一块空间图中绿色部分模拟成外部存储就可以兼容早期的flash外置SD卡的方式了。emulated storage的容量随着用户使用动态增减它是/data/路径下的一个目录所以emulated storage可用空间取决于/data所在分区大小。注意如果用户通过emulated storage占满了这个分区那么系统启动时一些更新、写重要系统文件的操作会因没有空间而失败从而导致系统无法启动所以需要限制一下emulated storage大小解决方案可以google搜索LIMIT_SDCARD_SIZE宏。 2为什么要用这么复杂的挂载 结论为了实现存储的动态权限。默认情况下应用没有权限访问共享空间应用需要读写共享空间时需要申请权限征得用户同意后才能后访问文件。这就涉及到android的“运行时权限”存储模块通过复杂的挂载来实现这个机制。大致的思想是这样的对于共享空间做4个bind mount通过这几个挂载点访问共享空间的权限分别为a无权限、b读权限、c写权限、d读写权限。应用启动的时候按a挂载假设没申请过权限申请权限并经用户同意后通过remount挂载b/c/d中的一个比如需要写共享空间的文件则采用“写权限”方式remount共享空间。 从android 11开始启用了分区存储scoped storage参考https://www.youtube.com/watch?vUnJ3amzJM94分区存储的目的我认为有2点为了更好地管理外部存储空间将同类型文件集中存储避免各个应用在存储中乱放文件还有就是在实现了分区存储的基础上可以更集中统一地做权限管理。 android 11 权限设计规则如下 不需要任何权限应用可以自由地读写自己的专属空间。比如在/data/data/包名/files目录中创建新的文件。不需要任何权限应用可以自由地读共享空间/storage/emulated/0中的内容也就是可以列出共享空间中的文件。应用读共享空间中的媒体文件需要申请READ_EXTERNAL_STORAGE 。文件管理类应用申请MANAGE_EXTERNAL_STORAGE权限可以读写共享存储空间中的所有文件。非文件管理类应用通过SAFStorage Access Framework访问非媒体文件或非媒体目录。 二、外部存储挂载视图 1bind mount介绍 在正式介绍挂载视图前需要讲一下bind mount。 绑定挂载命令bindmount  --bind   olddir   newdir 1将olddir绑定到newdir。绑定后olddir和newdir看到的都是olddir中的内容newdir中绑定前的内容变不可见。 2命令中的olddir对应内核mount函数的dev_name参数newdir对应mount的dir_name参数。 3务必注意mount命令查看挂载详情是看不到olddir的取而代之的是olddir所在的device name。 比如 cp:/data/media/0 # touch new/this-is-newdir cp:/data/media/0 # touch old/this-is-olddir//把/data/media/0/old绑定到/data/media/0/new cp:/data/media/0 # mount --bind old new//绑定后只能看到old目录中的内容 cp:/data/media/0 # ls old/ this-is-olddir cp:/data/media/0 # ls new/ this-is-olddir//mount命令只能看到old所属的/dev/block/dm-9挂载到了/data/media/0/new cp:/data/media/0 # mount |grep new /dev/block/dm-9 on /data/media/0/new type f2fs (rw,lazytime,seclabel,nosuid,nodev,noatime,background_gcon,discard,no_heap,user_xattr,inline_xattr,acl,inline_data,inline_dentry,extent_cache,modeadaptive,active_logs6,reserve_root56683,resuid0,resgid1065,inlinecrypt,alloc_modedefault,fsync_modenobarrier 再比如 cp:/storage/emulated/0 # mkdir old new cp:/storage/emulated/0 # mount --bind old new//mount命令只能看到old目录所属的/dev/fuse挂载到了/data/media/0/new cp:/storage/emulated/0 # mount |grep new /dev/fuse on /storage/emulated/0/new type fuse (rw,lazytime,nosuid,nodev,noexec,noatime,user_id0,group_id0,allow_other)注意下文会用到这些结论 1newdir看到的是olddir中的内容。 2,mount命令看不到bindmount命令的olddir。 2挂载视图 预置条件使能fuse、使能sdcardfs Noteandroid挂载实在很复杂图中没有完整地画出来也没有按照mount namespace把各命名空间的挂载情况分开画出来比如你会看到/storage有多个bind mount③④⑤但任何时刻一个进程只属于一个mount space只能看到其中一个bind mount。普通的app不是installer app、Mediaprovider类型的通过③将/mnt/user/0 bind mount到  /storageinstaller app通过⑤将/mnt/installer/0 bind mount到 /storageMediaProvider将/mnt/pass_through/0 bind mount到 /storage。 注意通常→的起始端表示source对应bindmount命令中的olddir终端表示target对应bindmount命令中的newdir但是为了画图方便图中的起始端表示bind mount的target比如将/mnt/user/0sourcebind mount 到/storagetarget图中表示出来就是③所以/storage看到的是/mnt/user/0中的内容原/storage中的内容被隐藏。 app访问/sdcard的过程是这样的内核解析路径时lookup过程是一级一级解析路径分量名的 1/sdcard是个软链接通过①链接到/storage/self/primary所以访问/sdcard就是访问/storage/self/primary目录。 2启动app时zygote 为app fork子进程接着设置app的挂载命名空间并通过③将/mnt/user/0目录bind  mount到/storage目录com_android_internal_os_Zygote_nativeForkSystemServer -- SpecializeCommon -- MountEmulatedStorage所以访问/storage/self/primary就是访问/mnt/user/0/self/primary目录。 3/mnt/user/0/self/primary是个软链接链接到/storage/emulated/0图中未画所以访问/mnt/user/0/self/primary就是访问/storage/emulated/0目录。 4从2可知/mnt/user/0目录olddirbind  mount到/storage目录newdir所以访问/storage/emulated/0目录就是访问/mnt/user/0/emulated/0目录。5/mnt/user/0/emulated是一个挂载点设备是/dev/fuse见图中⑥所以访问/mnt/user/0/emulated开头的文件比如上面的/mnt/user/0/emulated/0就会交给fuse文件系统处理。 6StorageSessionController::onVolumeMount挂载外部存储时connection.startSession将/storage/emulated上层目录和/data/media底层目录通过/dev/fuse关联起来。StorageUserConnection: StorageUserConnection::startSession task:StorageManagerService sessionId: emulated;0 upperPath:/storage/emulated lowerPath:/data/media 对/storage/emulated/0的访问将转换成对/data/media/0的访问。/data/media/0就是底层文件系统f2fs/ext4上的一个目录通过底层文件系统就可以获取真实的数据了。 上面各种链接各种bind mount绕来绕去了的是为了兼容早期的版本以用户0为例兼容的效果是让访问外部存储的路径变成/storage/emulated/0目录。现在版本通过getExternalStorageDirectory()获取到的路径就是“/storage/emulated/0”这个路径的解析过程从上面4开始最终定向到/data/media/0目录。 3动态权限 提交记录https://android.googlesource.com/platform/system/core//f38f29c87d97cea45d04b783bddbd969234b1030%5E%21/#F1 动态权限是通过改变app的不同视图实现的default、read、write、full 127|cp:/ # mount |grep runtime /data/media on /mnt/runtime/default/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,fsuid1023,fsgid1023,gid1015,multiuser,mask6,derive_gid,default_normal,unshared_obb) /data/media on /mnt/runtime/read/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,fsuid1023,fsgid1023,gid9997,multiuser,mask23,derive_gid,default_normal,unshared_obb) /data/media on /mnt/runtime/write/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,fsuid1023,fsgid1023,gid9997,multiuser,mask7,derive_gid,default_normal,unshared_obb) /data/media on /mnt/runtime/full/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,fsuid1023,fsgid1023,gid9997,multiuser,mask7,derive_gid,default_normal,unshared_obb) mask八进制表示ugouser-group-other权限,比如006表示other的权限掩码为0110即可读可写无执行(rw-)。 挂载点信息用户权限bind mount目录mask  gidgroup用户权限other用户权限/mnt/runtime/default006AID_SDCARD_RW (1023)group掩码0不去任何权限。即有完整权限other权限掩码6去掉读写权限即有执行/mnt/runtime/read023AID_EVERYBODY (9997)group掩码010,拿到写权限即可读、可执行other权限掩码3去掉写、执行权限即可读/mnt/runtime/write007AID_EVERYBODY (9997)group掩码0不去任何权限即有完整权限other权限掩码7去掉读、写、执行权限即无任何权限/mnt/runtime/full007AID_EVERYBODY  (9997)group掩码0不去任何权限即有完整权限other权限掩码7去掉读、写、执行权限即无任何权限 一般的应用程序属于AID_EVERYBODY组可对照上面表格group用户权限一列查看各bind mount目录视图的权限。 三、代码分析 1app挂载命名空间的创建 启动app时zygote通过forkAndSpecialize为app创建主线程并通过unshare(CLONE_NEWNS)为新创建的子进程设置新的命名空间。 forkAndSpecialize (Zygote.java)-- nativeForkAndSpecialize-- com_android_internal_os_Zygote_nativeForkAndSpecialize (com_android_internal_os_Zygote.cpp)-- SpecializeCommon -- MountEmulatedStorage-- ensureInAppMountNamespace -- unshare(CLONE_NEWNS) fork创建进程时父子进程共享一些“execution context”比如命名空间unshare指定父子进程的“execution context”相互独立。 2/storage的bind mount 在挂载视图一节可以看到有很多目录bind mount到了/storage图中的③④⑤以及未画的/mnt/androidwritable是不是很奇怪其实是这样的各app是在自己的mount name space中bind mount /storage目录的所以对于app来说只会挂载③④⑤中的一个最终各app进入/storage目录看到的内容是不一样的。 /storage挂载是这样的 代码见MountEmulatedStoragecom_android_internal_os_Zygote.cpp。 // Create a private mount namespace and bind mount appropriate emulated // storage for the given user. static void MountEmulatedStorage(uid_t uid, jint mount_mode,bool force_mount_namespace,fail_fn_t fail_fn) {/** 确认app的mount name space已经创建了。* 如果没有创建挂载命名空间则通过unshare创建。* 如果创建失败则通过fail_fnye也就是ZygoteFailure终止进程并报告错误。*/ensureInAppMountNamespace(fail_fn);/* 挂载模式指定不挂载外部存储直接返回 */if (mount_mode MOUNT_EXTERNAL_NONE) {return;}const userid_t user_id multiuser_get_user_id(uid);const std::string user_source StringPrintf(/mnt/user/%d, user_id);PrepareDir(user_source, 0710, user_id ? AID_ROOT : AID_SHELL,multiuser_get_uid(user_id, AID_EVERYBODY), fail_fn);bool isFuse GetBoolProperty(kPropFuse, false);bool isAppDataIsolationEnabled GetBoolProperty(kVoldAppDataIsolation, false);/* persist.sys.fuse属性是否enable了可通过getprop persist.sys.fuse查看 */if (isFuse) {if (mount_mode MOUNT_EXTERNAL_PASS_THROUGH) {/* MOUNT_EXTERNAL_PASS_THROUGH 7MediaProvider 进入此分支。* 对于MediaProvider 进程,访问 /storage 就是访问 /mnt/pass_through/[userid]。* 务必要记住MediaProvider访问/storage跟普通app访问/storage是不一样的* 普通app访问/storage经过fuse兜兜转转交给了MediaProvider这个时候* MediaProvider访问/storage访问的是/mnt/pass_through/%d目录了。否则如果 * MediaProvider访问跟普通app一样的/storage那就又回头死循环了。*/const std::string pass_through_source StringPrintf(/mnt/pass_through/%d, user_id);PrepareDir(pass_through_source, 0710, AID_ROOT, AID_MEDIA_RW, fail_fn);BindMount(pass_through_source, /storage, fail_fn);} else if (mount_mode MOUNT_EXTERNAL_INSTALLER) {/* MOUNT_EXTERNAL_INSTALLER 5packageinstall 进入此分支。* 调试的话可通过下面方法触发执行该分支代码--------------------------------------------------------------------cp:/ # ps -AT |grep installu0_a59 1823 1823 554 5404912 55800 SyS_epoll_wait 0 S ackageinstalleru0_a168 4990 5898 555 2440460 635332 futex_wait_queue_me 0 S split_install_tu0_a60 6224 6224 554 5886452 169904 SyS_epoll_wait 0 S ageinstaller.uicp:/ # kill -9 1823这个时候logcat 可以看到自己添加的调试信息--------------------------------------------------------------------*/const std::string installer_source StringPrintf(/mnt/installer/%d, user_id);BindMount(installer_source, /storage, fail_fn);} else if (isAppDataIsolationEnabled mount_mode MOUNT_EXTERNAL_ANDROID_WRITABLE) {/** 有写权限的app走这个分支等价于命令: mount --bind /mnt/androidwritable /storage* mount命令看不到olddir也即/mnt/androidwritable。前面说过原因。* nsenter -t app进程tid -m mount |grep /storage nsenter进入app的命名空间* tmpfs on /storage type tmpfs ……(挂载参数)*/const std::string writable_source StringPrintf(/mnt/androidwritable/%d, user_id);BindMount(writable_source, /storage, fail_fn);} else {/** 普通app走这个分支等价于命令: mount --bind /mnt/user/0 /storage* * mount命令看不到olddir也即/mnt/user/0。前面说过原因。* nsenter -t app进程tid -m mount |grep /storage nsenter进入app的命名空间* tmpfs on /storage type tmpfs ……(挂载参数)*/BindMount(user_source, /storage, fail_fn);}} else {/* persist.sys.fuse没有enable的场景挂载比较简单 */const std::string storage_source ExternalStorageViews[mount_mode];BindMount(storage_source, /storage, fail_fn);// Mount user-specific symlink helper into placeBindMount(user_source, /storage/self, fail_fn);} } 3外部存储挂载流程 上一篇文章android存储3--初始化.unlock事件的处理_geshifei的博客-CSDN博客讲了用户解锁设备后SystemServiceManager处理unlock事件主要有3个存储相关的service要处理解锁事件 1StorageManagerService$Lifecycle.onUserUnlocking 2mStorageSessionController.onUnlockUser 3mStoraged.onUserStarted 但只讲了怎么触发存储相关service做各自初始化工作的涉及到具体的emulated device的挂载就没有分析了。下图展示了mVold.onUserStarted挂载emulated device的流程图中蓝色字体是函数。 4动态权限处理 4.1 没有使能fuse时的场景 app访问外部存储时弹窗申请读写权限点击允许代码流程如下 PackageManagerService::grantRuntimePermission   - PermissionManagerService::grantRuntimePermission         - PermissionManagerService::grantRuntimePermissionInternal               - StorageManagerService::onExternalStoragePolicyChanged                      - StorageManagerService::remountUidExternalStorage                             - mVold.remountUid(uid, mode)即VoldNativeService::remountUid                                   - VolumeManager::remountUid int VolumeManager::remountUid(uid_t uid, int32_t mountMode) {/* 使能fuse的情况直接返回 */if (GetBoolProperty(android::vold::kPropFuse, false)) {// TODO(135341433): Implement fuse specific logic.return 0;}/** 遍历/proc下各个进程目录根据uid进行查找找到pid后* fork子进程进行重新挂载/mnt/runtime/XX setns切换mount name space*/return scanProcProcesses(uid, static_castuserid_t(-1),forkAndRemountChild, mountMode) ? 0 : -1; } 4.2 使能fuse时的场景 待补充。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/82153.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

秦皇岛做网站优化价格惠州建设局网站

目录 Flask MQTT 实现消息订阅发布准备开始1.创建Flask项目2创建py文件:mqtt_demo.py3.代码实现4.项目运行5.测试5.1 测试消息接收5.2 测试消息发布6、扩展 Flask MQTT 实现消息订阅发布 准备 本次项目主要使用到的库:flask_mqtt pip install flask…

自己做的网站本地虚拟上传可以做网站吗

os包中实现了平台无关的接口,设计向Unix风格,但是错误处理是go风格,当os包使用时,如果失败之后返回错误类型而不是错误数量.os包中函数设计方式和Unix类似,下面来看一下.func Chdir(dir string)…

高性能网站开发 书籍个人网站推广方法

并行运行hbase删表,建表操作,多个表多个region,导致hbase挂掉。查看日志:从日志中可以看出GC时间过长导致zookeeper连接超时,master退出。(是master退出而不是regionserver退出是因为进行的操作是建表,删表…

南坪网站建设马鞍山网站建设文

文章目录 🍪一、前言🍩1、C简介🍩2、C关键字 🍪二、命名冲突🍪三、命名空间🍩1、命名空间定义🍩2、命名空间的使用 🍪四、C输入&输出 🍪一、前言 本篇文章是《C 初阶…

给别人做网站挣钱wordpress企业主题免费

参考网址:http://www.runoob.com/design-pattern/singleton-pattern.html 1.目的:保证一个类仅有一个实例,并提供一个访问它的全局访问点。(比如世界只有一个月亮,党只有一个主席) 2. 优点: 1、在内存里只有一个实例,减少了内存的开销&#x…

建聊天网站深圳网站建设开发公司哪家好

为什么是B树? 我们推导下,首先看下用哈希表做索引,是否可以满足需求。如果我们用哈希建了索引,那么对于如下这种SQL,通过哈希,可以快速检索出数据: select * from t_user_info where id1;但是这…

大学跳蚤市场网站建设哈尔滨制作企业网站

最近在回顾网络知识点的时候,发现华为数通有关报文格式及网络协议地图神仙网站,这里涵盖了各个协议层及每个协议层对应的协议内容,最人性的化的一点是点击每个单独的协议可以跳转到该协议详细报文格式页面,有对应的说明和解释&…

淮安企业网站眉山网站建设公司

在当今世界,Windows 应用程序对我们的工作至关重要。随着处理 PDF 文档的需求不断增加,将 ComPDFKit PDF 查看和编辑功能集成到您的 Windows 应用程序或系统中,可以极大地为您的用户带来美妙的体验。 在本博客中,我们将首先探索集…

网站建设电子书永久免费crm软件哪个好

监控无人机的开发涉及多个方面,涵盖硬件、软件和网络等领域。下面是一般情况下开发监控无人机系统的主要步骤: 确定需求和功能:明确您的监控无人机系统的目标和应用场景,确定需要的功能和特性,例如实时视频监控、目标…

建设专业网站运营团队夜蝶直播app下载安装

许多业务流程要求在将来某个日期安排事件。例如,在与客户进行初次销售联系后,我们可能希望在将来的某个时间安排跟进电话。EasyNetQ可以通过其Future Publish功能帮助您实现此功能。例如,这里我们使用FuturePublish扩展方法来安排未来一个月的…

网站建设教程资源学设计用什么笔记本电脑好

1 问题 屏幕旋转之后当前activity被finish了依然被拉起来 2 分析思路 不用finish函数,使用 android.os.Process.killProcess(android.os.Process.myPid()); 还是被拉起来了,然后采用 System.exit(0); 还是被拉起来了,然后我就看app的进程,有2个进程,当一个activity被finish…

西安门户网站新乡网页制作

来源:云头条作者:Paul Smith-Goodson是知名研究分析公司Moor Insights & Strategy的量子计算常驻分析师。英特尔公司正迅速取得进展,将超导量子计算测试芯片的量子位增加到更多数量:从7个量子位增加到17个量子位,现…

济南饰品行业网站开发山东闪电建站网

Description 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。我们把第一个图的局面记为:12345678.把第二个图的局面…

网站导入链接营销网站建设收费标准

目录 初始化列表 定义 特点 必须使用初始化列表的成员变量 初始化顺序 隐式类型转换 示例 explicit关键字 初始化列表 Date::Date(const Date& d) {_year d._year;_month d._month;_day d._day; }Date::Date(const Date& d) :_year(d._year),_month(d._mon…

网站页面设计策划书昆明企业网站建设一条龙

Java EE 8包括对JSON处理API的更新,并使其与JSON的最新IEFT标准保持同步。 他们是: JSON指针 RFC 6901 JSON补丁 RFC 6902 JSON合并修补程序 RFC 7396 我将在这个迷你系列中涵盖这些主题。 入门 要开始使用JSON-P,您将需要Maven中央存储…

专业做h5网站嘉瑞建设集团有限公司网站

CAD发给客户没字体怎么办?快速打包DWG外部参照、字体、图片、打印样式!有没有遇见过这样的情况:图纸发给客户,外部参照的文件没有一起打包发出去,被老板和客户臭骂一顿。图纸发给审图,没有字体,…

海外网站建设公司熬夜必备黄

Python-大数据分析之常用库 1. 数据采集与第三方数据接入 1-1. Beautiful Soup ​ Beautiful Soup 是一个用于解析HTML和XML文档的库,非常适用于网页爬虫和数据抓取。可以提取所需信息,无需手动分析网页源代码,简化了从网页中提取数据的过…

人才招聘类网站开发文档网络舆情处置方案

第一章 计算机基础知识1.1 概述1.1.1 什么是计算机1.1.2 计算机的发展概况1.1.3 计算机的应用领域1.1.4 计算机的应用领域1.2 计算机中的数与编码1.2.1 二进制的基本概念1.2.2 编码1.3 计算机程序设计语言1.3.1 机器语言1.3.2 汇编语言1.3.3 高级语言1.4 计算机的…

创办一个网站多少钱百度游戏中心

为了系统的完整,必须要有可行性分析的,系统的可行性关系到生存问题,分析其意义可否利用本系统来弥补线下管理模式中的不足之处等,通过本系统来减少工作量,使管理者与用户的工作和管理效率更高。对此体现出更多的意义和…

品牌型网站制作有哪些公司百度下载免费安装到桌面

1. 启动工程 找到工程的路径,找到启动的bat文件,这里以 d:/so-vits-svc为例。 2. 启动过程 启动后会出现cmp的一个弹框,初始启动相对较慢,请耐心等待一会儿,启动完成后,会出现一个页面,如下…