参考文档:
https://blog.csdn.net/lanyzh0909/article/details/50404664 //线程绑定CPU核-sched_setaffinity
https://blog.csdn.net/lyx2007825/article/details/53885205 //android将线程绑定在指定CPU
https://www.jianshu.com/p/568cbc3ef786 //将C文件通过NDK编译生成SO库
https://my.oschina.net/zhiweiofli/blog/138454 //Android的ps命令介绍和技巧
功能:获取CPU当前核数,将线程/进程绑定到指定CPU核上
原理:利用jni将线程绑定到指定的CPU核上
要说的话:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_example_myapplication_Affinity */
#ifndef _Included_com_example_myapplication_Affinity
#define _Included_com_example_myapplication_Affinity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_myapplication_Affinity
* Method: bindToCpu
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_example_myapplication_Affinity_bindToCpu
(JNIEnv *, jclass, jint);
/*
* Class: com_example_myapplication_Affinity
* Method: getCores
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_example_myapplication_Affinity_getCores
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define __USE_GNU
#include
#include
#define THREAD_MAX_NUM 100 //1个CPU内的最多进程数
int num=0; //cpu中核数
#define TAG "Affinity"
#define DEBUG 1
#ifndef CPU_ZERO
#define CPU_SETSIZE 1024
#define __NCPUBITS (8 * sizeof (unsigned long))
typedef struct
{
unsigned long __bits[CPU_SETSIZE / __NCPUBITS];
} cpu_set_t;
#define CPU_SET(cpu, cpusetp) \
((cpusetp)->__bits[(cpu)/__NCPUBITS] |= (1UL << ((cpu) % __NCPUBITS)))
#define CPU_ZERO(cpusetp) \
memset((cpusetp), 0, sizeof(cpu_set_t))
#else
#define CPU_SET(cpu,cpustep) ((void)0)
#define CPU_ZERO(cpu,cpustep) ((void)0)
#endif
#ifdef DEBUG
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)
#else
#define LOGD(...) ((void)0)
#define LOGE(...) ((void)0)
#endif
static int getCores() {
return sysconf(_SC_NPROCESSORS_CONF);
}
JNIEXPORT int JNICALL Java_com_example_myapplication_Affinity_getCores (JNIEnv *env, jclass type) {
return getCores();
}
JNIEXPORT void JNICALL Java_com_example_myapplication_Affinity_bindToCpu (JNIEnv *env, jclass type, jint cpu) {
int cores = getCores();
LOGD("get cpu number = %d\n",cores);
if (cpu >= cores) {
LOGE("your set cpu is beyond the cores,exit...");
return;
}
cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(cpu,&mask);
if (sched_setaffinity(0, sizeof(mask), &mask) == -1)//设置线程CPU亲和力
{
LOGD("warning: could not set CPU affinity, continuing...\n");
}else
{
LOGD("set affinity to %d success",cpu);
}
}
package com.example.myapplication;
public class Affinity {
static {
System.loadLibrary("Affinity");
}
public static native void bindToCpu(int cpu);
public static native int getCores();
}
先进入工程main目录下 输入自己的Native.class文件的绝对路径
javah -d jni -classpath class路径 包名+类名例:
javah -d jni -classpath D:\Demo\JNITest\app\build\intermediates\classes\debug com.example.myapplication.Affinity注意:debug后面要留空格
APP_PLATFORM := android-16 //编译环境
APP_ABI := armeabi-v7a //编译后生成so的文件夹
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libAffinity //生成后的so文件名
LOCAL_SRC_FILES := Affinity.c //要生成的c文件
LOCAL_LDLIBS := -llog -lz
include $(BUILD_SHARED_LIBRARY)
......
android{
...
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}
adb shell ps -t -p -c
在我的代码中,在应用启动的进程下开了两个子线程,在新开的myservice进程中,开了四个子线程。最后一列的NAME默认情况下,是包名。
PID 9105是应用程序所在进程,PID 9132是应用程序下的主线程,也就是绘制UI的线程,PID 9134和9135是应用程序下的两个子线程。
PID 9136是myservice所在进程,下面的Thread-62到65是myservice下的子线程。
从上面的图片可以看到,如果在进程中绑定了cpu核,子线程也会绑定到那个核上;如果在子线程中绑定了与主线程不同的核,也是可以的。
我是在模拟器上运行的,这个问题的解决办法是在Application.mk中加生成的文件:
APP_PLATFORM := android-16
APP_ABI := armeabi-v7a,x86
build.gradle中同步添加:
android {
defaultConfig {
...
ndk {
moduleName "libAffinity"
ldLibs "log"
abiFilters "armeabi-v7a","x86"
}
}
...
}
源码地址:https://download.csdn.net/download/a569503963/10917571