Подтвердить что ты не робот

Как получить общее использование ЦП приложения из/proc/pid/stat?

Мне было интересно, как вычислить общее использование ЦП процесса.

Если я делаю cat /proc/pid/stat, я думаю, что соответствующие поля (взяты из lindevdoc.org):

  1. Время процессора, затраченное на код пользователя, измеренное в jiffies
  2. Время процессора, затраченное на код ядра, измеренное в jiffies
  3. Время процессора, затрачиваемое на код пользователя, включая время от детей
  4. Время CPU, затраченное на код ядра, включая время от детей

Итак, общее время тратит сумму полей от 14 до 17?

4b9b3361

Ответ 1

Подготовка

Чтобы вычислить использование ЦП для конкретного процесса, вам понадобится следующее:

  • /proc/uptime
    • #1 время работы системы (в секундах)
  • /proc/[PID]/stat
    • #14 utime - время процессора, затрачиваемое на код пользователя, измеренное в тактовых импульсах
    • #15 stime - время процессора, затрачиваемое на код ядра, измеренное в тактовых импульсах
    • #16 cutime - Ожидаемое детское время процессора, затрачиваемое на код пользователя (в часах)
    • #17 cstime - Ожидаемое детское время процессора, затраченное на код ядра (в тактах синхронизации)
    • #22 starttime - время начала процесса, измеренное в тактовых импульсах
  • Hertz (количество тактов в секунду) вашей системы.
    • В большинстве случаев getconf CLK_TCK может использоваться для возврата количества тактов.
    • sysconf(_SC_CLK_TCK) Вызов функции C может также использоваться для возврата значения герца.

Расчет

Сначала мы определяем общее время, затрачиваемое на процесс:

total_time = utime + stime

Мы также должны решить, хотим ли мы включить время от дочерних процессов. Если мы это сделаем, добавим эти значения в total_time:

total_time = total_time + cutime + cstime

Затем мы получаем общее время, прошедшее с момента запуска процесса:

seconds = uptime - (starttime / Hertz)

Наконец, мы вычисляем процент использования ЦП:

cpu_usage = 100 * ((total_time / Hertz) / seconds)

См. также

Верх и ps не показывают тот же результат cpu

Как получить общее использование процессора в Linux (С++)

Расчет использования процессора в Linux

Ответ 2

Да, вы можете так сказать. Вы можете преобразовать эти значения в секундах, используя формулу:

      sec = jiffies / HZ ; here - HZ = number of ticks per second

Значение HZ настраивается - выполняется во время настройки ядра.

Ответ 3

Если вам нужно вычислить, сколько cpu%, используемых процессом за последние 10 секунд

  • прибудет total_time (13 + 14) в jiffies = > t1 время начала (22) в jiffies = > s1

- задержка в 10 секунд

total_time (13 + 14) в jiffies = > t2 время начала (22) в jiffies = > s2

t2-t1 * 100/s2 - s1 не дал бы%??

Ответ 4

Вот еще один способ, которым я получил свое использование процессора приложений. Я сделал это в Android, и он делает главный вызов ядра и получает использование ЦП для ваших приложений PID, используя то, что вернул верх.

public void myWonderfulApp()
{
   // Some wonderfully written code here
   Integer lMyProcessID = android.os.Process.myPid();
   int lMyCPUUsage = getAppCPUUsage( lMyProcessID );
   // More magic
}


// Alternate way that I switched to.  I found the first version was slower
// this version only returns a single line for the app, so far less parsing
// and processing.
public static float getTotalCPUUsage2()
{
    try
    {
        // read global stats file for total CPU
        BufferedReader reader = new BufferedReader(new FileReader("/proc/stat"));
        String[] sa = reader.readLine().split("[ ]+", 9);
        long work = Long.parseLong(sa[1]) + Long.parseLong(sa[2]) + Long.parseLong(sa[3]);
        long total = work + Long.parseLong(sa[4]) + Long.parseLong(sa[5]) + Long.parseLong(sa[6]) + Long.parseLong(sa[7]);
        reader.close();

        // calculate and convert to percentage
        return restrictPercentage(work * 100 / (float) total);
    }
    catch (Exception ex)
    {
        Logger.e(Constants.TAG, "Unable to get Total CPU usage");
    }

    // if there was an issue, just return 0
    return 0;
}

