应用孵化服务appspawn
appspawn
是应用程序孵化模块,它在系统中以服务进程的形式存在,并且是系统的核心进程之一,它由init进程拉起,用于启动应用程序。它类似于Android操作系统里面的Zygote
进程,是所有应用程序进程的父进程。
code-1.0/base/startup/services/appspawn_lite/
模块代码位于上面的路径,下面是编译配置文件。模块编译生成bin档appspawn
。模块依赖于liteipc_adapter(ipc driver交互适配层)、samgr(系统能力管理者封装层)、cjson_shared(封装JSON操作的第三方C库)等。
code-1.0/base/startup/services/appspawn_lite/BUILD.gn
executable("appspawn") {
sources = [
"src/main.c",
"src/appspawn_process.c",
"src/appspawn_service.c",
"src/appspawn_message.c",
"src/appspawn_adapter.c",
]
deps = [
"//third_party/bounds_checking_function:libsec_shared",
"//foundation/distributedschedule/services/samgr_lite/samgr:samgr",
"//foundation/communication/frameworks/ipc_lite:liteipc_adapter",
"//third_party/cJSON:cjson_shared",
]
}
appspawn进程载体/壳体逻辑
code-1.0/base/startup/services/appspawn_lite/src/main.c
int main(int argc, char * const argv[])
{
// 1. ipc module init
// 这行是关键:启动appspawn服务
// 这里是调用samgr库里面的函数(非常多的逻辑封装在samgr库里面)
HOS_SystemInit();
// 2. register signal for SIGCHLD
// 捕获SIGCHLD信号(只是捕获,并没有进一步处理)
SignalRegist();
// 3. keep process alive
// 保持进程不退出
HILOG_INFO(HILOG_MODULE_HIVIEW, "[appspawn] main, entering wait.");
while (1) {
// pause only returns when a signal was caught and the signal-catching function returned.
// pause only returns -1, no need to process the return value.
(void)pause();
}
}
appspawn服务
code-1.0/base/startup/services/appspawn_lite/include/appspawn_service.h
#define APPSPAWN_SERVICE_NAME "appspawn"
enum APPSPAWN_FUNCID {
ID_CALL_CREATE_SERVICE = 0,
ID_CALL_BUT
};
应用孵化服务的名字是appspawn
,目前定义实现了一个功能创建服务ID_CALL_CREATE_SERVICE
。
code-1.0/base/startup/services/appspawn_lite/src/appspawn_service.c
static AppSpawnService g_appSpawnService = {
.GetName = GetName,
.Initialize = Initialize,
.MessageHandle = MessageHandle,
.GetTaskConfig = GetTaskConfig,
SERVER_IPROXY_IMPL_BEGIN,
.Invoke = Invoke,
IPROXY_END,
};
遵循系统的服务框架,实现GetName()、Initialize()、MessageHandle()、GetTaskConfig()
和Invoke()
五个接口。
前面四个接口都是常规实现,分别是:返回服务的名字、保存服务的Identity、空实现、返回服务的任务设置。
Invoke()是appspawn服务的核心,也就是appspawn提供的系统能力的具体实现,即启动应用程序。
创建进程
appspawn
服务的端点线程从ipc driver收到启动应用的请求消息后,会把消息添加到自己的消息队列。任务处理线程读取到消息之后,会调用Invoke()函数,同时传递消息数据过来。下面就是Invoke()处理数据的过程。
code-1.0/base/startup/services/appspawn_lite/src/appspawn_service.c
static int Invoke(IServerProxy* iProxy, int funcId, void* origin, IpcIo* req, IpcIo* reply)
{
(void)iProxy;
(void)origin;
// 需要返回数据给调用方,所以reply不能为NULL
if (reply == NULL) {
HILOG_ERROR(HILOG_MODULE_HIVIEW, "[appspawn] invoke, reply NULL!");
return EC_BADPTR;
}
// funcId必须为ID_CALL_CREATE_SERVICE,并且请求数据不能为NULL
if (funcId != ID_CALL_CREATE_SERVICE || req == NULL) {
HILOG_ERROR(HILOG_MODULE_HIVIEW, "[appspawn] invoke, funcId %{public}d invalid, reply %{public}d.",\
funcId, INVALID_PID);
IpcIoPushInt64(reply, INVALID_PID);
return EC_BADPTR;
}
// 从请求数据构建MessageSt结构体
BuffPtr* dataPtr = IpcIoPopDataBuff(req);
MessageSt msgSt = {0};
int ret = SplitMessage((char*)dataPtr->buff, dataPtr->buffSz, &msgSt);
// 释放req数据buffer
if (FreeBuffer(NULL, dataPtr->buff) != LITEIPC_OK) {
HILOG_ERROR(HILOG_MODULE_HIVIEW, "[appspawn] invoke, free buffer failed!");
}
// 执行创建进程
pid_t newPid = CreateProcess(&msgSt);
// 释放msgSt占用的内存
FreeMessageSt(&msgSt);
// 把创建的进程的PID返回给调用方
IpcIoPushInt64(reply, newPid);
return ((newPid > 0) ? EC_SUCCESS : EC_FAILURE);
}
code-1.0/base/startup/services/appspawn_lite/src/appspawn_process.c
pid_t CreateProcess(const MessageSt* msgSt)
{ // 声明两个变量,用来存放进程的名字和ID
char identityIDStr[MAX_IDENTITY_ID_LENGTH];
char processNameStr[MAX_PROCESS_NAME_LENGTH];
// 变量初始化为空字符串
if (memset_s(identityIDStr, MAX_IDENTITY_ID_LENGTH, '\0', MAX_IDENTITY_ID_LENGTH) != EOK ||
memset_s(processNameStr, MAX_PROCESS_NAME_LENGTH, '\0', MAX_PROCESS_NAME_LENGTH) != EOK) {
HILOG_ERROR(HILOG_MODULE_HIVIEW, "[appspawn] create service, memset_s failed.");
return -1;
}
// 从msgSt取数据给变量赋值
if (sprintf_s(identityIDStr, MAX_IDENTITY_ID_LENGTH, "%llu", msgSt->identityID) <= 0 ||
sprintf_s(processNameStr, MAX_PROCESS_NAME_LENGTH, "%s", msgSt->bundleName) <= 0) {
HILOG_ERROR(HILOG_MODULE_HIVIEW, "[appspawn] sprintf_s failed. id %{public}llu, name %{public}s.",\
msgSt->identityID, msgSt->bundleName);
return -1;
}
// 从msgSt取得LD参数
char* envStr = GetEnvStrs(msgSt);
if (envStr == NULL) {
return -1;
}
// 检查exe文件是否存在 abilityMain
struct stat pathStat = {0};
if (stat(ABILITY_EXE_FILE_FULL_PATH, &pathStat) != 0) {
HILOG_ERROR(HILOG_MODULE_HIVIEW, "[appspawn] stat %{public}s failed, err %{public}d.",\
ABILITY_EXE_FILE_FULL_PATH, errno);
free(envStr);
return -1;
}
// 调用fork()创建一个进程
pid_t newPID = fork();
if (newPID < 0) {
HILOG_ERROR(HILOG_MODULE_HIVIEW, "[appspawn] create process, fork failed! err %{public}d.", errno);
free(envStr);
return -1;
}
// in child process
if (newPID == 0) {
// 设置权限
// 设置进程的用户ID和组ID
if (SetPerms(msgSt->uID, msgSt->gID) != 0) {
HILOG_ERROR(HILOG_MODULE_HIVIEW, "[appspawn] process %{public}s exit!", processNameStr);
_exit(0x7f); // 0x7f: user specified
}
char* argv[] = {ABILITY_EXE_FILE_NAME, identityIDStr, processNameStr, NULL};
char* env[] = {envStr, NULL};
// 执行exe文件abilityMain(在新创建的进程里面)
if (execve(ABILITY_EXE_FILE_FULL_PATH, argv, env) != 0) {
HILOG_ERROR(HILOG_MODULE_HIVIEW, "[appspawn] execve %{public}s failed! err %{public}d.",\
ABILITY_EXE_FILE_FULL_PATH, errno);
}
HILOG_ERROR(HILOG_MODULE_HIVIEW, "[appspawn] sub-process exit, pid %{public}d.", getpid());
_exit(0x7f); // 0x7f: user specified
}
free(envStr);
return newPID;
}
小节:
appspawn
是所有应用进程的父进程,所有APP进程都是由appspawn进程fork()而来的。- 应用启动请求发起方,通过IPC把要启动的应用的信息通过ipc driver发送给appspawn进程
- appspawn进程fork()子进程,然后在子进程执行exe文件abilityMain,通过传参数过去
- 新创建的进程里面运行bin档abilityMain,abilityMain会执行应用程序的逻辑
- 启动参数包括:应用的名字和ID、LD参数、用户ID和组ID
继续分析,下面进入到abilityMain模块。