서버를 백그라운드로 cpu 사용률이 높아집니다.

yhjj777의 이미지

직접 실행을 시키면 cpu 사용률이 평상시에 거의 0퍼센트를 유지하던 서버가
백그라운드 또는 데몬으로 실행시키면 cpu 사용률이 99퍼센트로 나옵니다.
싱글 쓰레드로 돌아가는 서버이기때문에 이와 같이 cpu 사용률이 비정상적으로
나오면 서버가 제대로 동작하지않아야 된다고 생각하는데,, 서버는 정상적으로
작동하니 어디서 문제가 있는건지 도무지 찾을 길이 없습니다.

서버는 select와 논블락킹 소켓을 사용하고 있고, os는 레드햇 7.3, 커널은
2.4.18-3smp 입니다.. 이런 비슷한 문제를 경험하신분이 있다면 해결책 좀
알려주세요.

alsong의 이미지

무한 루프가 select밖에 없다면
select가 계속 리턴된다는 이야긴데
리턴값을 체크해 보심이...

그나저나 백수 언제 탈출하냐... ㅡㅡ; 배고파라.

qufdl113의 이미지

또 반성합니다.

sunyzero의 이미지

특별한 경우가 아니고는 100% 나오는 것은 거의 무한루프때문입니다.

가장 편리한 방법으로는 profiler를 가지고 컴파일하신다음에

특정시간이 지난뒤에 죽이고 나면 어느부분에서 시간이 많이 소모되었는지 알 수 있습니다. 보통 위와 같은 무한루프같은 문제는 이렇게 많이 알아내죠.

========================================
* The truth will set you free.

liongo의 이미지

안녕하세요..

100% 먹는것이 문제고 안문제고는.. 만든사람의 의도에

따라라고 생각합니다만.. 일없을때 쉬고 일있을때 일하고

이런 구조라면 100%먹는거라면 뭔가 오버워크가 아닌가 싶습니다..

아니면 진짜로 100%먹을정도의 로드가 걸리고있던지요..

해깔리실까봐 적습니다만 100%먹는 의도를 가진 프로그램들은..

게임류가 많습니다.. 게임은 최대 프레임수를 뽑아내기위해서..

모든 시피유 자원을 뽑아내지요 그렇기때문에 쉬지 않고 일합니다..

물론 게임서버도 뭐 프레임당으로 아니.. 개발자의 의도라고 치죠..

개발가능합니다만.. 일단 질문하신분의.. 제작된 서버가 어떤 업무를

하고 어떤의도로 개발을 하신것이 중요합니다.. 단순히 100%먹어도

된다는 논리는 맞지 않는것 같습니다.

p.s

일반적으로 셀렉트는 이벤트가 생길경우 블러킹에서 헤어납니다. ( 타임아웃 포함 )

' 형식이 내용을 규정한다. '

yhjj777의 이미지

답변 해주신분들꼐 감사드립니다..

서버는 게임 서버구요, 문제가 되는 부분은 select 라는걸
알아냈지만,, 포레그라운드에서는 이상없던게 백그라운드에선
select에서 리턴값을 바로 바로 내버리니,, 원인 파악이 안되네요,
백그라운드와 포레그라운드에서 select가 동작을 다르게 하는건지,,,

mach의 이미지

yhjj777 wrote:
답변 해주신분들꼐 감사드립니다..

서버는 게임 서버구요, 문제가 되는 부분은 select 라는걸
알아냈지만,, 포레그라운드에서는 이상없던게 백그라운드에선
select에서 리턴값을 바로 바로 내버리니,, 원인 파악이 안되네요,
백그라운드와 포레그라운드에서 select가 동작을 다르게 하는건지,,,


select()에 관계된 라인을 보여주세요.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

yhjj777의 이미지

mach wrote:
yhjj777 wrote:
답변 해주신분들꼐 감사드립니다..

서버는 게임 서버구요, 문제가 되는 부분은 select 라는걸
알아냈지만,, 포레그라운드에서는 이상없던게 백그라운드에선
select에서 리턴값을 바로 바로 내버리니,, 원인 파악이 안되네요,
백그라운드와 포레그라운드에서 select가 동작을 다르게 하는건지,,,


