Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = newArrayList<>();
ArrayList<ZygoteConnection> peers = newArrayList<>();
//将server socket加入到fds
socketFDs.add(mZygoteSocket.getFileDescriptor());
peers.add(null);
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
while(true) {
fetchUsapPoolPolicyPropsWithMinInterval();
mUsapPoolRefillAction = UsapPoolRefillAction.NONE;
int[] usapPipeFDs = null;
StructPollfd[] pollFDs;
//每次循环,都重新创建需要监听的pollFds
if(mUsapPoolEnabled) {
usapPipeFDs = Zygote.getUsapPipeFDs();
pollFDs = newStructPollfd[socketFDs.size() + 1+ usapPipeFDs.length];
} else{
pollFDs = newStructPollfd[socketFDs.size()];
}
intpollIndex = 0;
for(FileDescriptor socketFD : socketFDs) {
//关注事件到来
pollFDs[pollIndex] = newStructPollfd();
pollFDs[pollIndex].fd = socketFD;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
}
finalintusapPoolEventFDIndex = pollIndex;
if(mUsapPoolEnabled) {
pollFDs[pollIndex] = newStructPollfd();
pollFDs[pollIndex].fd = mUsapPoolEventFD;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
// The usapPipeFDs array will always be filled in if the USAP Pool is enabled.
assertusapPipeFDs != null;
for(intusapPipeFD : usapPipeFDs) {
FileDescriptor managedFd = newFileDescriptor();
managedFd.setInt$(usapPipeFD);
pollFDs[pollIndex] = newStructPollfd();
pollFDs[pollIndex].fd = managedFd;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
}
}
intpollTimeoutMs;
if(mUsapPoolRefillTriggerTimestamp == INVALID_TIMESTAMP) {
pollTimeoutMs = -1;
} else{
longelapsedTimeMs = System.currentTimeMillis() - mUsapPoolRefillTriggerTimestamp;
if(elapsedTimeMs >= mUsapPoolRefillDelayMs) {
// The refill delay has elapsed during the period between poll invocations.
// We will now check for any currently ready file descriptors before refilling
// the USAP pool.
pollTimeoutMs = 0;
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED;
} elseif(elapsedTimeMs <= 0) {
// This can occur if the clock used by currentTimeMillis is reset, which is
// possible because it is not guaranteed to be monotonic. Because we can't tell
// how far back the clock was set the best way to recover is to simply re-start
// the respawn delay countdown.
pollTimeoutMs = mUsapPoolRefillDelayMs;
} else{
pollTimeoutMs = (int) (mUsapPoolRefillDelayMs - elapsedTimeMs);
}
}
intpollReturnValue;
try{
//等待事件到来
pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
} catch(ErrnoException ex) {
thrownewRuntimeException("poll failed", ex);
}
if(pollReturnValue == 0) {
// The poll returned zero results either when the timeout value has been exceeded
// or when a non-blocking poll is issued and no FDs are ready. In either case it
// is time to refill the pool. This will result in a duplicate assignment when
// the non-blocking poll returns zero results, but it avoids an additional
// conditional in the else branch.
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED;
} else{
booleanusapPoolFDRead = false;
//倒序处理,即优先处理已建立链接的信息,后处理新建链接的请求
while(--pollIndex >= 0) {
if((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
//server socket最先加入fds,因此这里是server socket收到数据
if(pollIndex == 0) {
// Zygote server socket
//收到新的建立通信的请求,建立通信连接
ZygoteConnection newPeer = acceptCommandPeer(abiList);
//加入到peers和fds,即下一次也开监听
peers.add(newPeer);
socketFDs.add(newPeer.getFileDescriptor());
} elseif(pollIndex < usapPoolEventFDIndex) {
// Session socket accepted from the Zygote server socket
//说明接收AMS发送过来创建应用程序的请求,调用processOneCommand来创建新的应用程序进程
try{
//有socket连接,创建ZygoteConnection对象,并添加到fds
ZygoteConnection connection = peers.get(pollIndex);
booleanmultipleForksOK = !isUsapPoolEnabled()
&& ZygoteHooks.isIndefiniteThreadSuspensionSafe();
//处理连接
finalRunnable command =
connection.processCommand(this, multipleForksOK);
// TODO (chriswailes): Is this extra check necessary?
if(mIsForkChild) {
// We're in the child. We should always have a command to run at
// this stage if processCommand hasn't called "exec".
if(command == null) {
thrownewIllegalStateException("command == null");
}
returncommand;
} else{
// We're in the server - we should never have any commands to run.
if(command != null) {
thrownewIllegalStateException("command != null");
}
// We don't know whether the remote side of the socket was closed or
// not until we attempt to read from it from processCommand. This
// shows up as a regular POLLIN event in our regular processing
// loop.
if(connection.isClosedByPeer()) {
connection.closeSocket();
peers.remove(pollIndex);
socketFDs.remove(pollIndex);//处理完则从fds中移除该文件描述符
}
}
} catch(Exception e) {
......
} finally{
// Reset the child flag, in the event that the child process is a child-
// zygote. The flag will not be consulted this loop pass after the
// Runnable is returned.
mIsForkChild = false;
}
}
......
}
|