[c] 프로세스 검사하기
프로세스 검사하기
윤 상배
dreamyun@yahoo.co.kr
- 차례
- 1절. 소개
- 2절. 프로세스 관리기
- 2.1절. 프로세스 관리기 란?
- 2.2절. 프로세스 관리의 방법
- 2.3절. 만들고자 하는 프로그램에 대해서
- 2.4절. 솔라리스에서의 응용
- 3절. 결론
1절. 소개
이번에는 프로세스가 정상적으로 작동하고 있는지 그렇지 않은지를 검사하는 프로세스 관리기를 작성해보도록 할것이다. 이 관리 프로그램은 솔라리스와 리눅스에서 코딩되고 테스트 될것이다. 솔리리스와 Linux 를 선택한 이유는 필자가 쉽게 접근할수 있는 OS 이기 때문이다.
혹시라도 다른 Unix OS 에 접근할수 있는 기회가 생긴다면, 다른 기타 Unix 에서의 프로세스 관리 방법에 대해서 강좌를 만들어 보도록 하겠다.
2절. 프로세스 관리기
2.1절. 프로세스 관리기 란?
우리가 관리하는 시스템에는 수많은 프로세스가 작동하고 있을것이다. 이중 어떤 프로세스는 매우 중요해서 죽으면 안되는 그런 프로세스가 있을 것이며, 만약 이런 중요 프로세스가 작동을 중지 했다면 작동이 중지되었음을 관리자가 인지할수 있도록 신호를 보내주는 또다른 프로그램이 필요할 것이다.
이 프로그램은 관리해야되는 중요 프로세스를 지속적으로 모니터링 하고 있다가 문제가 생길경우 여러가지 방법으로 관리자에게 통보해야 할것이다. 통보 방법으로는 가장 널리 쓰일만한 것은 TCP/IP 소켓 통신을 이용한 관리자 프로그램으로의 alert 전송이 아마 가장 유용할것이다. 이는 대부분의 경우 관리자와 관리해야될 프로세스를 가동중인 시스템이 원격으로 떨어져 있기 때문일 것이다.
2.2절. 프로세스 관리의 방법
기본적으로 /proc 파일시스템의 정보를 이용한다. /proc 은 프로세스의 정보를 가지고 있는 임시 파일 시스템(process information pseudo-filesystem) 으로써 모든 실행중인 프로세스의 자세한 정보를 가진다.
대부분의 Unix 시스템들이 /proc 파일시스템을 채택하고 있는데, /proc 파일시스템을 분석함으로써, 어떤 프로세스가 어떤상태로 실행되고 있으며, 어떤 프로그램을 실행했는지, 어떤 파일을 open 하고 있는지, 메모리 사용은 어떠한지.. 등등 프로세스의 모든 정보를 알아낼수 있다.
프로세스 관리의 방법은 간단하다. /proc 파일시스템을 조사해서 관심있어 하는 프로세스가 제대로 작동하고 있는지 확인하면 되는 것이다.
2.3절. 만들고자 하는 프로그램에 대해서
프로세스관리라는 주제 자체가 너무 광범위 하므로, 범위를 좀 줄이도록 하겠다. 임의의 프로세스를 관리하는 방식이 아닌 특정한 프로세스를 관리하는 방식을 채택하도록 할것이다.
우리는 이전에 PIPE 응용 에서 fork&exec 기법으로 sub 프로그램을 자동으로 실행시키는 프로그램을 작성했었다. 우리는 기존의 프로그램을 약간 수정해서 생성된 sub 프로그램의 관리까지 가능하도록 할것이다.
2.3.1절. 프로세스
int main() { 설정파일을 읽어들인다. { 실행해야될 sub 프로그램의 실행명을 읽어들인다. } while(sub 프로그램 리스트의 크기만큼) { fork&exec 로 sub 프로그램을 실행시킨다. pipe 를 통하여 읽어들인 sub 프로그램의 pid 를 가져온다. } while(sub 프로그램의 pid 크기만큼) { /proc/pid/exe 를 조사한다. 만약 /proc/pid 가 없거나.. 있더라도 exe 이름이 다르면 프로세스에 이상이 생긴것으로 판단한다. } } |
2.3.2절. 코딩
아래의 프로그램의 이름은 proc_m.cc 로 하도록 하자. 코드는 수행가능한 상태로 만드는데에 중점을 두었으며, 아름다운 코드를 만들기 위한 부가적인 작업에는 신경을 쓰지 않았다. 아래의 프로그램을 보기전에 반드시 PIPE 응용 을 먼저 읽어보기 바란다.
예제 : proc_m.cc
#include <map> #include <stdio.h> #include <string> #include <unistd.h> #include <vector> int main(int argc, char **argv) { FILE *fp; char buf[80]; char info[20]; int sub_pid; int my_pid; int pid; int mypipe[2]; map |
각 실행프로그램의 프로세스 정보는 /proc 의 자신의 PID 를 이름으로 하는 디렉토리 밑에 저장된다. 예를들어 PID 이름이 1660 이였다면 PID 1660 에 대한 프로세스 정보는 /proc/1660 아래에 저장되게 된다.
/proc/pid 디렉토리 밑에 보면 exe 라는 심볼릭 링크된 파일이 하나 존재하는데 이것이 바로 해당 PID 에 대한 실행명령 이름이된다.
그러므로 우리는 최초에 프로그램을 실행시킬때 프로그램의 PID 번호와 실행프로그램의 이름을 안다면, /proc/pid/exe 파일을 조사함으로써, 프로세스가 제대로 실행되고 있는지를 감시할수 있게 된다.
2.3.3절. 테스트
이 프로그램을 실행시키면 아래와 같은 결과를 보여줄것이다.
[root@localhost test]# ./proc_m ok Process : 3217 ok Process : 3218 ok Process : 3219 ================== ok Process : 3217 ok Process : 3218 ok Process : 3219 ================== ok Process : 3217 ok Process : 3218 ok Process : 3219 ================== .... |
/usr/yundream/bin/proc1 Process error ok Process : 3218 ok Process : 3219 ================== ok Process : 3218 ok Process : 3219 ================== ... |
2.3.4절. 결과에 대한 분석
위의 프로그램은 특정상황에서 /proc 파일시스템을 이용해서 어떻게 프로세스의 관리가 가능한지에 대한 모습을 보여주고 있다. 비록 특정상황이긴 하지만, 기본적인 방법만 안다면 약간의 응용을 통하여 폭넓은 사용이 가능할것이다.
위의 프로그램을 서버/클라이언트 모델로 만들어서 문제 상황을 서버로 전송할수 있게 만들면 이 자체가 조그마한 SMS(시스템 관리하는 소프트웨어) 있다. 또한 마음만 먹는다면 ps 와 같은 전체 프로세스를 관리할수 있는 프로그램의 제작도 가능하다. 이렇게된다면 많은 기능을 포함하고 있는 SMS 프로그램의 작성도 가능할것이다.
여기에서는 설명하지 않고 있지만 /proc/pid 밑의 파일을 분석하면 해당 프로세스의 환경변수, 메모리 사용량, cpu 사용율, process 상태(좀비, sleep, run), 부모 PID 등의 아주 상세한 프로세스 정보를 가져올수 있기 때문이다. 이러한 상세한 정보는 man proc 를 참고하기 바란다.
2.4절. 솔라리스에서의 응용
리눅스의 /proc 시스템을 보면 모든 정보가 text 형태로 저장되어 있음을 알수 있을것이다. 그러므로 리눅스에서 필요한 프로세스 정보를 알아내고 싶다면, 정보를 가지고 있는 파일을 open 한다음에 이를 파싱하기만 하면 된다.
그러나 솔라리스의 경우에는 프로세스 정보가 text 가 아닌 구조체 형식으로 저장된다. 그러므로 해당 정보를 읽어들이기 위해서는 해당 프로세스 정보를 저장하고 있는 파일의 구조체 정보를 알고 있어야만 한다.
또한 파일의 이름이나 형식도 약간씩 차이가 있다. 예를 들어 리눅스에서는 해당 PID의 실행파일 이름을 가져오기 위해서 /proc/pid/exe 심볼릭 링크파일의 원본파일을 검사하면 되었지만 솔라리스는 /proc/pid/psinfo 의 파일을 읽어서 적당한 멤버변수로 구성되는 구조체에 저장한다음 이것을 읽어들여야 한다.
위의 리눅스 버젼을 솔라리스에서 사용가능한 버젼으로 바꾸기 위해서는 /proc/pid/psinfo 파일을 읽어들여서 psinfo 구조체에 담아오고 프로세스의 이름을 저장하고 있는 멤버변수를 읽어오는 방식을 사용해야 한다. 이 구조체는 다음과 같이 정의되어 있다.
typedef struct psinfo { int pr_flag; /* process flags */ int pr_nlwp; /* number of lwps in process */ pid_t pr_pid; /* unique process id */ pid_t pr_ppid; /* process id of parent */ pid_t pr_pgid; /* pid of process group leader */ pid_t pr_sid; /* session id */ uid_t pr_uid; /* real user id */ uid_t pr_euid; /* effective user id */ gid_t pr_gid; /* real group id */ gid_t pr_egid; /* effective group id */ uintptr_t pr_addr; /* address of process */ size_t pr_size; /* size of process image in Kbytes */ size_t pr_rssize; /* resident set size in Kbytes */ size_t pr_pad1; dev_t pr_ttydev; /* controlling tty device (or PRNODEV) */ /* The following percent numbers are 16-bit binary */ /* fractions [0 .. 1] with the binary point to the */ /* right of the high-order bit (1.0 == 0x8000) */ ushort_t pr_pctcpu; /* % of recent cpu time used by all lwps */ ushort_t pr_pctmem; /* % of system memory used by process */ timestruc_t pr_start; /* process start time, from the epoch */ timestruc_t pr_time; /* usr+sys cpu time for this process */ timestruc_t pr_ctime; /* usr+sys cpu time for reaped children */ char pr_fname[PRFNSZ]; /* name of execed file */ char pr_psargs[PRARGSZ]; /* initial characters of arg list */ int pr_wstat; /* if zombie, the wait() status */ int pr_argc; /* initial argument count */ uintptr_t pr_argv; /* address of initial argument vector */ uintptr_t pr_envp; /* address of initial environment vector */ char pr_dmodel; /* data model of the process */ char pr_pad2[3]; int pr_filler[7]; /* reserved for future use */ } psinfo_t; |
struct psinfo pinfo; fd = open("/proc/pid/psinfo", O_RDONLY); read(fd, (void *)&pinfo, sizeof(pinfo)); cout << "exec is " << pinfo.pr_fname << endl; |
어쨋든 정보를 가져오는 방식에는 약간 차이가 있긴하지만, 프로세스 정보를 가져오는 기본법칙은 리눅스나 솔라리스나 별차이가 없음을 알수 있다.
솔라리스에서 man proc 를 하면 이러한 정의된 구조체와 이에 대한 자세한 설명을 가져올수 있다.
3절. 결론
이상 간단한 프로세스 관리방법에 대해서 알아보았다. 느꼈겠지만 아마도 조금만더 신경을 쓰면, 꽤 많은 시스템 정보를 알려주는 SMS 프로그램의 제작이 가능할것이란 생각이 들것이다.
번호 | 분류 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|---|
397 | Develop |
[c++] 현승이가 준 P2P 프로그램 소스 ㅋㅋ
![]() |
hooni | 2013.04.23 | 12107 |
396 | Develop |
[php] 심플한 게시판 ㅋㅋ
1 ![]() |
hooni | 2013.04.23 | 13050 |
395 | Develop |
[jsp] RSS(xml) 파싱해서 보여주기 ㅎㅎ
![]() |
hooni | 2013.04.23 | 13246 |
394 | Develop |
[php] 한샘 전자발주 시스템..
![]() |
hooni | 2013.04.23 | 12034 |
393 | Develop | [c#] 파일(File) 쓰기 ㅎㅎ | hooni | 2013.04.23 | 13326 |
392 | Develop | [js] 자바스크립트를 동적으로 로딩하기 | hooni | 2013.04.23 | 13616 |
391 | Develop | [unix] 날짜 관련 쉘 명령어 (특정일 또는 +-시간, 날짜 계산된 값) | hooni | 2013.04.23 | 14894 |
390 | Develop |
[vb] 문자열에서 태그 제거함수 (Visual Basic)
![]() |
hooni | 2013.04.23 | 22684 |
389 | Develop |
[c#] 정규표현식을 이용한 문자열에서 태그 제거함수
![]() |
hooni | 2013.04.23 | 17883 |
388 | Develop |
[c] 포인터 학습용 예제 소스 코드
![]() |
hooni | 2013.04.23 | 21089 |
387 | Develop | OGNL(Object Graph Navigation Language) | hooni | 2013.04.23 | 15793 |
386 | Develop |
URI 인코딩, URL 인코딩
![]() |
hooni | 2013.04.23 | 18907 |