一,zygote进程
zygote进程的父进程是init,zygote也是所有应用的父进程,也是system_server进程的父进程。
1.1 Zygote系统源码组成
1) Zygote.java(frameworks/base/core/java/com/android/internal/os/)
提供访问vm的zygote接口,主要是包装Linux系统的fork,以 一个新的vm实例进程。
2) ZygoteConnection.java (frameworks/base/core/java/com/android/internal/os/)
Zygote的socket连接管理及其参数解析,AMS建立应用进程的请求是通过socket发送命令参数给zygote。
3) ZygoteInit.java(frameworks/base/core/java/com/android/internal/os/)
Zygote系统的main函数入口。
1.2 Zygote的启动
System/core/rootdir/init.rc中会把具体的zygote*.rc文件import进来:
import /init.${ro.zygote}.rc
这里根据不同的硬件平台加载不同的.rc,可以参看multilibbuild:http://blog.csdn.net/lin20044140410/article/details/79265521
以init.zygote64.rc为例,启动命令如下:
service zygote /system/bin/app_process64-Xzygote /system/bin --zygote --start-system-server
class main
socket zygotestream 660 root system
其中的关键字service:通知init进程创建一个名为zygote的进程,此zygote进程要执行的程序路径是system/bin/app_process64,后面是传递给app_process程序的参数。
关键字class:指定class类型是main。
关键字socket:表示这个zygote进程需要一个名称为zygote的socket资源, 系统启动后,会在/dev/socket/ 目录下看到一个名为zygote的文件。
App_process程序对应源码:frameworks/base/cmds/app_process/其中app_main.cpp的main函数是入口函数。
1)具体分析启动脚本:
在init.rc中,是以service的形式来启动zygote进程,在解析init.rc文件时,会调用service::start函数来启动zygote,也就是解析其中的service命令。具体代码:
Android/system/core/init/service.cpp
bool Service::Start() {
……
pid_t pid = fork();
if (pid == 0) {
umask(077);
for (const auto& ei : envvars_) {
add_environment(ei.name.c_str(), ei.value.c_str());
}
for (const auto& si : sockets_) {
int socket_type = ((si.type == "stream" ? SOCK_STREAM :
(si.type == "dgram" ? SOCK_DGRAM :
SOCK_SEQPACKET)));
const char* socketcon =
!si.socketcon.empty() ? si.socketcon.c_str() : scon.c_str();
int s = create_socket(si.name.c_str(), socket_type, si.perm,
si.uid, si.gid, socketcon);
if (s >= 0) {
PublishSocket(si.name, s);
}
}
}
}
每个service命令都会让init进程调用fork函数来创建一个新的进程,在新的进程中会处理其中的socket选项,对于每个socket选项来说,都会通过函数create_socket来在/dev/socket/目录下创建一个文件,
在看create_socket,调用函数socket()创建一个socket,使用文件描述符来描述这个socket。
System/core/init/Util.cpp
int create_socket(const char *name, int type, mode_t perm, uid_t uid,
gid_t gid, const char *socketcon){
struct sockaddr_un addr;
int fd, ret, savederrno;
char *filecon;
//创建一个socket,unix domain socket,
fd = socket(PF_UNIX, type, 0);
if (fd < 0) {
ERROR("Failed to open socket '%s': %s\n", name, strerror(errno));
return -1;
}
//为socket创建一个类型为AF_UNIX的socket地址addr。
memset(&addr, 0 , sizeof(addr));
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s",
name);
ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));
return fd;
}
接着看PublishSocket()函数,将指向socket的文件描述符fd,添加到环境变量中。
System/core/init/Service.h
#define ANDROID_SOCKET_ENV_PREFIX "ANDROID_SOCKET_"
#define ANDROID_SOCKET_DIR "/dev/socket"
System/core/init/Service.cpp
void Service::PublishSocket(const std::string& name, int fd) const {
std::string key = StringPrintf(ANDROID_SOCKET_ENV_PREFIX "%s", name.c_str());
std::string val = StringPrintf("%d", fd);
add_environment(key.c_str(), val.c_str());
/* make sure we don't close-on-exec */
fcntl(fd, F_SETFD, 0);
}
后面都是通过环境变量ANDROID_SOCKET_socket来获取这个文件描述的值。
2)zygote的入口函数main。
功能是创建AppRuntime实例,然后调用AppRuntime的start()启动进程。
Frameworks/base/cmds/app_process/App_main.cpp
int main(int argc, char* const argv[]){
//创建AppRuntime实例
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
//解析启动参数
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
//后面讲进程名字设置为niceName(zygote)
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());
}
//启动zygote,第一个参数是一个className:
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}
}
3)zygote的启动函数start()
调用startVM在zygote中创建一个虚拟机实例。
classAppRuntime : public AndroidRuntime…,AppRuntime继承自AndroidRuntime,runtime的start()方法调用的是AndroidRuntime中的定义。Frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)
{
//启动虚拟机,其中mJavaVM是:JavaVM* mJavaVM;Java虚拟机指针变量,
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
//用虚拟机实例注册jni函数。
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
//根据传入的参数className调用com.android.internal.os.ZygoteInit的main,启动zygote进程。
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
free(slashClassName);
}
ZygoteInit.java的main()函数。
Frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
try {
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
}
}
//创建一个socket接口,
registerZygoteSocket(socketName);
//预加载一些资源
preload();
//启动systemServer组件
startSystemServer(abiList, socketName);
//调用runSelectLoop,进入无线循环,在前面创建的socket接口上等待,等待新的到socket的连接发生,然后从连接中读取请求命令,以孵化新的进程。
runSelectLoop(abiList);
closeServerSocket();
} (MethodAndArgsCaller caller) {
caller.run();
}
}
private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
//通过环境变量ANDROID_SOCKET_zygote,获取/dev/socket/zygote文件的文件描述符,
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}
//通过这个socket的文件描述符创建一个LocalServerSocket,然后监听这个socket。
try {
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
sServerSocket = new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
其中预加载资源主要是预装Framework的部分类和资源,分为两类:
1)文本文件framework/base/preload-class中定义的类,这个文本文件是由framework/base/tools/preload子项目编译生成的。
2)加载preload-resources,主要是framework/base/core/res/res/values/arrays.xml中定义的drawable资源,color资源,这些资源通常有个前缀preloaded_***
4)跟zygote进程中的socket实现连接
当启动一个应用时,AMS通过函数Process.start创建一个新的进程,Process.start会通过socket连接到zygote进程,并由zygote进程实现创建应用进程的功能。Process通过函数openZygoteSocketIfNeeded连接到zygote进程中的socket。
Frameworks/base/core/java/android/os/Process.java
static ZygoteState primaryZygoteState;
private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
return primaryZygoteState;
}
public static ZygoteState connect(String socketAddress) throws IOException {
DataInputStream zygoteInputStream = null;
BufferedWriter zygoteWriter = null;
final LocalSocket zygoteSocket = new LocalSocket();
try {
//通过LocalSocketAddress实现LocalSocket到LocalServerSocket的连接。
zygoteSocket.connect(new LocalSocketAddress(socketAddress,
LocalSocketAddress.Namespace.RESERVED));
zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream());
zygoteWriter = new BufferedWriter(new OutputStreamWriter(
zygoteSocket.getOutputStream()), 256);
} catch (IOException ex) {
try {
zygoteSocket.close();
} catch (IOException ignore) {
}
throw ex;
}
String abiListString = getAbiList(zygoteWriter, zygoteInputStream);
Log.i("Zygote", "Process: zygote socket opened, supported ABIS: " + abiListString);
return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter,
Arrays.asList(abiListString.split(",")));
}
试着去打开socket,如果已经打来了就什么也不做。前面在zygoteInit.java中,提到通过registerZygoteSocket,创建了一个LocalServerSocket实例,这个LocalServerSocket类的构造函数中的参数是一个代表/dev/socket/zygote/文件的文件描述符,所以Process.java所在的进程只要能连接到LocalServerSocket,就可以通过LocalServerSocket中持有的socket文件描述符,实现跟zygote进程通信。在执行LocalSocket.connect()时,创建的LocalSocketAddress实现了到LocalServerSocket的连接,其中LocalSocket就是连接到zygote进程的本地对象,ZygoteState是对这个实现的一个封装,Process.java中实际是通过ZygoteState中输出流BufferedWriter writer往socket中写入请求命令的。
接下来Zygote进程的runSelectLoop()循环中,会接收到创建新的应用进程的请求,
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList fds = new ArrayList();
ArrayList peers = new ArrayList();
fds.add(sServerSocket.getFileDescriptor());
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
for (int i = pollFds.length - 1; i >= 0; --i) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done = peers.get(i).runOnce();
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
AMS请求zygote创建一个进程的过程大概是:
1)AMS调用startProcessLocked函数
2)Process.java中的start方法被调用
3)Process.java中的startViaZygote方法被调用,在这个函数中把启动参数存入列表ArrayList
4)构造一个LocalSocket类型的本地socket接口
5)通过该LocalSocket对象构造一个BufferedWriter对象
6)通过BufferedWrite对象把argsForZygote列表中的参数传递给zygote中的LocalServerSocket对象。
7)在zygote端调用Zygote.forkAndSpecialize()汗水和孕育一个新的应用进程。