随笔之Android平台上的进程调度探讨

一由来


最近在翻阅MediaProvider的时候,突然想起之前碰到的⼀个


问题,该问题是这样的:


一个Pad上有很多媒体文件,然后每次开机后的⼀段时间


内,Home Screen的反应都特别慢,有时候还会报出ANR


的错误。从ANR文件/data/anr/traces.txt分析,发现系统


打印的cpu占有率中,android.process.media占用非常高


。所以怀疑是MediaProvider做文件扫描占用CPU太多资


源导致。


但是我们实际测试的时候,通过top –m 5查看cpu占有率


的时候,发现只要一操作Home,android.process.media


进程cpu占有率就会下降很多。


当时看到这个现象,直观感觉就是MediaProvider抢占CPU能


力不够。直接把该现象告诉领导,这个事情也就结了。但是⼀


直没在代码中找到依据:总有地方设置进程的优先级吧??


后来,时间充裕了,想起这个问题。果不其然,在MediaScan


nerService中,找到答案:


public void run() 
 
 { 
 
 Process.setThreadPriority(Process.THREAD_PRIORITY_BA 
 
                 Process.THREAD_PRIORITY_LESS_FAVORAB 
 
      …… 
 
 }

上面代码显示得将本进程的优先级设置为BACKGROUND+LE


SS_FAVORABLE。


那么这个优先级是什么呢?


本随笔将关注两个问题:


Android平台提供的调度接口及其它的实现


调度⼀定是依靠Linux OS的,那么本随笔也会顺便介绍⼀


下Linux OS中的进程调度相关的知识。


二 Android平台中的进程调度接口


从最上的Java层看,Anroid提供的Process类封装了进程调度


优先级,调度策略等⼀些API。下图是整体调用流程和相关文


件位置。


 


 


图1 进程调度的API以及调用分发流程


从上图我们可知:


重点讨论Process.java提供的setThreadPriority和setThrea


dGroup函数。


调用分发顺序从Java⼀直贯穿JNI,Native层后,setThread


Priority直接转移到setpriority系统调用,而setThreadGrou


p通过set_sched_policy处理后,再转移给sched_setsche


duler系统调用。


 


2.1 设置调度优先级


进程调度的优先级,这个应该不难理解。简单地说:


l         OS在调度进程的时候是遵循⼀定规则的,优先级高的


进程分配CPU的时间多,而优先级低的进程相对分配的CPU时


间少。(这个仅是理论上的,具体如何分配是和OS相关的)


下面我们看看androidSetThreadPriority的实现。


int androidSetThreadPriority(pid_t tid, int pri) 
 
 { 
 
 #if defined(HAVE_PTHREADS)  //目前仅支持POSIX 
 
 //phtread_once保证这个线程创建时会首先执行⼀次(仅此⼀次, 
 
 //checkDoSchedulingGroup函数,该函数判断系统是否设置了”de 
 
     pthread_once(&gDoSchedulingGroupOnce, checkDoSch 
 
     if (gDoSchedulingGroup) { 
 
         if (pri >= ANDROID_PRIORITY_BACKGROUND) { 
 
             //设置调度策略。这个我们待会会碰到。 
 
             rc = set_sched_policy(tid, SP_BACKGROUND 
 
         } else if (getpriority(PRIO_PROCESS, tid) >= 
 
             rc = set_sched_policy(tid, SP_FOREGROUND 
 
         } 
 
     } 
 
   …… 
 
    //设置调度优先级。 
 
    if (setpriority(PRIO_PROCESS, tid, pri) < 0) { 
 
         rc = INVALID_OPERATION; 
 
 }  
 
 …… 
 
 }


从上面代码发现,Android直接调用了系统API setpriority,其


中有三个参数,其原型是:

int setpriority(int which, int who, int prio);


第⼀个参数which可选值为PRIO_PROGRESS,表示设置

进程;PRIO_PGROUP表示设置进程组;PRIO_USER表


示user。


第二个参数who,根据第⼀个参数的不同,分别指向进程I


D;进程组ID和user id。


第三个参数学名叫nice值,从-20到19。是优先级的表示


,越大表明越nicer,优先级越低。


看来,设置进程调度优先级还是很简单的嘛!

查看更多……