// This is an alternate way, but it takes the entire output of 
// top, so there is a fair bit of parsing.
public static int getAppCPUUsage( Integer aAppPID)
{
    int lReturn = 0;
    // make sure a valid pid was passed
    if ( null == aAppPID && aAppPID > 0)
    {
        return lReturn;
    }

    try
    {
        // Make a call to top so we have all the processes CPU
        Process lTopProcess = Runtime.getRuntime().exec("top");
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(lTopProcess.getInputStream()));

        String lLine;

        // While we have stuff to read and we have not found our PID, process the lines
        while ( (lLine = bufferedReader.readLine()) != null )
        {
            // Split on 4, the CPU % is the 3rd field .
            // NOTE: We trim because sometimes we had the first field in the split be a "".
            String[] lSplit = lLine.trim().split("[ ]+", 4);

            // Don't even bother if we don't have at least the 4
            if ( lSplit.length > 3 )
            {
                // Make sure we can handle if we can't parse the int
                try
                {
                    // On the line that is our process, field 0 is a PID
                    Integer lCurrentPID = Integer.parseInt(lSplit[0]);

                    // Did we find our process?
                    if (aAppPID.equals(lCurrentPID))
                    {
                        // This is us, strip off the % and return it
                        String lCPU = lSplit[2].replace("%", "");

                        lReturn = Integer.parseInt(lCPU);
                        break;
                    }
                }
                catch( NumberFormatException e )
                {
                    // No op.  We expect this when it not a PID line
                }
            }
        }

        bufferedReader.close();
        lTopProcess.destroy();      // Cleanup the process, otherwise you make a nice hand warmer out of your device

    }
    catch( IOException ex )
    {
        // Log bad stuff happened
    }
    catch (Exception ex)
    {
        // Log bad stuff happened
    }

    // if there was an issue, just return 0
    return lReturn;
}

Ответ 5

Вот мое простое решение, написанное на BASH. Это системный монитор и менеджер процессов linux/unix через procfs, например " top " или " ps ". Существует две версии: простая монохромная (быстрая) и цветная (немного медленная, но полезная, особенно для мониторинга состояния процессов). Я сделал сортировку по загрузке процессора.

https://github.com/AraKhachatryan/top

  • utime, stime, cutime, cstime, starttime, используемые для получения загрузки процессора и полученные из файла /proc/[pid]/stat.

  • Параметры состояния, ppid, priority, nice, num_threads, полученные также из файла /proc/[pid]/stat.

  • Параметры resident и data_and_stack, используемые для получения использования памяти и полученные из файла /proc/[pid]/statm.


    function my_ps
    {
        pid_array='ls /proc | grep -E '^[0-9]+$''
        clock_ticks=$(getconf CLK_TCK)
        total_memory=$( grep -Po '(?<=MemTotal:\s{8})(\d+)' /proc/meminfo )

        cat /dev/null > .data.ps

        for pid in $pid_array
        do
            if [ -r /proc/$pid/stat ]
            then
                stat_array=( 'sed -E 's/(\([^\s)]+)\s([^)]+\))/\1_\2/g' /proc/$pid/stat' )
                uptime_array=( 'cat /proc/uptime' )
                statm_array=( 'cat /proc/$pid/statm' )
                comm=( 'grep -Po '^[^\s\/]+' /proc/$pid/comm' )
                user_id=$( grep -Po '(?<=Uid:\s)(\d+)' /proc/$pid/status )

                user=$( id -nu $user_id )
                uptime=${uptime_array[0]}

                state=${stat_array[2]}
                ppid=${stat_array[3]}
                priority=${stat_array[17]}
                nice=${stat_array[18]}

                utime=${stat_array[13]}
                stime=${stat_array[14]}
                cutime=${stat_array[15]}
                cstime=${stat_array[16]}
                num_threads=${stat_array[19]}
                starttime=${stat_array[21]}

                total_time=$(( $utime + $stime ))
                #add $cstime - CPU time spent in user and kernel code ( can olso add $cutime - CPU time spent in user code )
                total_time=$(( $total_time + $cstime ))
                seconds=$( awk 'BEGIN {print ( '$uptime' - ('$starttime' / '$clock_ticks') )}' )
                cpu_usage=$( awk 'BEGIN {print ( 100 * (('$total_time' / '$clock_ticks') / '$seconds') )}' )

                resident=${statm_array[1]}
                data_and_stack=${statm_array[5]}
                memory_usage=$( awk 'BEGIN {print( (('$resident' + '$data_and_stack' ) * 100) / '$total_memory'  )}' )

                printf "%-6d %-6d %-10s %-4d %-5d %-4s %-4u %-7.2f %-7.2f %-18s\n" $pid $ppid $user $priority $nice $state $num_threads $memory_usage $cpu_usage $comm >> .data.ps

            fi
        done

        clear
        printf "\e[30;107m%-6s %-6s %-10s %-4s %-3s %-6s %-4s %-7s %-7s %-18s\e[0m\n" "PID" "PPID" "USER" "PR" "NI" "STATE" "THR" "%MEM" "%CPU" "COMMAND"
        sort -nr -k9 .data.ps | head -$1
        read_options
    }

screenshot of working script

Ответ 6

Здесь вы ищете:

//USER_HZ detection, from openssl code
#ifndef HZ
# if defined(_SC_CLK_TCK) \
     && (!defined(OPENSSL_SYS_VMS) || __CTRL_VER >= 70000000)
#  define HZ ((double)sysconf(_SC_CLK_TCK))
# else
#  ifndef CLK_TCK
#   ifndef _BSD_CLK_TCK_ /* FreeBSD hack */
#    define HZ  100.0
#   else /* _BSD_CLK_TCK_ */
#    define HZ ((double)_BSD_CLK_TCK_)
#   endif
#  else /* CLK_TCK */
#   define HZ ((double)CLK_TCK)
#  endif
# endif
#endif

Этот код на самом деле от cpulimit, но использует фрагменты openssl.