日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android中关于cpu/cpuset/schedtune的应用

發布時間:2025/3/15 Android 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android中关于cpu/cpuset/schedtune的应用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Android中關于cpu/cpuset/schedtune的應用都是基于進程優先級的,根據不同優先級劃分進程類型。AMS(ActivityManagerService)和PMS(PackageManagerService)等通過class Process設置進程優先級、調度策略等;android/osProcess JNI通過調用libcutils.so/libutils.so執行getpriority/setpriority/sched_setscheduler/sched_getschedler系統調用或者直接操作CGroup文件節點以達到設置優先級,限制進程CPU資源的目的。

根據優先級,通過設置CGroup的cpu/cpuset/stune控制進程獲得CPU執行時間、可調度CPU范圍等,以達到對不同優先級進程的控制。

Android關于cpu/cpuset/schedtune的框架結構

進程優先級和調度策略從上到下貫穿其中,但是在不同的層級的名稱有一些變化。下面逐一介紹。

class Process以及android/os/Process JNI

frameworks/base/core/java/android/os/Process.java

其他服務通過class Process來設置進程優先級、調度側率等。

class Process中優先級劃分:

public static final int THREAD_PRIORITY_DEFAULT = 0;??應用的默認優先級

/*
* ***************************************
* ** Keep in sync with utils/threads.h **
* ***************************************
*/

public static final int THREAD_PRIORITY_LOWEST = 19;??線程的最低優先級

public static final int THREAD_PRIORITY_BACKGROUND = 10;??后臺線程的默認優先級

public static final int THREAD_PRIORITY_FOREGROUND = -2;??前臺進程的標準優先級

public static final int THREAD_PRIORITY_DISPLAY = -4;??系統用于顯示功能的優先級

public static final int THREAD_PRIORITY_URGENT_DISPLAY = -8;??系統用于重要顯示功能的優先級

public static final int THREAD_PRIORITY_AUDIO = -16;??音頻線程默認優先級

public static final int THREAD_PRIORITY_URGENT_AUDIO = -19;??重要音頻線程默認優先級

調度策略劃分:

public static final int SCHED_OTHER = 0;?默認調度策略,對應CFS調度類

public static final int SCHED_FIFO = 1;??FIFO調度策略,對應RT調度類

public static final int SCHED_RR = 2;??RR調度策略,對應RT調度類

public static final int SCHED_BATCH = 3;??批調度策略,對應CFS調度類

public static final int SCHED_IDLE = 5;??idle調度策略

class Process相關API,主要用于:

??

public static final native void setThreadPriority(int tid, int priority)
??????? throws IllegalArgumentException, SecurityException;

public static final native void setThreadScheduler(int tid, int policy, int priority)
??????? throws IllegalArgumentException;

public static final native void setThreadPriority(int tid, int priority)
??????? throws IllegalArgumentException, SecurityException;

public static final native int getThreadPriority(int tid)
??????? throws IllegalArgumentException;

public static final native int getThreadScheduler(int tid)
??????? throws IllegalArgumentException;

public static final native void setThreadGroup(int tid, int group)
??????? throws IllegalArgumentException, SecurityException;

public static final native void setProcessGroup(int pid, int group)
??????? throws IllegalArgumentException, SecurityException;

frameworks/base/core/jni/android_util_Process.cpp

對應JNINativeMethod如下:

static const JNINativeMethod methods[] = {

??? {"setThreadPriority",?? "(II)V", (void*)android_os_Process_setThreadPriority},
??? {"setThreadScheduler",? "(III)V", (void*)android_os_Process_setThreadScheduler},
??? {"setCanSelfBackground", "(Z)V", (void*)android_os_Process_setCanSelfBackground},
??? {"setThreadPriority",?? "(I)V", (void*)android_os_Process_setCallingThreadPriority},
??? {"getThreadPriority",?? "(I)I", (void*)android_os_Process_getThreadPriority},
??? {"getThreadScheduler",?? "(I)I", (void*)android_os_Process_getThreadScheduler},
??? {"setThreadGroup",????? "(II)V", (void*)android_os_Process_setThreadGroup},
??? {"setProcessGroup",???? "(II)V", (void*)android_os_Process_setProcessGroup},
??? {"getProcessGroup",???? "(I)I", (void*)android_os_Process_getProcessGroup},

};

scheduler相關API直接調用sched_setscheduler/sched_getscheduler。

libcutils.so/libutils.so

在介紹這個函數之前先介紹一下此處所使用的優先級定義,可以看出和class Process中是完全的對應關系:

ANDROID_PRIORITY_LOWEST???????? =? 19,

/* use for background tasks */
ANDROID_PRIORITY_BACKGROUND???? =? 10,

