Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
ArrayList<ZygoteConnection> peers = new ArrayList<>();
//将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 = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
} else {
pollFDs = new StructPollfd[socketFDs.size()];
}
int pollIndex = 0 ;
for (FileDescriptor socketFD : socketFDs) {
//关注事件到来
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = socketFD;
pollFDs[pollIndex].events = ( short ) POLLIN;
++pollIndex;
}
final int usapPoolEventFDIndex = pollIndex;
if (mUsapPoolEnabled) {
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = mUsapPoolEventFD;
pollFDs[pollIndex].events = ( short ) POLLIN;
++pollIndex;
// The usapPipeFDs array will always be filled in if the USAP Pool is enabled.
assert usapPipeFDs != null ;
for ( int usapPipeFD : usapPipeFDs) {
FileDescriptor managedFd = new FileDescriptor();
managedFd.setInt$(usapPipeFD);
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = managedFd;
pollFDs[pollIndex].events = ( short ) POLLIN;
++pollIndex;
}
}
int pollTimeoutMs;
if (mUsapPoolRefillTriggerTimestamp == INVALID_TIMESTAMP) {
pollTimeoutMs = - 1 ;
} else {
long elapsedTimeMs = 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;
} else if (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);
}
}
int pollReturnValue;
try {
//等待事件到来
pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
} catch (ErrnoException ex) {
throw new RuntimeException( "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 {
boolean usapPoolFDRead = 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());
} else if (pollIndex < usapPoolEventFDIndex) {
// Session socket accepted from the Zygote server socket
//说明接收AMS发送过来创建应用程序的请求,调用processOneCommand来创建新的应用程序进程
try {
//有socket连接,创建ZygoteConnection对象,并添加到fds
ZygoteConnection connection = peers.get(pollIndex);
boolean multipleForksOK = !isUsapPoolEnabled()
&& ZygoteHooks.isIndefiniteThreadSuspensionSafe();
//处理连接
final Runnable 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 ) {
throw new IllegalStateException( "command == null" );
}
return command;
} else {
// We're in the server - we should never have any commands to run.
if (command != null ) {
throw new IllegalStateException( "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 ;
}
}
......
}
|