一、task_struct
Android的进程管理建立在Linux内核的基础上。Linux内核通过一个被称为进程描述符的task_struct结构体来管理进程,这个结构体包含了一个进程所需的所有信息。它定义在include/linux/sched.h文件中或者Android的kernel/msm-4.9/include/linux/sched.h中。包含一下的信息:
image
其中,进程的状态有以下取值:
image
二、进程创建流程
idle进程 -> init进程 -> zygote进程 -> system_server进程 →App进程
他们之间的关系如下:
image
64位下有两个zygote,zygote64和zygote。64位应用的父进程是zygote64,它的pgid也是zygote64的pid;32位应用的父进程是zygote,它的pgid却是zygote64的pid,如:com.ss.android.article.news的父进程是zygote(1112),但它的pgid是zygote64(1111),这是怎么回事呢?原来不管32位或64位的zygote,它在创建完子进程后,会调用setChildPgid()来改变子进程的pgid。
image
多个进程组还可以构成一个会话 (session),sid标识会话id,Android中进程的sid基本都是0。
一张更为详细的图:
image
ZygoteServer启动过程:
image
Zygote本身是一个Native的应用程序,刚开始的名字为“app_process”,运行过程中,通过调用setArgv0将名字改为Zygote。
ZygoteInit进程启动后,会注册一个Socket,在runSelectLoop方法中开启一个while死循环等待ActivityManagerService创建新进程的请求,其次,ZygoteInit启动了SystemServer进程,执行SystemServer的main方法。
Socket通信框架:
image
LocalSocket就是作为客户端建立于服务端的连接,发送数据。LocalServerSocket作为服务端使用,建立服务端的socket监听客户端请求,典型的C/S架构
三、如何创建一个进程
#inlucde<unistd.h>
#inlucde<stdio.h>
#inlucde<wait.h>
int main(){
int count = 0;
pid_t fpid = fork();
if( fpid < 0){
printf(“创建子进程失败”);
} else if( fpid == 0){
printf(“子进程Id:%d\n”,getpid());
} else {
printf(“父进程Id:%d\n”,getpid());
}
printf(“count=%d\n”,count);
waitpid(fpid,NULL,0); // 暂时停止目前进程的执行,直到有信号来到或子进程结束
return 0;
}
fork函数执行一次,返回两次,第一次返回父进程的id,第二次返回子进程的id。
count是全局变量,子进程和父进程同时操作,但是互相不受影响
fork()使用写时复制,copy-on-write,是一种可以推迟甚至避免拷贝数据的技术。内核此时并不复制整个进程的地址空间,而是让父子进程共享同一个地址空间。只用在需要写入的时候才会复制地址空间,从而使各个进行拥有各自的地址空间。如下图所示,同左到右大的方向箭头表示复制内容:
image
为这四个部分分配物理块,P2的:正文段–>PI的正文段的物理块,指的是不为P2分配正文段块,让P2的正文段指向P1的正文段块,数据段–>P2自己的数据段块(为其分配对应的块),堆–>P2自己的堆块,栈–>