/* most threads run at normal priority */
ANDROID_PRIORITY_NORMAL???????? =?? 0,

/* threads currently running a UI that the user is interacting with */
ANDROID_PRIORITY_FOREGROUND???? =? -2,

/* the main UI thread has a slightly more favorable priority */
ANDROID_PRIORITY_DISPLAY??????? =? -4,

/* ui service treads might want to run at a urgent display (uncommon) */
ANDROID_PRIORITY_URGENT_DISPLAY =? HAL_PRIORITY_URGENT_DISPLAY,

/* all normal audio threads */
ANDROID_PRIORITY_AUDIO????????? = -16,

/* service audio threads (uncommon) */
ANDROID_PRIORITY_URGENT_AUDIO?? = -19,

/* should never be used in practice. regular process might not
* be allowed to use this level */
ANDROID_PRIORITY_HIGHEST??????? = -20,

ANDROID_PRIORITY_DEFAULT??????? = ANDROID_PRIORITY_NORMAL,

還需要在研究一下,Sched Policy中使用的優先級映射關系:

/* Keep in sync with THREAD_GROUP_* in frameworks/base/core/java/android/os/Process.java */
typedef enum {
??? SP_DEFAULT??? = -1,
??? SP_BACKGROUND = 0,
??? SP_FOREGROUND = 1,
??? SP_SYSTEM???? = 2,? // can't be used with set_sched_policy()
??? SP_AUDIO_APP? = 3,
??? SP_AUDIO_SYS? = 4,
??? SP_TOP_APP??? = 5,
??? SP_CNT,
??? SP_MAX??????? = SP_CNT - 1,
??? SP_SYSTEM_DEFAULT = SP_FOREGROUND,
} SchedPolicy;

Threads.cpp中定義了androidSetThreadPriority用于設置線程的優先級。

int androidSetThreadPriority(pid_t tid, int pri)
{
??? int rc = 0;
??? int lasterr = 0;

??? if (pri >= ANDROID_PRIORITY_BACKGROUND) {??如果priority大于等于BACKGROUND,則設置為BACKGROUND類型的調度策略。
??????? rc = set_sched_policy(tid, SP_BACKGROUND);
??? } else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {??如果priority小于BACKGROUND,且當線程為BACKGROUND類型,則設置為FOREGROUND類型。
??????? rc = set_sched_policy(tid, SP_FOREGROUND);
??? }

??? if (rc) {
??????? lasterr = errno;
??? }

??? if (setpriority(PRIO_PROCESS, tid, pri) < 0) {??設置優先級
??????? rc = INVALID_OPERATION;
??? } else {
??????? errno = lasterr;
??? }

??? return rc;
}

set_cpuset_policy根據SchedPolicy類型將tid寫入cpuset和schedtune子系統中。

有下面的函數可以得出cpuset、schedtune和不同類型SchedPolicy之間的對應關系

/dev/cpuset/foreground/tasks? SP_FOREGROUND SP_AUDIO_APP SP_AUDIO_SYS
/dev/cpuset/background/tasks? SP_BACKGROUND
/dev/cpuset/system-background/tasks? SP_SYSTEM
/dev/cpuset/top-app/tasks? SP_TOP_APP

/dev/stune/top-app/tasks? SP_TOP_APP
/dev/stune/foreground/tasks? SP_FOREGROUND SP_AUDIO_APP SP_AUDIO_SYS
/dev/stune/background/tasks? SP_BACKGROUND

int set_cpuset_policy(int tid, SchedPolicy policy)
{
??? // in the absence of cpusets, use the old sched policy
#ifndef USE_CPUSETS
??? return set_sched_policy(tid, policy);
#else
??? if (tid == 0) {
??????? tid = gettid();
??? }
??? policy = _policy(policy);
??? pthread_once(&the_once, __initialize);

??? int fd = -1;
??? int boost_fd = -1;
??? switch (policy) {
??? case SP_BACKGROUND:
??????? fd = bg_cpuset_fd;
??????? boost_fd = bg_schedboost_fd;
??????? break;
??? case SP_FOREGROUND:
??? case SP_AUDIO_APP:
??? case SP_AUDIO_SYS:
??????? fd = fg_cpuset_fd;
??????? boost_fd = fg_schedboost_fd;
??????? break;
??? case SP_TOP_APP :
??????? fd = ta_cpuset_fd;
??????? boost_fd = ta_schedboost_fd;
??????? break;
??? case SP_SYSTEM:
??????? fd = system_bg_cpuset_fd;
??????? break;
??? default:
??????? boost_fd = fd = -1;
??????? break;
??? }

??? if (add_tid_to_cgroup(tid, fd) != 0) {
??????? if (errno != ESRCH && errno != ENOENT)
??????????? return -errno;
??? }

#ifdef USE_SCHEDBOOST
??? if (boost_fd > 0 && add_tid_to_cgroup(tid, boost_fd) != 0) {
??????? if (errno != ESRCH && errno != ENOENT)
??????????? return -errno;
??? }
#endif

??? return 0;
#endif
}

