如何獲取 Android CPU 核心數 (Java/C++)

Hi,出發了發表於2021-09-06

1 前言

最近學習Power HAL方面相關知識,透過Power HAL 去配置CPU的Freq需要先確定 CPU 核數。便先了解如何獲取 Android CPU 核數。

2 Java層獲取方式

// 獲取 CPU 核數
Runtime.getRuntime().availableProcessors()

3 C++層獲取方式

#include <unistd.h>

// 獲取CPU核心數(包含禁用的)
long result = sysconf(_SC_NPROCESSORS_CONF);
// 獲取可用的CPU核心數
long result = sysconf(_SC_NPROCESSORS_ONLN);

而在Linux平臺下,我們可以使用sysconf()來獲取處理器核數。

sysconf( )有unistd.h提供,要使用該函式需要#include<unistd.h>

其引數可以是 _SC_NPROCESSORS_CONF,也可以是 _SC_NPROCESSORS_ONLN。兩者差異:

_SC_NPROCESSORS_CONF -- 返回系統可以使用的核數,但是其值會包括系統中禁用的核的數目,因此該值並不代表當前系統中可用的核數。

_SC_NPROCESSORS_ONLN -- 返回值真正的代表了系統 當前可用的核數

4 再多說兩句--底層邏輯

針對上面的sysconf()函式我們看一下它的原始碼:

http://androidxref.com/9.0.0_r3/xref/bionic/libc/bionic/sysconf.cpp#69

long sysconf(int name) {
  switch (name) {
    ......
    case _SC_NPROCESSORS_CONF:  return get_nprocs_conf();
    case _SC_NPROCESSORS_ONLN:  return get_nprocs();
    ......
  }
}

上述流程也非常簡單,分別呼叫到get_nprocs()和get_nprocs_conf(),其原始碼分別如下:

int get_nprocs_conf() {
  // On x86 kernels you can use /proc/cpuinfo for this, but on ARM kernels offline CPUs disappear
  // from there. This method works on both.
  ScopedReaddir reader("/sys/devices/system/cpu");
  if (reader.IsBad()) {
    return 1;
  }

  int result = 0;
  dirent* entry;
  while ((entry = reader.ReadEntry()) != NULL) {
    if (entry->d_type == DT_DIR && __matches_cpuN(entry->d_name)) {
      ++result;
    }
  }
  return result;
}

int get_nprocs() {
  int cpu_count = 1;
  FILE* fp = fopen("/sys/devices/system/cpu/online", "re");
  if (fp != nullptr) {
    char* line = nullptr;
    size_t len = 0;
    if (getline(&line, &len, fp) != -1) {
      cpu_count = GetCpuCountFromString(line);
      free(line);
    }
    fclose(fp);
  }
  return cpu_count;
}

檢視上面的原始碼是不是就一目瞭然了

_SC_NPROCESSORS_CONF ==> get_nprocs_conf() ==> 讀取系統目錄sys/devices/system/cpu下的檔案,並匹配cpu0,cpu1,cpu2,cpu3....形式的目錄來統計數目 -- 返回系統CPU核心數,但是其值會包括系統中禁用的核的數目

_SC_NPROCESSORS_ONLN ==> get_nprocs() ==> 讀取系統檔案/sys/devices/system/cpu/online的值 ==> 獲取當前系統可用的CPU核心數

注意:

上面提到的Java層獲取CPU數目的方法本質上也是經過一路的流程,最終呼叫到sysconf(_SC_NPROCESSORS_CONF)來獲取的。

5 再多說兩句--真機console下瞧一瞧

1. 切換到/sys/devices/system/cpu目錄下,執行ls -l, 可以看到我的機子有4個核心:cpu0,cpu1,cpu2,cpu3

 如何獲取 Android CPU 核心數 (Java/C++)

2. 執行 cat online 可以看到線上工作的有 0-3四個核心

   如何獲取 Android CPU 核心數 (Java/C++)

3. 執行echo 0 > /sys/devices/system/cpu/cpu1/online 關掉cpu1這個核心,再看 cat online 就剩3個在工作了,cat offline 不線上的有1個

如何獲取 Android CPU 核心數 (Java/C++)

 

  個人拙見,不當之處請指教

相關文章