内容简介:接上文https://www.epubit.com/selfpublish/article/6093 @1未完编辑,有敏感词(代码里小写的ID居然是敏感词)。。。。那么第二个问题,当我们安装应用完成,启动应用,应用的进程是如何启动并被赋予进程属性的呢?
接上文https://www.epubit.com/selfpublish/article/6093 @1
未完编辑,有敏感词(代码里小写的ID居然是敏感词)。。。。
那么第二个问题,当我们安装应用完成,启动应用,应用的进程是如何启动并被赋予进程属性的呢?
每个应用都会运行在自己的 Dalvik 虚拟机进程中,但是为了提高启动效率,Android 不会为每个应用都新建一个 Dalvik 进程,而是采用 fork 的形式。每个进程都 fork form zygote 进程。那么 fork 比起 new ,效率提高在哪里?
因为 zygote 进程已经预加载了大部分核心和 Java 应用框架库,fork 的子进程会继承 zygote 的进程空间,也就是说,fork 的子进程,可以共享这些预加载的副本(记住,是副本,不是直接共享。fork 时,会 copy-on-write 预加载的内容),减少了重新加载核心库的时间。
当 zygote 收到启动新进程的请求时,它会 fork 自身出一个子进程,并对该子进程做特殊化处理。其源代码位于 dalvik/vm/native/dalvik_system_Zygote.c 中。forkAndSpecializeCommon() 的主要代码如下:
args, boolisSystemServer)
{
...
pID = fork();//创建新进程
if(pID ==0)//判断是否是root,有没有权限修改自己的进程属性
{
setgroupsIntarray(gIDs);//设置进程的所有组
setrlimitsFromArray(rlimits);
setgid(gID);//设置进程的组ID
setuid(uID);//设置进程的用户ID
}
...
}
args, boolisSystemServer){
...
pid = fork();//创建新进程
if(pid ==0)//判断是否是root,有没有权限修改自己的进程属性
{
setgroupsIntarray(gids);//设置进程的所有组
setrlimitsFromArray(rlimits);
setgid(gid);//设置进程的组ID
setuid(uid);//设置进程的用户ID
}
...
}
如上所示:这里设置进程的组 ID 和用户 ID,通过 fork 创建的子进程调用 setgroups Intarray 设置该进程所属的组,这样应用程序就拥有了该组的权限,并且可以通过 setgid() 及 setuid() 确定应用程序的 GID 及 UID 值。刚刚开始 fork 时,子进程是以 root 执行的,所以它可以更改自己的进程属性,当属性都设置完成,子进程就以分配的 GID 和 UID 执行,此时,子进程无法再更改自己的进程属性了,因为用户 ID 已经不是 root 即 ! = 0 了,没有修改自己进程属性的权限了。
adb shell ps,看下进程列表:
USERPIDPPIDVSZRSSWCHANADDRSNAME
root1 0 10456 2352SyS_epoll_wait0Sinit
...
root1620 1 1614572 20312poll_schedule_timeout0Szygote
...
u0_a883468 1620 1929916 112340SyS_epoll_wait0Scom.feelschaotic.demo
u0_a903574 1620 1696012 24176SyS_epoll_wait0Scom.demo.pushdemo
u0_a903607 1620 1708844 26748SyS_epoll_wait0Scom.demo.pushdemo:mult
u0_i03741 1879 1557800 11720SyS_epoll_wait0Scom.android.chrome:sandboxed
u0_a153774 1620 1690604 22056SyS_epoll_wait0Scom.google.android.ext.services
system3805 1620 1687840 19688SyS_epoll_wait0Scom.android.keychain
u0_a423831 1620 1834408 45660SyS_epoll_wait0Scom.android.chrome
...
PID 表示应用的进程 ID,PPID 表示父进程 ID,NAME 表示进程名称(一般情况下 NAME 是应用包名)。可以看到 zygote 进程是由 init 进程启动,所有的应用进程的父进程都是 zygote。USER 表示的是进程的专有用户,这个我们下次再详细讲讲 Android 的用户管理机制。
好了,既然如此,每个应用进程都分配好自己的 GID、UID和补充 GID,系统内核和守护进程就可以用这些标识来决定,是否要赋予进程权限。
权限的检查
1. 系统内核层权限检查
思考一下:如果我们的应用没有在 AndroidManifest.xml 中申请 android.permission.INTERNET 权限就进行网络请求,是不是会报 Permission denied 错误。这个权限,是谁来检查?其他进程来检查吗?明显不是,网络访问权限是由低层来进行控制的。
Android 的访问控制,和 Linux 是一样的,但 Android 增加了个特有的网络访问安全控制机制,也就是说,创建网络套接字的进程,必须属于 inet 组。
如上内核代码,current_has_network(void) 方法检查了进程的所在组。如果不在 inet 组,则直接返回错误。所以为了使我们的应用具有访问网络的能力,我们需要在 AndroidManifest.xml 中申请 INTERNET 权限,经过解析,逐步映射到内核层的组 ID 和用户 ID,最终才能通过内核层的检查。
你可能会有疑问,那非内核层的其他 C/C++ 层,要怎么拿到进程的所在组信息呢?在 PMS 初始化所有包信息之后,就会调用 mSettings.writeLPr()。
这段代码的任务就是将mPackages 中保存的所有包的信息保存到 /data/system/packages.list。所以,packages.list中保存了所有应用申请的权限,C代码只要读这个文件就能判断某个应用是否申请了我们要求的权限。
以上所述就是小编给大家介绍的《你真的了解Android权限机制吗?@2》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Django权限机制实现代码详解
- ZooKeeper ACL 权限控制机制
- Django 默认权限机制介绍及实践
- KodExplorer 4.40 发布,权限机制优化
- 你真的了解Android权限机制吗?@3
- 你真的了解Android权限机制吗?(1)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。