set_sched_policy設置cpu/schedtune兩個子系統,子系統節點和SchedPolicy類型對應如下:

/dev/cpuctl/tasks? SP_FOREGROUND SP_AUDIO_APP SP_AUDIO_SYS
/dev/cpuctl/bg_non_interactive/tasks? SP_BACKGROUND

/dev/stune/top-app/tasks? SP_TOP_APP
/dev/stune/foreground/tasks? SP_FOREGROUND SP_AUDIO_APP SP_AUDIO_SYS
/dev/stune/background/tasks? SP_BACKGROUND

int set_sched_policy(int tid, SchedPolicy policy)
{
??? if (tid == 0) {
??????? tid = gettid();
??? }
??? policy = _policy(policy);
??? pthread_once(&the_once, __initialize);

#if POLICY_DEBUG
??? char statfile[64];
??? char statline[1024];
??? char thread_name[255];

??? snprintf(statfile, sizeof(statfile), "/proc/%d/stat", tid);
??? memset(thread_name, 0, sizeof(thread_name));

??? int fd = open(statfile, O_RDONLY | O_CLOEXEC);
??? if (fd >= 0) {
??????? int rc = read(fd, statline, 1023);
??????? close(fd);
??????? statline[rc] = 0;
??????? char *p = statline;
??????? char *q;

??????? for (p = statline; *p != '('; p++);
??????? p++;
??????? for (q = p; *q != ')'; q++);

??????? strncpy(thread_name, p, (q-p));
??? }
??? switch (policy) {
??? case SP_BACKGROUND:
??????? SLOGD("vvv tid %d (%s)", tid, thread_name);
??????? break;
??? case SP_FOREGROUND:
??? case SP_AUDIO_APP:
??? case SP_AUDIO_SYS:
??? case SP_TOP_APP:
??????? SLOGD("^^^ tid %d (%s)", tid, thread_name);
??????? break;
??? case SP_SYSTEM:
??????? SLOGD("/// tid %d (%s)", tid, thread_name);
??????? break;
??? default:
??????? SLOGD("??? tid %d (%s)", tid, thread_name);
??????? break;
??? }
#endif

??? if (__sys_supports_schedgroups) {??是否使能schedtune CGroup
??????? int fd = -1;
??????? int boost_fd = -1;
??????? switch (policy) {
??????? case SP_BACKGROUND:
??????????? fd = bg_cgroup_fd;
??????????? boost_fd = bg_schedboost_fd;
??????????? break;
??????? case SP_FOREGROUND:
??????? case SP_AUDIO_APP:
??????? case SP_AUDIO_SYS:
??????????? fd = fg_cgroup_fd;
??????????? boost_fd = fg_schedboost_fd;
??????????? break;
??????? case SP_TOP_APP:
??????????? fd = fg_cgroup_fd;
??????????? boost_fd = ta_schedboost_fd;
??????????? break;
??????? default:
??????????? fd = -1;
??????????? boost_fd = -1;
??????????? break;
??????? }


??????? if (add_tid_to_cgroup(tid, fd) != 0) {
?????
????? if (errno != ESRCH && errno != ENOENT)
??????????????? return -errno;
??????? }

#ifdef USE_SCHEDBOOST
??????? if (boost_fd > 0 && add_tid_to_cgroup(tid, boost_fd) != 0) {
??????????? if (errno != ESRCH && errno != ENOENT)
??????????????? return -errno;
??????? }
#endif
??? } else {??如果沒有使能schedtune CGroup,則使用系統調用sched_setscheduler設置為SCHED_BATCH或者SCHED_NORMAL
??????? struct sched_param param;

??????? param.sched_priority = 0;
??????? sched_setscheduler(tid,
?????????????????????????? (policy == SP_BACKGROUND) ?
?????????????????????????? SCHED_BATCH : SCHED_NORMAL,
?????????????????????????? &param);
??? }

??? if (__sys_supports_timerslack) {
??????? set_timerslack_ns(tid, policy == SP_BACKGROUND ?
?????????????????????????????? TIMER_SLACK_BG : TIMER_SLACK_FG);
??? }

??? return 0;
}

?

上面的一系列轉換可以用下圖表示:

