Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>

CPU 사용율

리눅스는 proc(:12) 파일 시스템을 제공하는데, 여기에 운영체제의 여러 정보들을 저장합니다. 대부분의 정보가 plain text이기 때문에, 유저레벨에서 간단하게 운영체제의 정보를 읽을 수 있습니다. CPU, Memory 정보, 네트워크 인터페이스 정보, CPU 사용율, 프로세스 정보등등입니다.

CPU 사용율은 /proc/stat에 저장됩니다. 이 정보를 이용해서 모든 core의 user, sys, idle, iowait 사용율을 계산할 수 있습니다.
# cat /proc/stat
cpu  613212 1060 110282 2417014 43484 60 1260 0 0 0
cpu0 294570 408 56843 1205690 34442 42 1203 0 0 0
cpu1 318641 652 53438 1211323 9042 18 56 0 0 0
...

이 값은 누적 count이므로, 일정 시간 간격으로 값을 수집해서 이전 값의 변화량을 구해서 백분율로 나타내야 합니다. 예를 들어 idle을 계산하고 싶다면, 5초 간격으로 값을 수집해서 (idle 변화량/전체변화량) * 100 하면 됩니다. 자세한 내용은 sms 프로그램 개발문서를 참고하시기 바랍니다.

원리만 알고 있다면, 어떤 언어를 사용하든 어렵지 않게 CPU 사용율을 계산하는 프로그램을 만들 수 있습니다. 최근 Ruby언어를 공부하고 있는 관계로 Ruby로 만들어봤습니다. 루비언어를 공부한지 얼마되지 않아 그닥 세련된 코드를 기대하지는 마시길

#!/usr/bin/ruby

class CPUStat
    CID = 0
    USER = 1
    NICE = 2
    SYSTEM = 3
    IDLE = 4
    IOWAIT = 5
    TOTAL = 6
    def initialize
        @counter = 0
        @prev = Hash.new
        @cur = Hash.new
    end
    def open()
        statFile = File.new("/proc/stat", 'r') # /proc/stat 파일을 엽니다.
        begin
            @counter = @counter + 1
            while line = statFile.readline     # 내용을 읽어서 
                if line =~ /cpu[0-9]+/         # 정규표현식을 이용 cpu 정보라인만 읽습니다. 
                    items = line.split ' '     # 공백문자로 쪼갠다음 배열에 넣습니다.
                    @cur[items[CID]] = items   # cpu이름을 key로 저장합니다.
                end
            end
        rescue EOFError
            statFile.close
        end
    end

    def top()
        print "\033[0J\033[0;0H"
        # 사용율을 계산하려면 이전 측정값이 반드시 있어야 합니다.
        # 그래서 처음에 값을 한번 수집해야 합니다.
        if @counter == 1
            @prev = @cur.dup;
            return
        end
        puts "\033[1m#{Time.now}\033[0m"

        # 이전 값과 지금 수집한 값의 변화량을 이용
        # cpu 사용율을 계산합니다.
        @cur.each do | cpuname, v |
            total_prev = 0
            total_cur = 0
            total_diff=0
            for i in (USER..IOWAIT)
                total_prev = total_prev+@prev[cpuname][i].to_i
                total_cur = total_cur+v[i].to_i
            end
            total_diff = total_cur - total_prev
            puts "#{cpuname} : (%3d)%%us (%3d)%%sys (%3d)%%idle (%3d)%%wait \033[0m"  \
                % [ (((v[USER].to_i - @prev[cpuname][USER].to_i) / total_diff.to_f) * 100), \
                (((v[SYSTEM].to_i - @prev[cpuname][SYSTEM].to_i) / total_diff.to_f) * 100), \
                (((v[IDLE].to_i - @prev[cpuname][IDLE].to_i) / total_diff.to_f) * 100), \
                (((v[IOWAIT].to_i - @prev[cpuname][IOWAIT].to_i) / total_diff.to_f) * 100)] \
        end
        @prev = @cur.dup;
     end
end

cpustat = CPUStat.new
while 1
    cpustat.open()
    cpustat.top()
    sleep 2
end

실행화면 입니다. top 값과 비교해 보시면 되겠습니다.
Thu Nov 17 00:22:24 +0900 2011
cpu0 : ( 36)%us ( 13)%sys ( 49)%idle (  0)%wait 
cpu1 : ( 36)%us ( 13)%sys ( 50)%idle (  0)%wait