精华内容
下载资源
问答
  • 目前嵌入式开发为了追求稳定性、可靠性,多核处理器多使用静态任务调度架构,静态分配CPU、进程(APP)、线程(Task)、任务(runnable)的多层调用关系树。系统在低负载场景十分稳定,但高负载场景无法实时优化多核负载,...

    背景介绍

    目前嵌入式开发为了追求稳定性、可靠性,多核处理器多使用静态任务调度架构,静态分配CPU、进程(APP)、线程(Task)、任务(runnable)的多层调用关系树。系统在低负载场景十分稳定,但高负载场景无法实时优化多核负载,造成任务延迟。

    本文介绍了一种多核实时负载均衡的调度架构,均衡多核CPU资源,提高任务处理效率和系统实时响应能力。

    架构

     

     

    • 任务激励可配:中断、定时器(周期和功能分类);
    • CPU通过激励源上下文和任务Manager,在任务队列中获取和占据合适任务,完成后释放;
    • CPUs清空激励源相关任务集,并等待下一个激励源;
    • CPU在任务执行过程中发布新的任务和产生中断;
    • 任务锁保护任务不被重入执行;
    • 任务队列初始化时需要配置启动任务集;

     

    优点

     

    • CPU只需要配置中断和定时器即可,任务调度解耦处理器架构;
    • 激励的处理由CPUs共同完成,完全的负载均衡,单一CPU负载降低,延时减少;
    • 单一CPU失效,其余CPUs不受影响,可继续完成任务,乃至分析失效CPU原因,系统不会失效。
    展开全文
  • eCos系统CPU负载测量

    千次阅读 2013-12-02 19:40:36
    原文:http://ecos.sourceware.org/docs-latest/ref/services-cpuload.html 译文:...mingdu.zheng <at> gmail <dot>... cpuload组件包提供了一种估算CPU负载的方式。它可以...

    原文:http://ecos.sourceware.org/docs-latest/ref/services-cpuload.html
    译文:http://blog.csdn.net/zoomdy/article/details/17078995
    mingdu.zheng <at> gmail <dot> com

    cpuload组件包提供了一种估算CPU负载的方式。它可以估算最近0.1秒、1秒和10秒内的CPU负载百分比。

    负载测量API

    首先,必须在被测目标机上对测量算法进行校准,一旦校准完成后就可以开始测量。测量是一个连续过程,因此总是提供最近的测量数据,测量过程可以根据需要随时停止。一旦开始测量过程,就可以获取测量结果。

    需要注意的是:如果目标机或CPU执行任何节能措施,例如降低时钟频率或者挂起CPU等,这些节能措施将干扰CPU负载测量,在这种情况下,测量结果是未定义的。Synthetic Target就是这样的情况之一。阅读本文后续实现细节章节可以了解更多。

    『译注』Cortex-M架构的默认实现会在执行空闲任务时挂起CPU,因此默认情况下,测量结果并非是实际的CPU负载,需要重定义HAL_IDLE_THREAD_ACTION宏取消空闲时挂起,HAL_IDLE_THREAD_ACTION宏的默认实现位于hal/cortexm/arch/<version>/include/hal_arch.h:336。

    负载测量不支持SMP系统,仅支持单CPU系统。

    负载测量API可以在cyg/cpuload/cpuload.h中找到。

    『译注』源代码位于services/cpuload/。

    cyg_cpuload_calibrate

    这个函数用来校准CPU负载测量算法。它执行一次特别的测量过程确定空闲时的CPU性能。

    void cyg_cpuload_calibrate(cyg_uint32* calibration);

    该函数通过calibration指针返回校准值。

    这个函数是非常特别的,为了获得正确的校准结果需要满足若干条件。该函数使用了2个最高线程优先级,当该函数被使用时,其它线程不能使用这两个优先级。调用该函数时,内核调度器必须已经启动而且调度器未加锁。该函数将花费0.1秒的时间完成校准操作,在这0.1秒校准期间不能有任何其它线程执行。

    『译注』这个函数使用了线程优先级1和2,为了获得正确的测量结果,其它线程不能使用优先级1和2。eCos的最高线程优先级是0,如果有优先级为0的线程,必须保证在校准过程该线程处于挂起状态,否则校准过程可能被优先级为0的线程抢占而导致错误的校准结果。

    『译注』该函数将会创建一个线程,线程堆栈大小为CYGNUM_HAL_STACK_SIZE_MINIMUM,在Cortex-M架构下约1.5KB,该线程仅在校准过程执行一次,随后被删除永远都不会再执行,如果目标机内存非常有限,应当知晓CPU负载测量校准时使用了1.5KB的堆栈空间。

    cyg_cpuload_create

    这个函数启动CPU负载测量。

    void cyg_cpuload_create(cyg_cpuload_t* cpuload,
                            cyg_uint32 calibrate,
                            cyg_handle_t* handle);

    调用该函数启动测量过程,handle返回操作句柄,通过该句柄可以读取测量结果以及停止测量过程。

    cyg_cpuload_delete

    这个函数停止CPU负载测量。

    void cyg_cpuload_delete(cyg_handle_t handle);

    handle必须是cyg_cpuload_create函数返回的操作句柄。

    cyg_cpuload_get

    这个函数返回最近的测量结果。

    void cyg_cpuload_get(cyg_handle_t handle,
                         cyg_uint32* average_point1s,
                         cyg_uint32* average_1s,
                         cyg_uint32* average_10s);

    handle必须是cyg_cpuload_create函数返回的操作句柄。最近0.1秒、1秒和10秒的负载测量结果通过average_point1s、average_1s和average_10s返回。

    实现细节

    这一节给出一些测量过程的实现细节,这些细节可以帮助我们理解测量结果的意义。

    当没有其它线程可以执行时,eCos将执行空闲线程,空闲线程总是可执行的而且使用最低线程优先级。空闲线程只做一点点事情,它有一个永远都不会退出的循环,每次循环将idle_thread_loops变量加1,然后调用HAL_IDLE_THREAD_ACTION宏。CPU负载测量算法就是使用了idle_thread_loops变量,测量算法周期性地检查idle_thread_loops变量,并记录前后两次检查的差值,系统越空这个差值就越大,通过这个简单的手段就可以确定系统的负载。

    cyg_cpuload_calibrate函数执行空闲任务0.1秒,从而确定系统空闲0.1秒的时间内idle_thread_loops会被累加多少次。cyg_cpuload_create函数启动一个闹钟,这个闹钟每隔0.1秒调用回调函数,回调函数计算idle_thread_loops从上次检查到本次检查的差值,然后根据这个差值以及校准值计算出CPU负载。回调函数用新的计算结果更新cyg_cpuload结构,0.1秒负载只是简单地复制最近的测量结果,然后通过一个简单的滤波计算1秒和10秒负载。由于舍入误差的存在,即使系统满负载,1秒和10秒测量值也永远都不会达到100%,通常看到的是99%。

    如前所述,电源管理代码将干扰上述测量结果。CPU负载测量的基本假设是:空闲线程可以无障碍地运行,而且运行条件与校准时的运行条件保持一致。如果降低CPU时钟频率,那么空闲线程的计数器累加速率将变慢,因此CPU负载测量结果值将偏高,如果CPU被完全挂起,那么CPU负载测量结果将是100%。

    展开全文
  • 在《一文读懂 | 进程怎么绑定 CPU》这篇文章中介绍过,在 Linux 内核中会为每个 CPU 创建一个可运行进程队列,由于每个 CPU 都拥有一个可运行进程队列,那么就有可能会出现每个...

    在《一文读懂 | 进程怎么绑定 CPU》这篇文章中介绍过,在 Linux 内核中会为每个 CPU 创建一个可运行进程队列,由于每个 CPU 都拥有一个可运行进程队列,那么就有可能会出现每个可运行进程队列之间的进程数不一样的问题,这就是所谓的 负载不均衡 问题,如下图所示:

    (图1)

    最极端的情况是,一个 CPU 的可运行进程队列拥有非常多的进程,而其他 CPU 的可运行进程队列为空,这就是著名的 一核有难,多核围观,如下图:

    (图2)

    为了避免这个问题的出现,Linux 内核实现了 CPU 可运行进程队列之间的负载均衡。接下来,我们将会介绍 CPU 间的负载均衡的实现原理。

    本文使用的内核版本为:Linux-2.6.23

    CPU 间负载均衡原理

    CPU 间负载不均衡的根本原因就是,CPU 的可运行进程队列中的进程数量不均衡导致的。所以,要解决 CPU 间负载不均衡的方法就是:将最繁忙的 CPU 可运行进程队列的一些进程迁移到其他比较空闲的 CPU 中,从而达到 CPU 间负载均衡的目的。

    当然,在 2.6.0 版本的内核的确是这样实现的,我们可以看看其实现代码:

    static void 
    load_balance(runqueue_t *this_rq, int idle, cpumask_t cpumask)
    {
        int imbalance, idx, this_cpu = smp_processor_id();
        runqueue_t *busiest;
        prio_array_t *array;
        struct list_head *head, *curr;
        task_t *tmp;
    
        // 1. 找到最繁忙的 CPU 运行队列
        busiest = find_busiest_queue(this_rq, this_cpu, idle, &imbalance, cpumask);
        if (!busiest)
            goto out;
        ...
    
        head = array->queue + idx;
        curr = head->prev;
    
    skip_queue:
        // 2. 从最繁忙运行队列中取得一个进程
        tmp = list_entry(curr, task_t, run_list);
        ...
    
        // 3. 把进程从最繁忙的可运行队列中迁移到当前可运行队列中
        pull_task(busiest, array, tmp, this_rq, this_cpu);
        ...
    }
    

    load_balance 函数主要用于解决 CPU 间负载均衡问题,其主要完成以下 3 个步骤:

    • 从所有 CPU 的可运行队列中找到最繁忙的可运行队列。

    • 从最繁忙可运行队列中取得一个进程。

    • 把进程从最繁忙的可运行队列中迁移到当前可运行队列中。

    这是 2.6.0 版本的解决方案,但这个方案并不是最优的,因为现代 CPU 架构是非常复杂的,比如一个物理 CPU 有多个核心(多核),而每个核心又可以通过超线程(Hyper-Threading)来实现多个逻辑 CPU,如下图所示:

    (图3)

    如上图所示,一个物理 CPU 中拥有 4 个核心,而每个核心又拥有 2 个超线程。在 Linux 内核中,会为每个超线程定义一个可运行进程队列,所以 Linux 内核会为上面的 CPU 定义 8 个可运行进程队列。

    现在问题来了,在上面的 CPU 架构中,不同的可运行队列之间的进程迁移代价是不一样的。因为同一个核心的不同超线程共用了所有的缓存,所以同一个核心不同超线程间的进程迁移代价是最小的。

    而同一个物理 CPU 不同核心间也会共用某些缓存,所以不同核心间的进程迁移的代价会比同一核心不同超线程间的进程迁移稍大。由于现在很多主板都支持安装多个物理 CPU,而不同物理 CPU 间基本不会共用缓存,所以不同物理 CPU 间的进程迁移代价最大。如下图所示(图中的 L1、L2 和 L3 分别指一级、二级和三级缓存):

    (图4)

    为了解决进程迁移成本的问题,新版本的 Linux 内核引入了 调度域 和 调度组

    调度域与调度组

    从前面的分析可知,根据 CPU 的物理架构可以划分为:不同的物理 CPU、相同 CPU 不同的核心、相同核心不同的超线程等,如下图所示:

    (图5)

    在 Linux 内核中,把这个层级成为 调度域。从前面的分析可知,越下层的调度域共用的缓存就越多,所以在进程迁移时,优先从底层的调度域开始进行。

    由于内核为每个超线程定义一个可运行队列,所以图 3 中的 CPU 拥有 8 个可运行队列。而根据不同的调度域,可以把这 8 个可运行队列划分为不同的 调度组,如下图所示:

    (图6)

    如上图所示,由于每个超线程都拥有一个可运行队列,所以图 3 的 CPU 拥有 8 个可运行队列,而这些可运行队列可以根据不同的核心来划分为 4 个调度组,而这 4 个调度组可以根据不同的物理 CPU 来划分成 1 个调度组。

    由于越底层的调度域共用的缓存越多,所以对 CPU 可运行队列进行负载均衡时,优先从底层调度域开始。比如把 Thread0 可运行队列的进程迁移到 Thread1 可运行队列的代价要比迁移到 Thread2 可运行队列的小,这是由于 Thread0 与 Thread1 属于同一个核心,同一个核心共用所有的 CPU 缓存。

    在 Linux 内核中,调度域使用 sched_domain 结构表示,而调度组使用 sched_group 结构表示。我们来看看 sched_domain 结构的定义:

    struct sched_domain {
        struct sched_domain *parent;    /* top domain must be null terminated */
        struct sched_domain *child;     /* bottom domain must be null terminated */
        struct sched_group  *groups;    /* the balancing groups of the domain */
        cpumask_t            span;      /* span of all CPUs in this domain */
        ...
    };
    

    下面介绍一下 sched_domain 结构各个字段的作用:

    • parent:由于调度域是分层的,上层调度域是下层的调度域的父亲,所以这个字段指向的是当前调度域的上层调度域。

    • child:如上所述,这个字段用来指向当前调度域的下层调度域。

    • groups:每个调度域都拥有一批调度组,所以这个字段指向的是属于当前调度域的调度组列表。

    • span:这个字段主要用来标记属于当前调度域的 CPU 列表(每个位表示一个 CPU)。

    我们接着分析一下 sched_group 结构,其定义如下:

    struct sched_group {
        struct sched_group *next;
        cpumask_t           cpumask;
        ...
    };
    

    下面介绍一下 sched_group 结构各个字段的作用:

    • next:指向属于同一个调度域的下一个调度组。

    • cpumask:用于标记属于当前调度组的 CPU 列表(每个位表示一个 CPU)。

    它们之间的关系如下图所示:

    (图7)

    CPU 间负载均衡实现

    要实现 CPU 间的负载均衡,只需要将最繁忙的可运行队列中的一部分进程迁移到空闲的可运行队列中即可。但由于 CPU 缓存的原因,对使用不同的 CPU 缓存的可运行队列之间进行进程迁移,将会导致缓存丢失,从而导致性能损耗。所以,Linux 内核会优先对使用相同 CPU 缓存的可运行队列之间进行进程迁移。

    1. CPU 间负载均衡触发时机

    当 CPU 的负载不均衡时,内核就需要对 CPU 进行负载均衡。负载均衡的触发时机比较多,如进程被创建、进程被唤醒、进程休眠和时钟中断等,这里我们介绍一下在时钟中断时怎么进行 CPU 间的负载均衡。

    在 Linux 内核中是通过 rq 结构来描述一个可运行进程队列的,它有个名为 sd 的字段用于指向其所属的 调度域 层级的最底层,如下所示:

    struct rq {
        ...
        struct sched_domain *sd;
        ...
    }
    

    它与调度域和调度组的关系如下图所示:

    (图8)

    在时钟中断下半部处理中,会通过调用 run_rebalance_domains 函数来对 CPU 进行负载均衡处理,而 run_rebalance_domains 接着会通过调用 rebalance_domains 函数来完成负载均衡的工作,其实现如下:

    static inline void 
    rebalance_domains(int cpu, enum cpu_idle_type idle)
    {
        int balance = 1;
        struct rq *rq = cpu_rq(cpu);
        unsigned long interval;
        struct sched_domain *sd;
        unsigned long next_balance = jiffies + 60*HZ;
        int update_next_balance = 0;
    
        // 遍历可运行队列的调度组层级 (从最底层开始)
        for_each_domain(cpu, sd) {
            ...
            // 由于对 CPU 进行负载均衡可能会导致 CPU 缓存丢失
            // 所以对 CPU 进行负载均衡不能太频繁, 必须隔一段时间才能进行
            // 这里就是判断上次进行负载均衡与这次的间隔是否已经达到合适的时间
            // 如果时间间隔已经达到一段时间, 那么就调用 load_balance 函数进行负载均衡
            if (time_after_eq(jiffies, sd->last_balance + interval)) {
                if (load_balance(cpu, rq, sd, idle, &balance)) {
                    idle = CPU_NOT_IDLE;
                }
                sd->last_balance = jiffies;
            }
            ...
        }
        ...
    }
    

    由于每个 CPU(超线程)都有一个可运行队列,而 rebalance_domains 函数的工作就是获取当前 CPU (超线程)的可运行队列,然后从最底层开始遍历其调度域层级(由于越底层的调度域,进行进程迁移的代价越小)。

    由于对 CPU 进行负载均衡可能会导致 CPU 缓存丢失,所以对 CPU 进行负载均衡不能太频繁(需要隔一段时间才能进行)。那么在对 CPU 进行负载均衡前,就需要判断上次进行负载均衡与这次的时间间隔是否合理。如果时间间隔合理, 那么就调用 load_balance 函数对调度域进行负载均衡。

    load_balance 函数实现如下:

    static int
    load_balance(int this_cpu, struct rq *this_rq, struct sched_domain *sd,
                 enum cpu_idle_type idle, int *balance)
    {
        ...
    
    redo:
        // 1. 从调度域中找到一个最繁忙的调度组
        group = find_busiest_group(sd, this_cpu, &imbalance, idle, &sd_idle,
                                   &cpus, balance);
        ...
    
        // 2. 从最繁忙的调度组中找到一个最繁忙的运行队列
        busiest = find_busiest_queue(group, idle, imbalance, &cpus);
        ...
    
        if (busiest->nr_running > 1) {
            ...
            // 3. 从最繁忙的运行队列中迁移一些任务到当前任务队列
            ld_moved = move_tasks(this_rq, this_cpu, busiest, imbalance, sd, idle,
                                  &all_pinned);
            ...
        }
        ...
        return 0;
    }
    

    load_balance 函数主要完成 3 个工作:

    • 从 调度域 中找到一个最繁忙的 调度组

    • 从最繁忙的 调度组 中找到一个最繁忙的 可运行队列

    • 从最繁忙的 可运行队列 中迁移一些任务到当前 可运行队列

    这样就完成了 CPU 间的负载均衡处理。


    推荐阅读:

    专辑|Linux文章汇总

    专辑|程序人生

    专辑|C语言

    我的知识小密圈

    关注公众号,后台回复「1024」获取学习资料网盘链接。

    欢迎点赞,关注,转发,在看,您的每一次鼓励,我都将铭记于心~

    嵌入式Linux

    微信扫描二维码,关注我的公众号

    展开全文
  • 程序运行过程中某一阶段,其CPU占用会高达90%。 2. 分析方法 2.1 使用以下命令得到当前占用CPU情况 awk '{print $1,$2,$14,$15,$14+$15 | "sort -r -n -k5";}' /proc/191/task/*/stat 2.2 参考...

    1. 现象

    程序运行过程中某一阶段,其CPU占用会高达90%。

    2. 分析方法

    2.1 使用以下命令得到当前占用CPU情况

    awk '{print $1,$2,$14,$15,$14+$15 | "sort -r -n -k5";}' /proc/191/task/*/stat

    2.2 参考 https://blog.csdn.net/litao31415/article/details/80905891中代码,可以看出当前每个线程占用CPU的比例

    代码中做了一点修改,显示线程名以及新加线程:

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <getopt.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/termios.h>
    #include <sys/time.h>
    #include <unistd.h>
    #include <linux/unistd.h>
    #include <sys/types.h>
    #include <dirent.h>
    #include <pthread.h>
     
     
    #define VALID_PROCSTATE 0xa84b62fc
     
    struct procState
    {
        char procname[32];
        char thrName[32];
        FILE * fp;
        int pid;
        unsigned int utimeold;
        unsigned int utimenew;
        unsigned int stimeold;
        unsigned int stimenew;
        unsigned int allold;
        unsigned int allnew;
        int valid;
    };
     
    #define MAX_THREADS_NUM 100
    struct procState lanProc[MAX_THREADS_NUM];
    int procTotal=0;
    char targetProcName[64]="";
    int targetProcPid=0;
     
    char taskName[64]="";
    FILE            *taskfp;
    FILE            *statfp;
     
    char *version = "1.1.0";
    char            *procdevice = "/proc/stat";
     
    struct dirent *taskdirent;
    DIR * taskdir;
     
    struct stats
    {
        unsigned int    user;
        unsigned int    nice;
        unsigned int    system;
        unsigned int    idle;
        unsigned int    total;
    };
     
    void readprocessstat( void );
     
    int getdata(struct stats *st)
    {
        unsigned char   buf[80];
        int i;
     
        for(i=0;i<procTotal;i++)
        {
            if ((lanProc[i].fp = fopen(lanProc[i].procname,"r")) == NULL) 
    		{
                  fprintf(stderr, "ERROR: failed, errno=%d\n", errno);
                  exit(-1);
            }
     
            fscanf(lanProc[i].fp, "%d %s %s %s %s %s %s %s %s %s %s %s %s %lu %lu", &lanProc[i].pid,
                   lanProc[i].thrName,&buf[0],&buf[0],&buf[0],&buf[0],&buf[0],&buf[0],&buf[0],&buf[0],&buf[0],&buf[0],&buf[0],
                   &lanProc[i].utimenew,&lanProc[i].stimenew);
    	 	fclose(lanProc[i].fp);
        }
     
        if ((statfp = fopen(procdevice, "r")) == NULL) 
    	{
            fprintf(stderr, "ERROR: failed to open %s, errno=%d\n",
                    procdevice, errno);
            exit(0);
        }
     
        fscanf(statfp, "%s %d %d %d %d", &buf[0], &st->user, &st->nice,&st->system, &st->idle);
    	fclose(statfp);
    			
        st->total = st->user + st->nice + st->system + st->idle;
        for(i=0;i<procTotal;i++)
        {
            lanProc[i].allnew = lanProc[i].utimenew + lanProc[i].stimenew;
        }
     
        return(0);
    }
     
    int getSubThreadsInfo(int pid)
    {
        int i;
        procTotal = 0;
    	sprintf(targetProcName, "%d", pid);
    
    	sprintf(taskName, "/proc/%d/task", pid);
    
    	if((taskdir = opendir(taskName))==NULL)
    	{
    		fprintf(stderr, "ERROR: failed to open %s, errno=%d\n", taskName,errno);
    		exit(-1);
    	}
    
    	targetProcPid=atol(targetProcName);
    
    	for(i=0;i<MAX_THREADS_NUM;i++) 
    	{
    		if ((taskdirent=readdir(taskdir)) == NULL) 
    		{
    			break;
    		}
    
    		lanProc[procTotal].pid=atoi(taskdirent->d_name);// /proc/%s/task 下的文件名即为线程tid号
    		if( lanProc[procTotal].pid < targetProcPid ) //一般不会小于父进程id
    		{ 
    			continue;
    		}
    
    		sprintf(lanProc[procTotal].procname, "/proc/%d/task/%s/stat", pid,taskdirent->d_name);
    		lanProc[procTotal].valid = VALID_PROCSTATE;
    		procTotal++;
    	}
    	return 0; 
    }
    
    void usage(FILE *fp, int rc)
    {
        fprintf(fp, "Usage: ./thread_top [-h?v] [-p <pid>] [-c <count>] [-s seconds]\n\n");
        fprintf(fp, "        -h?            this help\n");
        fprintf(fp, "        -v             print version info\n");
    	fprintf(fp, "        -p <pid>       pid of target proccess\n");
    	fprintf(fp, "        -c count       repeat count times\n");
        fprintf(fp, "        -s seconds     seconds between output\n");
        exit(rc);
    }
     
    int main(int argc, char *argv[])
    {
    	struct stats    st, stold;
    	unsigned int    curtotal;
    	int             c = 0;
    	int 			cnt = 1;
    	int             loop = 1;
    	int				delay = 1;
    	int pid = -1;
    	int             busy = 0;
    	int 			max_busy=0;
    	int 			i = 0;
     
    	if(argc < 2)
    		usage(stdout, 0);
    	
    	while ((c = getopt(argc, argv, "h?vc:s:p:")) > 0) 
    	{
    		switch (c) {
    			case 'v':
    				printf("%s: version %s\n", argv[0], version);
    				exit(0);
    			case 'c':
    				loop = 0;
    				cnt = atoi(optarg) + 1;
    				break;
    			case 's':
    				delay = atoi(optarg);
    				break;
    			case 'h':
    			case '?':
    				usage(stdout, 0);
    				return 0;
    			case 'p':
     
    //struct dirent {
    //   ino_t          d_ino;       /* inode number */
    //   off_t          d_off;       /* offset to the next dirent */
    //   unsigned short d_reclen;    /* length of this record */
    //   unsigned char  d_type;      /* type of file */
    //   char           d_name[256]; /* filename */
    //};
     
                    pid = atoi(optarg);
                    if (pid < 0) {
                        printf("invalid pid\n");
                        return 0;
                    }
    				break;
    			default:
    				fprintf(stderr, "ERROR: unkown option '%c'\n", c);
    				usage(stderr, 1);
    				break;
    		}
    	}
     
        getSubThreadsInfo(pid);
    	getdata(&st);
     
    	for (c = 0; (loop || (c < cnt)); c++) 
    	{
    		sleep(delay);
     
    		stold = st;
    		
    		getSubThreadsInfo(pid);
    		getdata(&st);
     
    		curtotal = st.total - stold.total;
    		busy = ((st.system + st.user + st.nice)-(stold.system + stold.user + stold.nice)) * 100 / curtotal;
    		if (max_busy < busy)
    			max_busy = busy;
     
    		if(c) //第一次不打印
    		printf("busy %3d%%:max=%3d%%(system %3d%%, user %3d%%, nice %3d%%, idle %3d%%)\n",
    												busy,max_busy,
    												(st.system - stold.system) * 100 / curtotal,
    												(st.user - stold.user) * 100 / curtotal,
    												(st.nice - stold.nice) * 100 / curtotal,
    												(st.idle - stold.idle) * 100 / curtotal);
     
    		for(i=0;i<procTotal;i++) 
    		{
    			if( lanProc[i].valid != VALID_PROCSTATE )
    				continue;
     
    			if(c) //第一次不打印	
    			printf("pthread:%3d-%20s  alltime:%6lu %3d%% usrtime:%6lu %3d%% systime:%6lu %3d%% \n",
    										lanProc[i].pid, lanProc[i].thrName,
    										lanProc[i].allnew - lanProc[i].allold,
    										(lanProc[i].allnew - lanProc[i].allold) * 100/curtotal,
    										lanProc[i].utimenew - lanProc[i].utimeold,
    										(lanProc[i].utimenew - lanProc[i].utimeold) * 100/curtotal,
    										lanProc[i].stimenew - lanProc[i].stimeold,
    										(lanProc[i].stimenew - lanProc[i].stimeold) * 100/curtotal);
     
    			lanProc[i].allold = lanProc[i].allnew;
    			lanProc[i].utimeold = lanProc[i].utimenew;
    			lanProc[i].stimeold = lanProc[i].stimenew;
    		}
    		
    		printf("\n");
    	}
     
    	exit(0);
    }

     

    展开全文
  • 嵌入式系统中如何降低CPU占用率

    千次阅读 2018-08-01 07:32:18
    在软件开发和性能测试中,CPU占用率是一个很重要的指标,到底有哪些因素会导致CPU占用率上升呢?又有哪些手段可以降低CPU的占用率呢?简单地总结了一下关于CPU占用率的那些事。 1. 如何测试CPU占用率? 首先,...
  • GPU厂商nVidia的首席科学家称,谈到节能计算,在执行常见的并行任务方面CPU负载过多的传统功能而逊色于GPU(图形处理单元)。在新奥尔良举行的2010年超级计算机大会上nVidia的首席科学家和高级副总裁Bill Dally...
  • 第一节 CPU利用率和CPU负载 在Linux/Unix下,CPU利用率(CPU utilization)分为用户态,系统态和空闲态,分别表示CPU处于用户态执行的时间,系统内核执行的时间,和空闲系统进程执行的时间。平时所说的CPU利用率是...
  • 嵌入式linux CPU过高排查方法汇集

    千次阅读 2018-07-04 00:14:26
    1,主要是使用top命令,可看出哪个进程CPU占有率过高,但嵌入式linux的top是由busybox编译出来的,属于轻量级。PC上有的功能,嵌入式平台上可能没有,譬如“top -H”等。 2,另外ps命令可以看到各个进程的pid,包括...
  • Linux查看每个CPU负载及进程IO

    千次阅读 2015-03-02 10:20:38
    Linux查看每个CPU负载及进程IO
  • LINUX 智能电视 电视盒子 嵌入式硬件CPU压测压力测试 将硬件平台软件版本升级为最新正式发布版本,观察并记录升级过程; 2.执行(cat /proc/cpuinfo)查询CPU信息,3399为6核心CPU; 3.将stress工具上传至OS任意...
  • 解决PaintEvent时候CPU负载过高的问题

    千次阅读 2016-08-18 17:00:38
    比如有计时器,那么painrEvent里如果再设置一些函数,比如画线函数的时候,那么就会使得整个PaintEvent函数需要不断刷新,导致CPU的占用率一直过高,在PC上还看不大出来问题,但是在嵌入式设备中,就会导致整个系统...
  • 现在的CPU处理器一般都是超流水线工作,动不动就是10级以上流水线,超高主频,这两者之间有什么关系呢?今天就跟大家科普下CPU流水线的工作原理,以及他们之间的关系。 说到流水线,很多人会想到富士康;说到富士康...
  • 查看代码运行过程中,嵌入式平台的CPU占用情况,以及memeory情况。 开两个命令窗口,一个运行代码,另外一个输入命令查看。 1.CPU占用情况 top //持续刷新CPU的占用情况。 保存到文本:top | tee top.txt   2....
  • 步骤 1....在telnet终端上运行”top –d 1”,查看哪个pid的线程CPU占有率最高,记下这个值。 步骤 4.按’q’退出top,或者另外再起一个telnet终端登录单板。 步骤 5.在telnet终端上运行gdb,不需要带
  • 有一次测试过程需要查看开发板在增加负载的过程是否正常,由于在增加负载的过程中打印温度,打印温度可以通过脚本直接体现出来,负载也可以使用top命令打印出来,但是top命令用于保存脚本就比较费劲了,如何将负载...
  • https://blog.csdn.net/wofeile880_jian/article/details/77584842 https://blog.csdn.net/shamofeiyu/article/details/21336557
  • 嵌入式测试

    千次阅读 2007-01-27 19:16:00
    嵌入式测试来源:中科永联高级技术培训中心 嵌入式软件测试/嵌入式测试或叫交叉测试(cross-test)的日的与非嵌入式软件是相同的。但是,在嵌入式系统设计中,软件正越来越多地取代硬件,以降低系统的成本,获得更...
  • 一款32位嵌入式CPU的定点加法器设计

    千次阅读 2006-11-02 16:47:00
    来源:21IC中国电子网 / 作者:夏有为 林正浩 杨晓峰 发表时间:2006-04-02 从CPU的指令执行频率上看,算术逻辑单元、程序计数器、协处理器是CPU中使用频率最多的模块,而加法器正是这些模块的核心部件,几乎所有...
  • 指标 外在表现:对于GUI程序而言,用户操作时界面是否卡顿,操作是否有延时,对于非GUI程序而言,程序是否反应及时,这些体现了CPU使用情况。 内在指标:指令的运行时长,GUI程序...cpu负载 使用率 cpu 使用率可...
  • 查看CPU信息(型号) # cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c   8 Intel(R) Xeon(R) CPU  E5410 @ 2.33GHz (看到有8个逻辑CPU, 也知道了CPU型号) # cat /proc/cpuinfo | grep physical | ...
  • 走进嵌入式Linux的世界 一、嵌入式系统 嵌入式系统是以应用为中心,以计算机技术为基础,并且软硬件是可裁剪的,适用于对功能、可靠性、成本、体积、功耗等有严格要求的专用计算机系统。嵌入式系统最典型的特点是...
  • 边缘计算与嵌入式系统

    万次阅读 多人点赞 2018-07-06 19:46:00
    嵌入式系统与边缘计算 3.1 嵌入式系统概述 3.2 嵌入式系统的发展历史 3.3 嵌入式系统应用到边缘计算 3.4 嵌入式硬件的要求 3.5 边缘计算环境下嵌入式系统与人工智能 观点与看法 4.1 边缘数据安全 4.2 人工...
  • 嵌入式操作系统

    2021-01-29 15:26:35
    嵌入式操作系统一、嵌入式操作系统概述1.1 嵌入式操作系统的特点1.2 嵌入式操作系统的分类1.2.1 非实时操作系统1.2.1 实时操作系统二、实时操作系统2.1 实时操作系统与通用操作系统的比较2.2 实时操作系统的评价指标...
  • 嵌入式 如何定位死循环或高CPU使用率(linux) ln -s /mnt/nfs/_install/usr/bin/sort /usr/bin/sort awk '{print $1,$2,$14,$15 | "sort -r -n -k3";}' /proc/589/task/*/stat awk '{print $1,$2,$14,$15 | ...
  • 嵌入式视觉技术

    千次阅读 2018-07-06 17:19:09
    随着嵌入式技术的发展,嵌入式视觉技术也越来越比较重视,多年前。人们对嵌入式视觉技术的研究还是很模糊的,而在嵌入式视觉技术高度专业化应用的今天。越来越多的新兴工业为视觉应用找到了用武之地。那么就让我们...
  • 嵌入式系统基础

    千次阅读 2013-02-21 20:46:41
    嵌入式系统基础 1、嵌入式系统的定义 (1)定义:以应用为中心,以计算机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。 (2)嵌入式系统发展的4个阶段:...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,462
精华内容 4,584
关键字:

cpu嵌入式负载