程序的启动是从进程启动开始的,换句话说只有程序进程启动后,程序才会加载和执行,在AMS启动程序时首先会判断当前进程是否启动,对未启动的进程会发送请求,Zygote在收到请求后创建新的进程;
1、Zygote监听客户端请求
由Android进阶知识树——Android系统的启动过程知道,系统的启动会执行到ZygoteInit.main()方法;
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();//1
zygoteServer.registerServerSocketFromEnv(socketName);
caller = zygoteServer.runSelectLoop(abiList); //2
}
在main中创建并注册了服务端的Socket,然后执行runSelectLoop()循环等待AMS的请求创建进程,前一篇文章中跳过了这个部分,本片文章来分析下系统如何实现Socket通信的
- registerServerSocketFromEnv()
void registerServerSocketFromEnv(String socketName) {
if (mServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;//1
try {
String env = System.getenv(fullSocketName);//2
fileDesc = Integer.parseInt(env);
}
try {
FileDescriptor fd = new FileDescriptor();//3
fd.setInt$(fileDesc);
mServerSocket = new LocalServerSocket(fd);//4
mCloseSocketFd = true;
} catch (IOException ex) {
}
}
在registerServerSocketFromEnv中()出入的参数为进程名称,由上一篇文章知道传入的为ztgote,然后使用ANDROID_SOCKET_PREFIX拼接Socket名称,最终的名称为ANDROID_SOCKET_zygote,然后将fullSocketName转换为环境变量的值,注释3处创建文件描述符,然后根据文件描述符fd创建LocalServerSocket对象;
public LocalServerSocket(FileDescriptor fd) throws IOException
{
impl = new LocalSocketImpl(fd);
impl.listen(LISTEN_BACKLOG);
localAddress = impl.getSockAddress();
}
LocalService使用select监听文件描述符,当文件描述符上出现新内容时会自动触发中断,然后中断处理函数中再次读取文件描述福符上的数据,从而获取信息;
- zygoteServer.runSelectLoop()
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
177 fds.add(mServerSocket.getFileDescriptor());//1
178 peers.add(null);
179
180 while (true) {
//2
181 StructPollfd[] pollFds = new StructPollfd[fds.size()];
182 for (int i = 0; i < pollFds.length; ++i) {
183 pollFds[i] = new StructPollfd();
184 pollFds[i].fd = fds.get(i);
185 pollFds[i].events = (short) POLLIN;
186 }
187 try {
188 Os.poll(pollFds, -1);
189 } catch (ErrnoException ex) {
190 throw new RuntimeException("poll failed", ex);
191 }
192 for (int i = pollFds.length - 1; i >= 0;