select()에 관계된 라인을 보여주세요.

	tv.tv_sec  = timeout/1000;
	tv.tv_usec = timeout%1000*1000;

	Refresh(); // fd_set 갱신

	int count = select( maxfd + 1, &readset, 0, 0, &tv );
	if( count < 1 )
		return count;

timeout 값은 300으로 넘겨줍니다.

최종호의 이미지

select() 호출전에 readset 에 설정된 fd 리스트를 한번 출력해 보세요.

lsof 가 있다면 lsof 명령어를 이용해서 해당 프로세스의 파일 리스트들을

확인해 보시고, fd 리스트에 유효한 fd들이 지정되었는지 확인해 보세요.

cpu 100% 먹을 때 select가 리턴할 때 리턴값은 무엇인가요?

0보다 작은 경우라면 errno 는 어떻게 되나요?

0이라면, 혹시나 tv의 값도 한번 찍어보세요.

0보다 크다면 해당 처리로직을 쫓아가보시고,

다음번 루프에 그 fd가 readset 에 다시 설정되는지 여부를 확인해보세요.

mach의 이미지

yhjj777 wrote:

timeout 값은 300으로 넘겨줍니다.

300이면 수식에 의해 300%1000*1000 = 300000 => 300 ms인데
이 정도를 대기하면 현재 연결된 클라이언트가 없을 경우 100%가 나올 수 없습니다.
따라서, 당연하게도 의심이 가는 파라메터는 2개 입니다.
첫째, maxfd
둘째, readset
즉, 클라언트와 연결된 소켓이 단절되었을때의 후-처리가 부족하여,
이 값이 엉뚱한 값을 가지지 않나 궁금합니다.(이를 테면,
BAD file descriptor라던가.)
일단 아래 if문 내에 에러를 출력해보도록 하세요.
디버깅시에는 포어-그라운드(foreground)로 실행하셔도 무방하실듯합니다.
int count = select( maxfd + 1, &readset, 0, 0, &tv );
if( count < 1 ) {
   perror("[my debug] select ::");
   printf("maxfd = %d\n", maxfd );
   return count;
}

위 에러메시지를 올려주시지요. 만일 에러 메시지가 발생하지 않는다면,
문제가 복잡해지는군요.(현재, count >=1 인 경우에 대해서는, 고려하지 않았습니다.)

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

yhjj777의 이미지

읔,, 해결한줄 알았는데 해결된게 아닌거같습니다..

일단 첫번쨰 문제는 종료 처리를 제대로 안해줘 readfd에 0번 소켓이
계속 추가되는 문제였습니다..

두번째 문제는 현재 서버에서는 어떤 클라이언트도 접속하지 않은 상태이고
listen 소켓만 select의 readfd에 등록되어있는 상태입니다. 그런데,, 어떤
클라이언트도 접속을 하지 않았고 데이타를 주지도 않았는데 select에서
계속 1을 리턴하네요, 반응이 오는 소켓은 listen 하고 있는 소켓이구요..

select의 readfd에 반응하는 일이 접속을 한 경우와, 데이타를 보내온 경우,
접속을 종료한 경우 외에는 없다고 알고 있는데, 위 세가지외에 반응하는
일이 있나요?

같은 소스로 다른곳에서 테스트를 해봤습니다. 하나는 윈도우의
cygwin이고 하나는 linux 2.4.20입니다.. 그런데,, 잘됩니다.. --;;
이게 어찌된 경우인지..

mach의 이미지

yhjj777 wrote:

일단 첫번쨰 문제는 종료 처리를 제대로 안해줘 readfd에 0번 소켓이
계속 추가되는 문제였습니다..


