From 4bc89027fc7e3444ee8fec666a4e1ff70ca7d8c6 Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Fri, 21 Jan 2022 16:35:01 +0800 Subject: [PATCH] =?UTF-8?q?Add:=20=E5=A2=9E=E5=8A=A0=E7=BB=91=E6=A0=B8?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=EF=BC=8C=E8=A7=A3=E6=9E=90'd-caps',=20'apl'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xionglei6 --- services/init/include/init_service.h | 9 +++ services/init/include/init_service_manager.h | 3 + services/init/init_common_service.c | 40 +++++++++++++ services/init/init_service_manager.c | 63 +++++++++++++++++++- 4 files changed, 112 insertions(+), 3 deletions(-) diff --git a/services/init/include/init_service.h b/services/init/include/init_service.h index ef19acf8..11f456c7 100755 --- a/services/init/include/init_service.h +++ b/services/init/include/init_service.h @@ -46,6 +46,7 @@ extern "C" { #define SERVICE_ATTR_DYNAMIC 0x100 // dynamic service #define SERVICE_ATTR_ONDEMAND 0x200 // ondemand, manage socket by init +#define MAX_APL_NAME 32 #define MAX_SERVICE_NAME 32 #define MAX_WRITEPID_FILES 100 @@ -57,6 +58,11 @@ extern "C" { #define SERVICES_ARR_NAME_IN_JSON "services" +typedef struct { + int *cpus; + int cpuNum; +} CpuArgs; + typedef struct { uid_t uID; gid_t *gIDArray; @@ -83,6 +89,9 @@ typedef struct { int crashTime; unsigned int attribute; int importance; + char apl[MAX_APL_NAME + 1]; + ServiceArgs capsArgs; + CpuArgs cpuInfo; Perms servPerm; ServiceArgs pathArgs; ServiceArgs extraArgs; diff --git a/services/init/include/init_service_manager.h b/services/init/include/init_service_manager.h index 37a60a05..4a5c224a 100755 --- a/services/init/include/init_service_manager.h +++ b/services/init/include/init_service_manager.h @@ -33,6 +33,9 @@ extern "C" { #define CRITICAL_STR_IN_CFG "critical" #define DISABLED_STR_IN_CFG "disabled" #define CONSOLE_STR_IN_CFG "console" +#define D_CAPS_STR_IN_CFG "d-caps" +#define APL_STR_IN_CFG "apl" +#define CPU_CORE_STAR_IN_CFG "cpucore" #define MAX_SERVICES_CNT_IN_FILE 100 diff --git a/services/init/init_common_service.c b/services/init/init_common_service.c index f6c40e4e..a3410af3 100755 --- a/services/init/init_common_service.c +++ b/services/init/init_common_service.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #ifdef __MUSL__ #include #endif @@ -177,6 +179,41 @@ void SetSecon(Service *service) #endif // WITH_SELINUX } +static int SetAffinityBetweenProcAndCore(pid_t pid, int cpuIndex) +{ + cpu_set_t setMask; + CPU_ZERO(&setMask); + CPU_SET(cpuIndex, &setMask); + int ret = sched_setaffinity(pid, sizeof(cpu_set_t), &setMask); + if (ret != 0) { + INIT_LOGI("Set affinity between process(pid=%d) with CPU's core %d failed", pid, cpuIndex); + return SERVICE_FAILURE; + } else { + INIT_LOGE("Set affinity between process(pid=%d) with CPU's core %d successfully", pid, cpuIndex); + } + return SERVICE_SUCCESS; +} + +static int BindCpuCore(Service *service) +{ + if (service == NULL || service->cpuInfo.cpuNum <= 0) { + return SERVICE_SUCCESS; + } + long cpuNum = sysconf(_SC_NPROCESSORS_CONF); + INIT_ERROR_CHECK(service->cpuInfo.cpuNum <= cpuNum, return SERVICE_FAILURE, + "%s cpus cores exceeds total number of device cores", service->name); + int index = 0; + for (int i = 0; i < service->cpuInfo.cpuNum; i++) { + index = (int)service->cpuInfo.cpus[i]; + if ((int)cpuNum <= index) { + INIT_LOGW("%s core number %d of CPU cores does not exist", service->name, index); + continue; + } + (void)SetAffinityBetweenProcAndCore(getpid(), index); + } + return SERVICE_SUCCESS; +} + int ServiceStart(Service *service) { INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "start service failed! null ptr."); @@ -205,6 +242,9 @@ int ServiceStart(Service *service) if (service->attribute & SERVICE_ATTR_CONSOLE) { OpenConsole(); } + // bind cpu core + INIT_CHECK_ONLY_ELOG(BindCpuCore(service) == SERVICE_SUCCESS, + "binding core number failed for service %s", service->name); // permissions INIT_ERROR_CHECK(SetPerms(service) == SERVICE_SUCCESS, _exit(PROCESS_EXIT_CODE), "service %s exit! set perms failed! err %d.", service->name, errno); diff --git a/services/init/init_service_manager.c b/services/init/init_service_manager.c index 77db7ca4..ff20db16 100755 --- a/services/init/init_service_manager.c +++ b/services/init/init_service_manager.c @@ -154,7 +154,13 @@ void ReleaseService(Service *service) } FreeServiceArg(&service->pathArgs); FreeServiceArg(&service->writePidArgs); + FreeServiceArg(&service->capsArgs); + if (service->cpuInfo.cpus != NULL) { + free(service->cpuInfo.cpus); + service->cpuInfo.cpus = NULL; + } + service->cpuInfo.cpuNum = 0; if (service->servPerm.caps != NULL) { free(service->servPerm.caps); service->servPerm.caps = NULL; @@ -215,7 +221,12 @@ static int GetServiceArgs(const cJSON *argJson, const char *name, int maxCount, for (int i = 0; i < count + 1; ++i) { args->argv[i] = NULL; } - args->count = count + 1; + // ServiceArgs have a variety of uses, some requiring a NULL ending, some not + if (strcmp(name, D_CAPS_STR_IN_CFG) != 0) { + args->count = count + 1; + } else { + args->count = count; + } for (int i = 0; i < count; ++i) { char *curParam = cJSON_GetStringValue(cJSON_GetArrayItem(obj, i)); INIT_ERROR_CHECK(curParam != NULL, return SERVICE_FAILURE, "Invalid arg %d", i); @@ -495,6 +506,7 @@ static int CheckServiceKeyName(const cJSON *curService) char *cfgServiceKeyList[] = { "name", "path", "uid", "gid", "once", "importance", "caps", "disabled", "writepid", "critical", "socket", "console", "dynamic", "file", "ondemand", + "d-caps", "apl", "cpucore", #ifdef WITH_SELINUX SECON_STR_IN_CFG, #endif // WITH_SELINUX @@ -573,6 +585,49 @@ int GetCritical(const cJSON *curArrItem, Service *curServ, const char *attrName return SERVICE_SUCCESS; } +static int Comparefunc(const void *before, const void *after) +{ + return (*(int*)before - *(int*)after); +} + +static int GetCpuArgs(const cJSON *argJson, const char *name, CpuArgs *args) +{ + INIT_ERROR_CHECK(argJson != NULL, return SERVICE_FAILURE, "Invalid argJson"); + cJSON *obj = cJSON_GetObjectItem(argJson, name); + INIT_CHECK(obj != NULL, return SERVICE_FAILURE); + + int ret = cJSON_IsArray(obj); + INIT_ERROR_CHECK(ret, return SERVICE_FAILURE, "Invalid type"); + int count = cJSON_GetArraySize(obj); + int tmpArray[count]; + for (int i = 0; i < count; ++i) { + cJSON *item = cJSON_GetArrayItem(obj, i); + INIT_ERROR_CHECK(item != NULL, return SERVICE_FAILURE, "prase invalid"); + tmpArray[i] = (int)cJSON_GetNumberValue(item); + } + qsort(tmpArray, count, sizeof(int), Comparefunc); + int cpuCount = 0; + for (int j = 0; j < count; j++) { + if (j == 0 && tmpArray[0] == 0) { + tmpArray[cpuCount++] = 0; + continue; + } + if (tmpArray[j] != tmpArray[j-1]) { + tmpArray[cpuCount++] = tmpArray[j]; + } + } + args->cpus=(int*)malloc(cpuCount * sizeof(int)); + INIT_ERROR_CHECK(args->cpus != NULL, return SERVICE_FAILURE, "Failed to malloc for argv"); + for (int i = 0; i < cpuCount; ++i) { + args->cpus[i] = -1; + } + args->cpuNum = cpuCount; + for (int i = 0; i < count; ++i) { + args->cpus[i] = tmpArray[i]; + } + return SERVICE_SUCCESS; +} + int ParseOneService(const cJSON *curItem, Service *service) { INIT_CHECK_RETURN_VALUE(curItem != NULL && service != NULL, SERVICE_FAILURE); @@ -604,8 +659,10 @@ int ParseOneService(const cJSON *curItem, Service *service) ret = GetServiceAttr(curItem, service, CONSOLE_STR_IN_CFG, SERVICE_ATTR_CONSOLE, NULL); INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get console for service %s", service->name); - ret = GetServiceArgs(curItem, "writepid", MAX_WRITEPID_FILES, &service->writePidArgs); - INIT_CHECK_ONLY_ELOG(ret == 0, "No writepid arg for service %s", service->name); + (void)GetServiceArgs(curItem, "writepid", MAX_WRITEPID_FILES, &service->writePidArgs); + (void)GetServiceArgs(curItem, D_CAPS_STR_IN_CFG, MAX_WRITEPID_FILES, &service->capsArgs); + (void)GetStringItem(curItem, APL_STR_IN_CFG, service->apl, MAX_APL_NAME); + (void)GetCpuArgs(curItem, CPU_CORE_STAR_IN_CFG, &service->cpuInfo); ret = GetServiceCaps(curItem, service); INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get caps for service %s", service->name); ret = GetDynamicService(curItem, service); -- GitLab