内容简介:接上文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)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Programming Amazon Web Services
James Murty / O'Reilly Media / 2008-3-25 / USD 49.99
Building on the success of its storefront and fulfillment services, Amazon now allows businesses to "rent" computing power, data storage and bandwidth on its vast network platform. This book demonstra......一起来看看 《Programming Amazon Web Services》 这本书的介绍吧!