0번... 혹시 stdin 아닐까요? 만일 그러하다면, 데몬(daemon)으로 실행하지 않고, 그냥 포어그라운드로 실행하면 0,1,2번 파일이 열리는것은 당연하겠습니다.
main() {
{
    close(0);  // 보통 데몬화 하는 함수내에 들어가게 됨
   //close(1); // 디버깅 중이므로 닫지 말고 보자!
   //close(2); // 디버깅 중이므로 닫지 말고 보자!
    ....
}

일단 위와 같이 코드를 수정하시고 테스트를 해보시고 나중에 데몬코드(여기서 0번파일 및 모든 열려진 파일을 닫을것임)를 검토하시길.

yhjj777 wrote:

두번째 문제는 현재 서버에서는 어떤 클라이언트도 접속하지 않은 상태이고
listen 소켓만 select의 readfd에 등록되어있는 상태입니다. 그런데,, 어떤
클라이언트도 접속을 하지 않았고 데이타를 주지도 않았는데 select에서
계속 1을 리턴하네요, 반응이 오는 소켓은 listen 하고 있는 소켓이구요..

음, FD_ISSET()으로 검토한 결과가 그와 같나요?
혹시, listen하고 있는 소켓디스크립터가 listenSocket이라고 할때,
select()를 진입하기전에 FD_SET()연산이 정확한지 검토하세요.
대충 다음과 같은 코드가 될텐데요.
while(loop) {
   FD_ZERO(&rfds); // 중요
   FD_SET(listenSocket, &rfds); // listenSocket에 대해 select의 이벤트를 보겠음
   ...
   // 그외 클라이언트들에 대해서도 FD_SET()을 수행할 수 있음
   ...
   select(....);
   ....
   // select에러 없음
   if ( FD_ISSET(listenSocket, &rfds)) { //새로운 클라이언트 연결 도착됨
        신규 클라이언트 처리; // 계속 이 조건에 걸린다는 말씀이죠?
   }
   ....
}

계속 위의 조건에 걸린다는 말씀이죠?
만일 그러하다면, 클라이언트 추가 로직이 계속 수행될텐데.....
일단 그러한지 답변을 주십시요.

yhjj777 wrote:

select의 readfd에 반응하는 일이 접속을 한 경우와, 데이타를 보내온 경우,
접속을 종료한 경우 외에는 없다고 알고 있는데, 위 세가지외에 반응하는
일이 있나요?

없습니다.
readfd에 대해서만 연산을 가했다면 당연합니다.
- listen 하는 소켓이라면 : 접속요청 도착
- 그외 소켓 : 입력(데이터)이 도착, 또는 접속종료(또는 파일인 경우 EOF;즉 더이상 데이터 읽을 수 없음!)

*참고로, 그외 시그널이나, 에러, 또는 타임아웃에 의해 select()를 빠져나올 수 있지만
이때의 리턴 값은 -1 입니다.(타임아웃은 '0' zero지요 )

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

yhjj777의 이미지

Quote:
음, FD_ISSET()으로 검토한 결과가 그와 같나요?
혹시, listen하고 있는 소켓디스크립터가 listenSocket이라고 할때,
select()를 진입하기전에 FD_SET()연산이 정확한지 검토하세요.
대충 다음과 같은 코드가 될텐데요.
while(loop) {
   FD_ZERO(&rfds); // 중요
   FD_SET(listenSocket, &rfds); // listenSocket에 대해 select의 이벤트를 보겠음
   ...
   // 그외 클라이언트들에 대해서도 FD_SET()을 수행할 수 있음
   ...
   select(....);
   ....
   // select에러 없음
   if ( FD_ISSET(listenSocket, &rfds)) { //새로운 클라이언트 연결 도착됨
        신규 클라이언트 처리; // 계속 이 조건에 걸린다는 말씀이죠?
   }
   ....
}

계속 위의 조건에 걸린다는 말씀이죠?
만일 그러하다면, 클라이언트 추가 로직이 계속 수행될텐데.....
일단 그러한지 답변을 주십시요.

클라이언트 추가 로직이 작동하거든요.. select에서 타임아웃이 안걸리고
바로 바로 리턴이 되버려서 cpu 사용률은 높지만요.. 다른 시스템에서
정상적으로 작동을 하는걸 보면 로직에 잘못된 부분이 있지는 않다고
생각하고 있습니다.. 차라리 다른데서도 전부 이상하게 작동을 하면 찾기는
쉬울텐데 말입니다.. --;;
아무래도 시스템쪽에 문제가 있다는 생각이 듭니다..

답변해주셔서 감사합니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.