system\core\libcutils\Sched_policy.c中,對SP_*系列SchedPolicy轉換成使用不同cpuctl、cpuset、stune句柄,將對應的pid、tid寫入tasks中。
SP_BACKGROUND對應SCHED_BACH調度策略,其他對應SCHED_NORMAL。
SCHED_NORMAL:默認的調度策略,在舊版中為SCHED_OTHER。SCHED_BATCH:針對批處理進程。SCHED_IDLE:使用此調度側率的進程優先級最低。
SCHED_NORMAL和SCHED_BATCH區別只是再喚醒時有區別,喚醒較頻繁的進程不適合SCHED_BATCH。
如果使能__sys_supports_schedgroups,就不會調用sched_setscheduler去設置SchedulePolicy。

SCHED_NORMAL和SCHED_BACH區別

SP_BACKGROUND對應SCHED_BACH調度策略,其他對應SCHED_NORMAL。

SCHED_NORMAL:默認的調度策略,在舊版中為SCHED_OTHER。SCHED_BATCH:針對批處理進程。SCHED_IDLE:使用此調度側率的進程優先級最低。

SCHED_NORMAL和SCHED_BATCH區別只是再喚醒時有區別,喚醒較頻繁的進程不適合SCHED_BATCH。

如果使能__sys_supports_schedgroups,就不會調用sched_setscheduler去設置SchedulePolicy。

Android中的一個應用

cpu子系統:

# Create cgroup mount points for process groups

mkdir /dev/cpuctl

mount cgroup none /dev/cpuctl cpu

chown system system /dev/cpuctl

chown system system /dev/cpuctl/tasks

chmod 0666 /dev/cpuctl/tasks

write /dev/cpuctl/cpu.shares 1024

write /dev/cpuctl/cpu.rt_runtime_us 800000

write /dev/cpuctl/cpu.rt_period_us 1000000

mkdir /dev/cpuctl/bg_non_interactive

chown system system /dev/cpuctl/bg_non_interactive/tasks

chmod 0666 /dev/cpuctl/bg_non_interactive/tasks

# 5.0 %

write /dev/cpuctl/bg_non_interactive/cpu.shares 52

write /dev/cpuctl/bg_non_interactive/cpu.rt_runtime_us 700000

write /dev/cpuctl/bg_non_interactive/cpu.rt_period_us 1000000

cpuset子系統:

# sets up initial cpusets for ActivityManager

mkdir /dev/cpuset

mount cpuset none /dev/cpuset

# this ensures that the cpusets are present and usable, but the device's

# init.rc must actually set the correct cpus

mkdir /dev/cpuset/foreground

write /dev/cpuset/foreground/cpus 0

write /dev/cpuset/foreground/mems 0

mkdir /dev/cpuset/foreground/boost

write /dev/cpuset/foreground/boost/cpus 0

write /dev/cpuset/foreground/boost/mems 0

mkdir /dev/cpuset/background

write /dev/cpuset/background/cpus 0

write /dev/cpuset/background/mems 0

# system-background is for system tasks that should only run on

# little cores, not on bigs

# to be used only by init, so don't change system-bg permissions

mkdir /dev/cpuset/system-background

write /dev/cpuset/system-background/cpus 0

write /dev/cpuset/system-background/mems 0

mkdir /dev/cpuset/top-app

write /dev/cpuset/top-app/cpus 0

write /dev/cpuset/top-app/mems 0

# change permissions for all cpusets we'll touch at runtime

chown system system /dev/cpuset

chown system system /dev/cpuset/foreground

chown system system /dev/cpuset/foreground/boost

chown system system /dev/cpuset/background

chown system system /dev/cpuset/system-background

chown system system /dev/cpuset/top-app

chown system system /dev/cpuset/tasks

chown system system /dev/cpuset/foreground/tasks

chown system system /dev/cpuset/foreground/boost/tasks

chown system system /dev/cpuset/background/tasks

chown system system /dev/cpuset/system-background/tasks

chown system system /dev/cpuset/top-app/tasks

# set system-background to 0775 so SurfaceFlinger can touch it

chmod 0775 /dev/cpuset/system-background

chmod 0664 /dev/cpuset/foreground/tasks

chmod 0664 /dev/cpuset/foreground/boost/tasks

chmod 0664 /dev/cpuset/background/tasks

chmod 0664 /dev/cpuset/system-background/tasks

chmod 0664 /dev/cpuset/top-app/tasks

chmod 0664 /dev/cpuset/tasks

schedtune子系統:

# Create energy-aware scheduler tuning nodes

mkdir /dev/stune

mount cgroup none /dev/stune schedtune

mkdir /dev/stune/foreground

chown system system /dev/stune

chown system system /dev/stune/foreground

chown system system /dev/stune/tasks

chown system system /dev/stune/foreground/tasks

chmod 0664 /dev/stune/tasks

chmod 0664 /dev/stune/foreground/tasks


總結

以上是生活随笔為你收集整理的Android中关于cpu/cpuset/schedtune的应用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。