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

2.1 设置调度优先级

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

l         OS在调度进程的时候是遵循一定规则的,优先级高的进程分配CPU的时间多,而优先级低的进程相对分配的CPU时间少。(这个仅是理论上的,具体如何分配是和OS相关的)

下面我们看看AndroidSetThreadPriority的实现。

int androidSetThreadPriority(pid_t tid, int pri)   {   #if defined(HAVE_PTHREADS)  //目前仅支持POSIX    //phtread_once保证这个线程创建时会首先执行一次(仅此一次,类似Class的constructor)    //checkDoSchedulingGroup函数,该函数判断系统是否设置了”debug.sys.noschedgroups”        pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);       if (gDoSchedulingGroup) {           if (pri >= ANDROID_PRIORITY_BACKGROUND) {               //设置调度策略。这个我们待会会碰到。                rc = set_sched_policy(tid, SP_BACKGROUND);           } else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {               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,根据第一个参数的不同,分别指向进程ID;进程组ID和user id。 第三个参数学名叫nice值,从-20到19。是优先级的表示,越大表明越nicer,优先级越低。

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

2.2 设置调度策略

Linux的进程调度除了简单的设置nice值外,还可以设置调度策略。这个问题我们放到最后讨论。先来看看上层API。

int androidSetThreadSchedulingGroup(pid_t tid, int grp)   {   ……   #if defined(HAVE_PTHREADS)        ……     if (set_sched_policy(tid, (grp == ANDROID_TGROUP_BG_NONINTERACT) ?                                             SP_BACKGROUND : SP_FOREGROUND)) {   #endif    }   int set_sched_policy(int tid, SchedPolicy policy)   {       pthread_once(&the_once, __initialize);//先运行__initialize函数    #if POLICY_DEBUG       ……   #endif        //看看系统是否支持调度策略        if (__sys_supports_schedgroups) {           if (add_tid_to_cgroup(tid, policy)) {               ……           }       } else {           struct sched_param param; //调度参数,类型为sched_param            param.sched_priority = 0;           sched_setscheduler(tid,//如果系统不支持的话,直接调用OS的调度策略设置API                               (policy == SP_BACKGROUND) ?                               SCHED_BATCH : SCHED_NORMAL,                              ?m);       }   }

initialize这个函数很关键,这里的__sys_supports_schedgroups用来检查android系统,而不是OS。

static void __initialize(void) {   char* filename;   //如果android手机上有/dev/cpuctl/tasks文件,则__sys_supports_schedgroups为1    //目前我的索爱手机并没有该文件。        if (!access("/dev/cpuctl/tasks", F_OK)) {           __sys_supports_schedgroups = 1;           filename = "/dev/cpuctl/tasks";           normal_cgroup_fd = open(filename, O_WRONLY);           ……           filename = "/dev/cpuctl/bg_non_interactive/tasks";           bg_cgroup_fd = open(filename, O_WRONLY);           ……       } else {           __sys_supports_schedgroups = 0;       }   }

 目前还没有找到解释/dev/cpuctl/tasks这个特殊文件的地方。有明白的网友请不吝赐教.

下面我们看看linux提供的设置调度策略的函数,其原型是:

int sched_setscheduler(pid_t pid, int policy,const struct sched_param *param);

第一个参数为进程id。 第二个参数为调度策略,目前android支持SCHED_OTHER,标准round-robin分时共享策略(也就是默认的策略);SCHED_BATCH,针对具有batch风格(批处理)进程的调度策略;SCHED_IDLE,针对优先级非常低的适合在后台运行的进程。另外,linux还支持实时(Real-time)调度策略(SCHED_FIFO,先入先出调度策略,SCHED_RR,round-robin调度策略,也就是循环调度。)。 param参数中最重要的是该结构体中的sched_priority变量。针对上面三种非实时调度策略,该值必须为零。 2.3 小结

从前面可以看出,Android上进程调度还是依赖OS提供的调度机制。当然上层API还是比较简单易懂的,但是Linux OS调度到底是怎么样的呢?不妨探讨一下。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/pxwsj.html