长期支持版本

    社区创新版本

      使用powerapi进行开发

      下载源码(可选)

      源码下载:https://gitee.com/openeuler/powerapi

      源码中部分接口还处于实验阶段,并未发布,代码中使用 RELEASE_MODE 对接口是否正式发布进行了隔离。

      当前已发布接口参考源码库中的 API 文档。

      安装软件包

      使用以下命令安装 powerapi-devel 软件包,使用提供的接口进行开发。

      yum install powerapi-devel
      

      基本流程

      查询类接口调用只需要注册,设置类接口调用前除了注册还需要请求控制权。按业务场景分,业务流程如下:
      离散型感知类业务场景:设置日志回调 -> 注册 -> 查询接口调用 -> 注销
      配置类业务场景:设置日志回调 -> 注册 -> 请求控制权 -> 配置接口调用 -> 释放控制权 -> 注销

      powerapi接口

      通用接口

      设置日志回调函数

      接口定义:PWR_API int PWR_SetLogCallback(void(LogCallback)(int level, const char *fmt, va_list vl))
      接口描述:设置日志打印回调,设置后,powerapi库将回调LogCallBack函数打印日志。如不设置,默认打印到控制台。该接口可在注册前调用。

      参数描述:

      参数类型描述
      LogCallBackvoid(*)日志打印回调函数指针

      返回值:

      类型描述
      int返回码
      0:成功
      4:失败,回调函数指针为空

      设置服务端信息

      接口定义:PWR_API int PWR_SetServerInfo(const char* socketPath)
      接口描述:该接口用于设置unix domain socket通信服务端地址信息。
      参数描述:

      参数类型描述
      socketPathconst char*服务端地址路径信息

      返回值:

      类型描述
      int返回码
      0:成功
      4:失败,回调函数指针为空

      注:
      服务端sock文件默认路径为/etc/sysconfig/pwrapis/pwrserver.sock,若在pwrapis配置文件修改默认路径,则需要保证目录权限为755,而文件权限为722。
      修改路径后需要在注册前通过该接口来告知so修改后的路径,否则连接将失败。

      注册

      接口定义:PWR_API int PWR_Register(void)
      接口描述:用于注册到powerapi service。
      参数描述:无参数
      返回值:

      类型描述
      int返回码
      0:成功
      1:失败,初始化sock客户端失败

      注销

      接口定义:PWR_API int PWR_UnRegister(void)
      接口描述:用于从服务端注销。
      参数描述:无参数
      返回值:

      类型描述
      int返回码
      0:注销成功

      请求接管能效控制权

      接口定义:PWR_API int PWR_RequestControlAuth(void)
      接口描述:该接口用于请求对系统能效控制权进行接管。上层应用接管后,系统不会自动进行能效调控,否则会自动进行能效调控。
      参数描述:无参数
      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      放弃能效控制权

      接口定义:PWR_API int PWR_ReleaseControlAuth(void)
      接口描述:该接口用于释放对系统能效的控制权。
      参数描述:无参数
      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      CPU

      获取CPU信息

      接口定义:PWR_API int PWR_CPU_GetInfo(PWR_CPU_Info *cpuInfo)
      接口描述:获取CPU信息,包含CPU基础信息,NUMA信息。
      参数描述:

      参数类型描述
      cpuinfoPWR_CPU_Info*CPU信息

      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      获取CPU Frequency能力

      接口定义:PWR_API int PWR_CPU_GetFreqAbility(PWR_CPU_FreqAbility *freqAbi, uint32_t bufferSize)
      参数描述:查询可用的CPUFreq调频域信息,可用governor和当前使用的CPUFreq驱动。

      参数类型描述
      freqAbiPWR_CPU_FreqAbility*CPUFreq能力信息
      bufferSizeuint32_tfreqAbi内存块大小。
      该内存块建议大小:
      sizeof(PWR_CPU_FreqAbility)+CPU核心数*(sizeof(int)+5)
      内存块太小,则只返回能容纳的调频域数据。

      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      获取CPU Frequency governor

      接口定义:PWR_API int PWR_CPU_GetFreqGovernor(char gov[], uint32_t size)
      接口描述:获取系统当前使用的CPUFreq调频器(默认获取第一个调频域的governor)。
      参数描述:

      参数类型描述
      govchar[]governor的名称,最大长度31。
      sizeuint32_t给定gov数组空间大小,需大于等于PWR_MAX_ELEMENT_NAME_LEN(32)。

      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      设置CPU Frequency governor

      接口定义:PWR_API int PWR_CPU_SetFreqGovernor(const char gov[])
      接口描述:设置系统当前使用的CPUFreq调频器(设置时将所有调频域设置为输入的governor)。
      参数描述:

      参数类型描述
      govchar[]governor的名称,最大长度31。
      取值如:
      conservative
      ondemand
      userspace
      powersave
      performance
      schedutil
      seep

      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      获取CPU Frequency governor所有属性值

      接口定义:PWR_API int PWR_CPU_GetFreqGovAttrs(PWR_CPU_FreqGovAttrs *govAttrs)
      接口描述:获取当前所使用的CPUFreq调频器的所有属性信息。
      参数描述:

      参数类型描述
      govAttrsPWR_CPU_FreqGovAttrs*调频器属性信息

      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      获取CPU Frequency governor属性

      接口定义:PWR_API int PWR_CPU_GetFreqGovAttr(PWR_CPU_FreqGovAttr *govAttr)
      接口描述:获取当前使用的CPUFreq属性(系统将获取第一个调频域(policy0)当前使用的governor对应的属性)。
      参数描述:

      参数类型描述
      govAttrsPWR_CPU_FreqGovAttrs*调频器属性信息

      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      设置CPU Frequency governor属性

      接口定义:PWR_API int PWR_CPU_SetFreqGovAttr(const PWR_CPU_FreqGovAttr *govAttr)
      接口描述:设置当前使用的CPUFreq属性(系统将设置第一个调频域(policy0)当前使用的governor对应的属性)。
      参数描述:

      参数类型描述
      govAttrsPWR_CPU_FreqGovAttrs*调频器属性信息。
      需指定要设置的attr名称及其value。

      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      注:
      不同的governor所支持的属性有所差异,governor所支持的属性一般在以下路径:/sys/devices/system/cpu/cpufreq/{gov}/,其中{gov}为当前使用的调频器名称。

      获取CPU工作频率范围

      接口定义:PWR_API int PWR_CPU_GetFreqRange(PWR_CPU_FreqRange *freqRange)
      接口描述:获取CPU工作频率范围(默认获取第一个调频域的工作频率范围)。
      参数描述:

      参数类型描述
      freqRangePWR_CPU_FreqRange*所获取的工作频率范围

      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      设置CPU工作频率范围

      接口定义:PWR_API int PWR_CPU_SetFreqRange(const PWR_CPU_FreqRange *freqRange)
      接口描述:设置CPU工作频率范围(把所有调频域设置成指定的频率范围)。
      参数描述:

      参数类型描述
      freqRangePWR_CPU_FreqRange*设置的工作频率范围

      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      获取CPU当前频率

      接口定义:PWR_API int PWR_CPU_GetFreq(PWR_CPU_CurFreq curFreq[], uint32_t *num, int spec)
      接口描述:获取调频域的当前频率。
      参数描述:

      参数类型描述
      curFreqPWR_CPU_CurFreq[]表示要查询的policy当前调频域的频率信息。
      spec=1时需要设置对应成员的policyId。
      输出调频域的当前频率。
      numuint32_t *curFreq数组空间长度,代表要查询的policy的个数。
      输出时为系统实际返回的有效数据长度(表现为实际policy的个数与输入num的较小值)。
      specint释放获取特定某个或某几个调频域的信息。
      0:否
      1:是,此时需要在curFreq成员中设定具体的调频域所对应的policyId,如32,64等。

      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      设置CPU当前频率

      接口定义:PWR_API int PWR_CPU_SetFreq(const PWR_CPU_CurFreq curFreq[], uint32_t num)
      接口描述:设置调频域的工作频率(CPUFreq governor为userspace时才可设置)。
      参数描述:

      参数类型描述
      curFreqPWR_CPU_CurFreq[]要设置的调频域及其频率列表。
      numuint32_tcurFreq数组空间长度,即调整policy的个数。

      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      获取CPU休眠能力和状态信息

      接口定义:PWR_API int PWR_CPU_GetIdleInfo(PWR_CPU_IdleInfo *idleInfo)
      接口描述:获取CPUIdele能力和状态信息。
      参数描述:

      参数类型描述
      idleInfoPWR_CPU_IdleInfo*CPUIdele能力和状态信息

      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      获取CPU休眠governor

      接口定义:PWR_API int PWR_CPU_GetIdleGovernor(char idleGov[], uint32_t size)
      接口描述:获取CPU休眠模式。
      参数描述:

      参数类型描述
      idleGovchar[]governor名称
      sizeuint32_tidleGov缓存区大小,最小值PWR_MAX_ELEMENT_NAME_LEN(32)

      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      设置CPU休眠governor

      接口定义:PWR_API int PWR_CPU_SetIdleGovernor(const char idleGov[])
      接口描述:设置CPU休眠模式。
      参数描述:

      参数类型描述
      idleGovchar[]governor名称,如:
      ladder
      menu
      teo
      haltpoll

      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      获取CPU&DMA时延

      接口定义:PWR_API int PWR_CPU_DmaGetLatency(int *latency)
      接口描述:获取CPU&DMA可忍受时延。
      参数描述:

      参数类型描述
      latencyint*时延(单位:us)。

      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      设置CPU&DMA时延

      接口定义:PWR_API int PWR_CPU_DmaSetLatency(int latency)
      接口描述:设置CPU&DMA可忍受时延。
      参数描述:

      参数类型描述
      latencyint*时延(单位:us)。取值范围:[0,2000000000]

      返回值:

      类型描述
      int返回码
      0:成功
      其他值:失败,参见错误码

      注:
      不同的C-state,被唤醒所需时间不同,睡得越深,唤醒时延越大,因而系统在进入C-state前会判断CPU&DMA latency,如果对应C-state的时延大于CPU&DMA latency,则不会进入C-state。
      各个C-state唤醒时延参考(单位:us)

      C-state namelatency
      C0 POLL0
      C12
      C1E10
      C340
      C6133
      C7S166
      C8300
      C9600
      C102600

      使用用例

      将以下代码保存为powerapi_test.c

      #include <stdio.h>
      #include <unistd.h>
      #include <signal.h>
      #include <string.h>
      #include <stdlib.h>
      #include <pwrapic/powerapi.h>
      
      #define MAIN_LOOP_INTERVAL 5
      #define TEST_FREQ 2400
      #define TEST_CORE_NUM 128
      #define AVG_LEN_PER_CORE 5
      #define TEST_CPU_DMA_LATENCY 2000
      #define TASK_INTERVAL 1000
      #define TASK_RUN_TIME 10
      #define TEST_FREQ_RANGE_MIN 500
      #define TEST_FREQ_RANGE_MAX 2500
      
      static int g_run = 1;
      
      static void PrintResult(char *function, int ret)
      {
          int length = 24;
          printf("[TEST ]    ");
          printf("%-*s", length, function);
          printf(":");
          if (ret == PWR_SUCCESS) {
              printf("SUCCESS ret: %d\n", ret);
          } else {
              printf("ERROR   ret: %d\n", ret);
          }
      }
      
      enum {
          DEBUG = 0,
          INFO,
          WARNING,
          ERROR
      };
      
      static const char *GetLevelName(int level)
      {
          static char debug[] = "DEBUG";
          static char info[] = "INFO";
          static char warning[] = "WARNING";
          static char error[] = "ERROR";
          switch (level) {
              case DEBUG:
                  return debug;
              case INFO:
                  return info;
              case WARNING:
                  return warning;
              case ERROR:
                  return error;
              default:
                  return info;
          }
      }
      
      void LogCallback(int level, const char *fmt, va_list vl)
      {
          char logLine[4096] = {0};
          char message[4000] = {0};
          int length = 5;
      
          if (vsnprintf(message, sizeof(message) - 1, fmt, vl) < 0) {
              return;
          }
      
          printf("[");
          printf("%-*s", length, GetLevelName(level));
          printf("]    %s\n", message);
      }
      
      static void SignalHandler(int none)
      {
          g_run = 0;
      }
      
      static void SetupSignal(void)
      {
          // regist signal handler
          (void)signal(SIGINT, SignalHandler);
          (void)signal(SIGUSR1, SignalHandler);
          (void)signal(SIGUSR2, SignalHandler);
          (void)signal(SIGTERM, SignalHandler);
          (void)signal(SIGKILL, SignalHandler);
      }
      /************************** COMMON ************************/
      static void TEST_PWR_SetLogCallback(void)
      {
          int ret = -1;
          ret = PWR_SetLogCallback(LogCallback);
          PrintResult("PWR_SetLogCallback", ret);
      }
      
      static void TEST_PWR_SetServerInfo(void)
      {
          int ret = -1;
          char str[] = "/etc/sysconfig/pwrapis/pwrserver.sock";
          ret = PWR_SetServerInfo(str);
          PrintResult("PWR_SetServerInfo", ret);
      }
      
      static void TEST_PWR_Register(void)
      {
          while (PWR_Register() != PWR_SUCCESS) {
              sleep(MAIN_LOOP_INTERVAL);
              PrintResult("PWR_Register", PWR_ERR_COMMON);
              continue;
          }
          PrintResult("PWR_Register", PWR_SUCCESS);
      }
      
      static void TEST_PWR_RequestControlAuth(void)
      {
          int ret = -1;
          ret = PWR_RequestControlAuth();
          PrintResult("PWR_RequestControlAuth", ret);
      }
      /************************** COMMON END************************/
      
      /***************************** CPU ***************************/
      static void TEST_PWR_CPU_GetInfo(void)
      {
          int ret = -1;
          PWR_CPU_Info *info = (PWR_CPU_Info *)malloc(sizeof(PWR_CPU_Info));
          if (!info) {
              return;
          }
          bzero(info, sizeof(PWR_CPU_Info));
          ret = PWR_CPU_GetInfo(info);
          PrintResult("PWR_CPU_GetInfo", ret);
          printf("    arch: %s\n    coreNum: %d\n    maxFreq: %f\n    minFreq: %f\n    "
              "modelName: %s\n    numaNum: %d\n    threadsPerCore: %d\n", info->arch,
              info->coreNum, info->maxFreq, info->minFreq, info->modelName, info->numaNum,
              info->threadsPerCore);
          for (int i = 0; i < info->numaNum; i++) {
              printf("    numa node[%d]  cpuList: %s\n", info->numa[i].nodeNo, info->numa[i].cpuList);
          }
          free(info);
      }
      
      static void TEST_PWR_CPU_GetFreq(void)
      {
          int ret = -1;
          int num = 0;
          int spec = 0;
          int i = 0;
      
          /**
           * Test 1: spec = 0, get all policy freq.
           * Set the num to the number of CPU cores
           * (it is possible that one kernel corresponds to one policy)
           */
          num = TEST_CORE_NUM;
          spec = 0;
          PWR_CPU_CurFreq cpuCurFreq1[num];
          bzero(cpuCurFreq1, num * sizeof(PWR_CPU_CurFreq));
          ret = PWR_CPU_GetFreq(cpuCurFreq1, &num, spec);
          PrintResult("1  PWR_CPU_GetFreq", ret);
          for (i = 0; i < num; i++) {
              printf("    policy[%d]: %lf\n", cpuCurFreq1[i].policyId, cpuCurFreq1[i].curFreq);
          }
      
          /**
           * Test 2: spec = 0 num = 2. get the previous 2 policies freq
           */
          ret = -1;
          // 2: previous 2 policies
          num = 2;
          spec = 0;
          PWR_CPU_CurFreq cpuCurFreq2[num];
          bzero(cpuCurFreq2, num * sizeof(PWR_CPU_CurFreq));
          ret = PWR_CPU_GetFreq(cpuCurFreq2, &num, spec);
          PrintResult("2  PWR_CPU_GetFreq", ret);
          for (i = 0; i < num; i++) {
              printf("    policy[%d]: %lf\n", cpuCurFreq2[i].policyId, cpuCurFreq2[i].curFreq);
          }
      
          /**
           * Test 3: spec = 1, get the two target policy freq
           */
          ret = -1;
          // 2: previous 2 policies
          num = 2;
          spec = 1;
          PWR_CPU_CurFreq cpuCurFreq3[num];
          bzero(cpuCurFreq3, num * sizeof(PWR_CPU_CurFreq));
          cpuCurFreq3[0].policyId = 0;
          // 32 : the Id of the second policy.
          cpuCurFreq3[1].policyId = 32;
          ret = PWR_CPU_GetFreq(cpuCurFreq3, &num, spec);
          PrintResult("3  PWR_CPU_GetFreq", ret);
          for (i = 0; i < num; i++) {
              printf("    policy[%d]: %lf\n", cpuCurFreq3[i].policyId, cpuCurFreq3[i].curFreq);
          }
      }
      
      static void TEST_PWR_CPU_SetFreq(void)
      {
          int ret = -1;
          int num = 1;
          PWR_CPU_CurFreq cpuCurFreq[num];
          bzero(cpuCurFreq, num * sizeof(PWR_CPU_CurFreq));
          cpuCurFreq[0].policyId = 0;
          cpuCurFreq[0].curFreq = TEST_FREQ;
          ret = PWR_CPU_SetFreq(cpuCurFreq, num);
          PrintResult("PWR_CPU_SetFreq", ret);
      
          int spec = 1;
          bzero(cpuCurFreq, num * sizeof(PWR_CPU_CurFreq));
          cpuCurFreq[0].policyId = 0;
          ret = PWR_CPU_GetFreq(cpuCurFreq, &num, spec);
          printf("    current policy[%d]: %lf\n", cpuCurFreq[0].policyId, cpuCurFreq[0].curFreq);
      }
      /*************************** CPU END *************************/
      
      int main(int argc, const char *args[])
      {
          /********** Common **********/
          TEST_PWR_SetServerInfo();
          TEST_PWR_SetLogCallback();
          TEST_PWR_Register();
          TEST_PWR_RequestControlAuth();
      
          /************ CPU ***********/
          TEST_PWR_CPU_GetInfo();
          TEST_PWR_CPU_GetFreq();
          TEST_PWR_CPU_SetFreq();
      
          PWR_ReleaseControlAuth();
          PWR_UnRegister();
          return 0;
      }
      

      使用gcc编译:

      gcc powerapi_test.c -o powerapi_test -lpwrapi
      

      运行查看结果:

      ./powerapi_test
      

      文档捉虫

      “有虫”文档片段

      问题描述

      提交类型 issue

      有点复杂...

      找人问问吧。

      PR

      小问题,全程线上修改...

      一键搞定!

      问题类型
      规范和低错类

      ● 错别字或拼写错误;标点符号使用错误;

      ● 链接错误、空单元格、格式错误;

      ● 英文中包含中文字符;

      ● 界面和描述不一致,但不影响操作;

      ● 表述不通顺,但不影响理解;

      ● 版本号不匹配:如软件包名称、界面版本号;

      易用性

      ● 关键步骤错误或缺失,无法指导用户完成任务;

      ● 缺少必要的前提条件、注意事项等;

      ● 图形、表格、文字等晦涩难懂;

      ● 逻辑不清晰,该分类、分项、分步骤的没有给出;

      正确性

      ● 技术原理、功能、规格等描述和软件不一致,存在错误;

      ● 原理图、架构图等存在错误;

      ● 命令、命令参数等错误;

      ● 代码片段错误;

      ● 命令无法完成对应功能;

      ● 界面错误,无法指导操作;

      风险提示

      ● 对重要数据或系统存在风险的操作,缺少安全提示;

      内容合规

      ● 违反法律法规,涉及政治、领土主权等敏感词;

      ● 内容侵权;

      您对文档的总体满意度

      非常不满意
      非常满意
      提交
      根据您的反馈,会自动生成issue模板。您只需点击按钮,创建issue即可。
      文档捉虫
      编组 3备份