성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>리눅스 - /proc/pid/stat 정보를 이용해 프로세스의 CPU 사용량 구하는 방법</h1> <p> 아래의 글에 보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Calculate the Total CPU Usage of a Process From /proc/pid/stat ; <a target='tab' href='https://www.baeldung.com/linux/total-process-cpu-usage'>https://www.baeldung.com/linux/total-process-cpu-usage</a> </pre> <br /> 다음과 같은 스크립트를 소개하고 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > #!/bin/bash PID=$1 if [ -z "$PID" ]; then echo Usage: $0 PID exit 1 fi PROCESS_STAT=($(sed -E 's/\([^)]+\)/X/' "/proc/$PID/stat")) PROCESS_UTIME=${PROCESS_STAT[13]} PROCESS_STIME=${PROCESS_STAT[14]} PROCESS_STARTTIME=${PROCESS_STAT[21]} SYSTEM_UPTIME_SEC=$(tr . ' ' </proc/uptime | awk '{print $1}') CLK_TCK=$(getconf CLK_TCK) let PROCESS_UTIME_SEC="$PROCESS_UTIME / $CLK_TCK" let PROCESS_STIME_SEC="$PROCESS_STIME / $CLK_TCK" let PROCESS_STARTTIME_SEC="$PROCESS_STARTTIME / $CLK_TCK" let PROCESS_ELAPSED_SEC="$SYSTEM_UPTIME_SEC - $PROCESS_STARTTIME_SEC" let PROCESS_USAGE_SEC="$PROCESS_UTIME_SEC + $PROCESS_STIME_SEC" let PROCESS_USAGE="$PROCESS_USAGE_SEC * 100 / $PROCESS_ELAPSED_SEC" echon TCK == ${CLK_TCK}, The PID $PID has spent ${PROCESS_UTIME_SEC}s in user mode, ${PROCESS_STIME_SEC}s in kernel mode. Total CPU usage is ${PROCESS_USAGE_SEC}s echo The process has been running for ${PROCESS_ELAPSED_SEC}s. So, the process has used ${PROCESS_USAGE}% of CPU </pre> <br /> 그런데, 이게 좀 말이 안 됩니다. 프로세스가 구동된 시간(PROCESS_ELAPSED_SEC) 대비 CPU를 소비한 시간(PROCESS_USAGE_SEC)을 계산하고 있는데요, 그럼, 프로세스를 실행한 지 오래될수록 CPU 소비 시간이 줄어드는 계산밖에는 안 나옵니다. 그런데 달리 생각해 보면 말이 되기도 합니다. 프로세스가 실행된 이후로 시스템의 프로세스를 얼마나 소비했느냐를 알 수 있다는 것인데... 대개의 경우 별 쓸모없는 데이터에 불과합니다.<br /> <br /> 위와 같은 계산에 따르면, CPU 100%를 자주 치는 프로세스가 아닌 다음에야, 대부분의 경우 시간이 지날수록 출력 결과는 1%에 가까워지게 됩니다. 게다가 오래된 프로세스에 CPU 100%를 치는 코드를 돌려도 이미 지난 시간의 값이 크기 때문에 1%에서 2%로 가는 것조차 시간이 걸립니다. 실제로 위의 코드를 while 루프로 바꾸게 되면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > while [ -z "" ]; do <span style='color: blue; font-weight: bold'>sleep 1</span> ...[생략]... echo The PID $PID has spent ${PROCESS_UTIME_SEC}s in user mode, ${PROCESS_STIME_SEC}s in kernel mode. Total CPU usage is ${PROCESS_USAGE_SEC}s echo The process has been running for ${PROCESS_ELAPSED_SEC}s. So, the process has used ${PROCESS_USAGE}% of CPU done </pre> <br /> 화면에는 이런 식의 출력만 보게 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > The process has been running for 942s. So, the process has used <span style='color: blue; font-weight: bold'>1% of CPU</span> TCK == 100, The PID 21702 has spent 8s in user mode, 9s in kernel mode. Total CPU usage is 17s The process has been running for 943s. So, the process has used <span style='color: blue; font-weight: bold'>1% of CPU</span> TCK == 100, The PID 21702 has spent 8s in user mode, 9s in kernel mode. Total CPU usage is 17s The process has been running for 944s. So, the process has used <span style='color: blue; font-weight: bold'>1% of CPU</span> TCK == 100, The PID 21702 has spent 8s in user mode, 9s in kernel mode. Total CPU usage is 17s The process has been running for 945s. So, the process has used <span style='color: blue; font-weight: bold'>1% of CPU</span> TCK == 100, The PID 21702 has spent 8s in user mode, 9s in kernel mode. Total CPU usage is 17s The process has been running for 946s. So, the process has used <span style='color: blue; font-weight: bold'>1% of CPU</span> </pre> <br /> <hr style='width: 50%' /><br /> <br /> 그렇다면, 위의 코드를 우리가 잘 알고 있는 "작업 관리자"처럼, 혹은 "<a target='tab' href='https://man7.org/linux/man-pages/man1/top.1.html'>top</a>"처럼 보고 싶다면 어떻게 해야 할까요? ^^<br /> <br /> 방법은 예전에 설명한 윈도우의 CPU 사용량과 유사합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C# - 시스템의 CPU 사용량 및 프로세스(EXE)의 CPU 사용량 알아내는 방법 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/1684'>https://www.sysnet.pe.kr/2/0/1684</a> </pre> <br /> 즉, 시간 차에 따른 증가량을 CPU 사용량으로 보면 되는 건데요, 이를 위해 위의 코드에서 /proc/[pid]/stat 파일로부터 구한 user(PROCESS_UTIME), kernel(PROCESS_STIME) 시간을 1초마다 바뀐 차이를 계산하면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > #!/bin/bash # proc_cpu.sh let OLD_PROCESS_TIME=0 while [ -z "" ]; do sleep 1 PROCESS_STAT=($(sed -E 's/\([^)]+\)/X/' "/proc/$PID/stat")) PROCESS_UTIME=${PROCESS_STAT[13]} PROCESS_STIME=${PROCESS_STAT[14]} let PROCESS_TIME="$PROCESS_UTIME + $PROCESS_STIME" if [ $OLD_PROCESS_TIME -eq 0 ]; then OLD_PROCESS_TIME=$PROCESS_TIME continue fi <span style='color: blue; font-weight: bold'>let ELAPSED="$PROCESS_TIME - $OLD_PROCESS_TIME"</span> OLD_PROCESS_TIME=$PROCESS_TIME echo $ELAPSED done /* 출력 결과 0 4 0 ...[생략]... */ </pre> <br /> 저 값은 CLK_TCK가 반영된 것이니 이 값을 정식으로는 다음과 같이 계산한 다음,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <a target='tab' href='https://www.sysnet.pe.kr/2/0/13192'>x = $ELAPSED / $CLK_TCK</a> </pre> <br /> 퍼센트로 바꾸기 위해 이렇게 계산하면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > usage = x * 100 / 1(초) </pre> <br /> 바로 저 값이 프로세스의 CPU 사용률이 됩니다. 그런데, 대개의 경우 <span class="tex2jax_ignore">$</span>CLK_TCK가 100이기 때문에 $ELAPSED 자체가 백분율로 된 값으로 나옵니다. <br /> <br /> <hr style='width: 50%' /><br /> <br /> 그런데, 실제로 저렇게 구한 값을 top과 비교해 보면 좀 맞지 않습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [1초마다 $ELAPSED] 0, 0, 5, 0, 0, 3, 0, 0, 4 [top에서 보이는 값] 대체로 1.0 ~ 1.3 정도의 값 </pre> <br /> 도대체 무슨 차이일까요? 위의 테스트에 사용한 응용 프로그램은 CPU 사용을 약 1초마다 한 번씩 하고 있습니다. 실제로 /proc/pid/stat 파일의 값 변화를 체크해 봐도 그렇게 나옵니다.<br /> <br /> 그리고 왠지 top의 화면 변화는 약 3초로 보이는데요, 그래서 -d 옵션을 줘서 top을 1초 갱신으로 다시 실행해 보면,<br /> <br /> <img alt='linux_cpu_usage_1.png' src='/SysWebRes/bbs/linux_cpu_usage_1.png' /><br /> <br /> 거의 동일한 값을 보여주고 있습니다. 그러니까 결국 top은 /proc/pid/stat 값의 변화를 설정된 refresh 주기로 나눠서 "%CPU"에 보여주는 것이었습니다. 그렇기 때문에 기본 refresh 주기인 3초마다 나온 5, 3, 4의 값을 3으로 나눈 1.0 ~ 1.3 정도의 값이 나온 것입니다.<br /> <br /> 정리해 보면, 여러분들이 /proc/pid/stat을 이용해 CPU 사용량을 구하는 경우 차등 값을 사용해야 CPU 사용량을 구할 수 있습니다. 대개의 경우, 차등 값은 1초마다 구하게 될 텐데요, 그런 경우 (기본) 3초마다 평균을 보여주는 리눅스의 top 명령어와는 결과가 다를 수 있다는 점만 알아두시면 되겠습니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 참고로, /proc/pid/stat 파일의 갱신 주기는 어떻게 될까요? 아래의 Q&A 글에 보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > /proc/[pid]/stat refresh period ; <a target='tab' href='https://stackoverflow.com/questions/31219317/proc-pid-stat-refresh-period'>https://stackoverflow.com/questions/31219317/proc-pid-stat-refresh-period</a> </pre> <br /> <a target='tab' href='https://tldp.org/LDP/Linux-Filesystem-Hierarchy/html/proc.html'>문서</a>를 인용하며, OS/kernel 데이터가 바뀌는 순간에 바로 반영된다고 하니 아마도 CPU 사용량의 경우라면 이상적인 경우 <a target='tab' href='https://www.sysnet.pe.kr/2/0/11063'>시스템 타이머</a>의 주기에 맞춰 바뀔 듯합니다. 예를 들어, CPU 100%를 소비하는 예제를 실행한 다음 위의 proc_cpu.sh을 사용하면 구하는 시간마다 값이 바뀌는 것을 볼 수 있습니다. 반면, CPU를 거의 사용하지 않으면 해당 파일도 바뀌지 않은 채로 그 시간만큼 유지됩니다.<br /> </p><br /> <br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
7537
(왼쪽의 숫자를 입력해야 합니다.)