From 8f39550cea77eef1054b1febe7e647f96ac523c2 Mon Sep 17 00:00:00 2001 From: victor <taehoon@falinux.com> Date: Thu, 22 Jun 2017 17:27:41 +0900 Subject: [PATCH] =?UTF-8?q?superdaemon=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/superdaemon/Makefile | 15 ++ app/superdaemon/main.c | 392 ++++++++++++++++++++++++++++++++++++++++ app/superdaemon/main.h | 27 +++ app/superdaemon/projectinc.c | 33 ++++ app/superdaemon/projectinc.h | 21 +++ app/superdaemon/readme.txt | 29 +++ app/superdaemon/superdaemon.ini | 30 +++ 7 files changed, 547 insertions(+) create mode 100644 app/superdaemon/Makefile create mode 100644 app/superdaemon/main.c create mode 100644 app/superdaemon/main.h create mode 100644 app/superdaemon/projectinc.c create mode 100644 app/superdaemon/projectinc.h create mode 100644 app/superdaemon/readme.txt create mode 100644 app/superdaemon/superdaemon.ini diff --git a/app/superdaemon/Makefile b/app/superdaemon/Makefile new file mode 100644 index 0000000..dee6914 --- /dev/null +++ b/app/superdaemon/Makefile @@ -0,0 +1,15 @@ +CC = arm-buildroot-linux-gnueabihf-gcc +OBJS = main.o projectinc.o +TARGET = superdaemon + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CC) -lm -o $@ $^ + +%.o:%.c + @echo "Compiling $< ..." + $(CC) -c $< + +clean: + rm $(OBJS) $(TARGET) diff --git a/app/superdaemon/main.c b/app/superdaemon/main.c new file mode 100644 index 0000000..c3d0ffb --- /dev/null +++ b/app/superdaemon/main.c @@ -0,0 +1,392 @@ +/********************************************************************* + �� �� : superdaemon - ��ϵ� ���α��� ���� �� ���� + �� �� : 1.0.2 + - get_execinfo() �Լ� �߰� + - read_task_list() �Լ����� task_t ������ ��� �����ϵ��� ���� + 1.0.1 + - �ڽ� ���μ������� ���α��� �����ϱ� ���� + �θ� ���μ����� Ÿ��ũ ������ ������ ���μ����� ID�� + �����ϴ� �ð��� ���� �ֱ� ���� sleep()�Լ��� ȣ�� + 1.0.0 +*********************************************************************/ +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include "main.h" +#include "projectinc.h" + +#define PATH_SIZE 255 +#define TASK_ARRAY_SIZE 20 + +task_t ary_task[TASK_ARRAY_SIZE]; // Ÿ��ũ �迭 +int cnt_task; // ������ Ÿ��ũ�� ���� + +//-------------------------------------------------------------------- +// desc ���ϵ� ���μ����� ����Ǹ� ���ϴ� �̺�Ʈ �ڵ鷯 +// params sig +// ref ����� ���ϵ� ���μ����� �ش��ϴ� ary_task �� ������ ���� +// �����Ѵ�. +// +// ary_task ������ ���� �����ϸ�, main() ���� check_task_list() +// �� ȣ�������ν� �ٽ� �����ϰ� �ȴ�. +//-------------------------------------------------------------------- +void on_check_child( int sig) +{ + pid_t pid; + int result; + int ndx; + + // ����� ���ϵ� ���μ����� �ش��ϴ� ary_task �������� ã�´�. + // task_t �������� pid �� 0 ���� �����ϸ� check_task_lisk() ���� + // count_down ���� �����ϰ�, 0 �̵Ǹ� �ٽ� �����ϰ� �ȴ�. + + while( 0 < ( pid = waitpid( -1, &result, WNOHANG))) + { dp( "killed child pid=%d", pid); + for ( ndx= 0; ndx < cnt_task; ndx++) + { dp( "checked child pid=%d %s", ary_task[ndx].pid, ary_task[ndx].full_filename); + if ( pid == ary_task[ndx].pid) + { + ary_task[ndx].count_down = ary_task[ndx].interval; // �ٽ� �����ϱ� ������ ��� �ð�(��) + ary_task[ndx].pid = 0; // check_task_list() �� ����� �ǵ��� 0 ���� �ʱ�ȭ + } + } + } +} + +//-------------------------------------------------------------------- +// desc _str ���� ù��° ���� ���� ������ +// �Ǵ� ���� ���ڰ� ���� ������ ���ڿ� �������� _rst +// �� �����Ѵ�. +// params _str ���� ���ڿ��� ������ �ִ� ���� +// _rst ���ڿ��� ���� ���� ���� +// ret ���� ���ڿ� ������ ���� ��ġ�� ������ +//-------------------------------------------------------------------- +char *str_spc( char *_str, char *_rst) +{ + char *pos; + + *_rst = '\0'; // NULL �� ���� + pos = index(_str, ' '); + if ( !pos) // ���� �����ڰ� ���ٸ� ���� ������ + { + strcpy(_rst, _str); + } + else + { + strncpy(_rst, _str, pos-_str); + _rst[pos-_str] = '\0'; + while ( ' ' == *pos) // �տ� �ִ� ���� ���� + pos++; + } + return( pos); +} + +//-------------------------------------------------------------------- +// desc _task �� ���뿡 ���� �� ���μ����� ���� �����Ѵ�. +// params _task : ���� ���Ͽ� ���� ���� +// ref 1. +// _task �� task �κ��� �������ϰ� �μ��� ���Ѵ�. +// �����̳� �μ����� ������ �ִٸ� ������ ����ϰ�, +// _task �� error �� �����ڵ带 �־� ���� ȣ��� ������ +// ���� �ʵ��� �Ѵ�. +// 2. +// �μ��� 20������ ó���Ѵ�. +// +// 3. +// �μ��� ������ ���α��� ���� �ٸ��Ƿ�, +// *[] �� ����ϴ� execv() �� ����Ѵ�. +//-------------------------------------------------------------------- +void exec_task( task_t *_task) +{ + pid_t pid; + + if ( ERR_NONE != _task->error) + { + return; + } + + pid = fork(); + if ( 0 == pid) // �ڽ� ���μ��� ��� + { dp( "1 sec wait and exec %s", _task->full_filename); + sleep( 1); // ���� ���μ������� _task->pid = pid �� ������ �ǵ��� sleep + execv(_task->full_filename, _task->params); // ���α��� �����Ѵ�. + } + else if ( 0 < pid) // fork ��� �̻��� �����ٸ� + { dp( "********** task= %s New Pid= %d", _task->full_filename, pid); + _task->pid = pid; + } + else // ���� fork() ��� �����ߴٸ� + { dp( "Reset Counter %d", _task->interval); + _task->count_down = _task->interval; + } +} + +//-------------------------------------------------------------------- +// desc ary_task ����� Ȯ���ؼ� ����� ���ϵ尡 �ִ����� Ȯ���Ѵ�. +// ����� ���ϵ尡 �ִٸ� �����(���� ����)�� Ȯ���ϰ�, +// �� ���� ��Ų��. +//-------------------------------------------------------------------- +void check_task_list( void) +{ + int ndx; + + // ary_task ��Ͽ��� pid �� 0 �� ���� + // ����� ���ϵ� �̴�. + // + + for ( ndx = 0; ndx < cnt_task; ndx++) + { + if ( ( !ary_task[ndx].pid) // Ÿ��ũ�� ���� ���̰� + && ( ERR_NONE == ary_task[ndx].error)) // ������ ���ٸ� + { + if ( 0 < ary_task[ndx].count_down) // ���� ī��Ʈ �ٿ� ���̶�� + { dp( "count down :%d", ary_task[ndx].count_down); + ary_task[ndx].count_down--; + } + else // ī��Ʈ �ٿ��� �Ϸ� + { + exec_task( &ary_task[ndx]); + } + } + } + return; +} + +//-------------------------------------------------------------------- +// ������ ���ڿ����� task_t �� ������ ���α� �̸��� �μ��� ���Ѵ�. +// +// _data : ���Ͽ��� �о� ���� ������ ���丮 ��ġ������ ���ڿ� +// _task : ���� ���Ͽ� ���� ���� +// +// typedef struct +// { +// char *full_filename; <- ���丮 ���� ��ü ���� �̸��� ���Ѵ�. +// char *params[20]; <- ���α� ������ ���� �μ� �迭�� ���Ѵ�. +// : +// int error; <- ������ ���� �߿� ������ �ִٸ� ���� ���� +// : +// } task_t; + + + +// ref 1. +// _task �� task �κ��� �������ϰ� �μ��� ���Ѵ�. +// �����̳� �μ����� ������ �ִٸ� ������ ����ϰ�, +// _task �� error �� �����ڵ带 �־� ���� ȣ��� ������ +// ���� �ʵ��� �Ѵ�. +// 2. +// �μ��� 20������ ó���Ѵ�. +// +// 3. +// �μ��� ������ ���α��� ���� �ٸ��Ƿ�, +// *[] �� ����ϴ� execv() �� ����Ѵ�. +//-------------------------------------------------------------------- +void get_execinfo( char *_data, task_t *_task) +{ + char buf[PACKET_SIZE]; + char exe_path[PATH_SIZE+5]; // ���� ��� +5 + char exe_name[PATH_SIZE+5]; // ���� ��� +5 + int nparam; + int sz_str; + pid_t pid; + + // ��� ���� ���Ѵ�. + // ��� ���� ���� '/' �� ���ٸ� �߰��Ѵ�. + + _data = str_spc(_data, buf); + if ( PATH_SIZE < strlen( buf)) // ��θ��� ���̰� �ʹ� ���. + { + printf( "%s : path is too long!!\n", buf); + _task->error = ERR_PATH_TOO_LONG; + return; + } + strcpy( exe_path, buf); // exe_path <- ��θ� + + // ��� ���� ���� '/' �� Ȯ���Ѵ�. + + sz_str = strlen( exe_path); + if ( '/' != exe_path[sz_str-1]) // ���� / �� �ݵ�� ���� + { + exe_path[sz_str ] = '/'; + exe_path[sz_str+1] = '\0'; + } + + // ���� ������ ��ü �̸��� ���Ѵ�. + + _data = str_spc(_data, buf); + if ( PATH_SIZE < strlen( exe_path)+strlen( buf)) // ��ο� ���������� �̸� ���� ���� �ʹ� ���. + { + printf( "%s/%s : full name is too long!!\n", exe_path, buf); + _task->error = ERR_PATH_TOO_LONG; + return; + } + strcpy( exe_name, buf); + strcat( exe_path, exe_name); // exe_path <- ���/���������̸� + _task->full_filename = malloc( strlen( exe_path)+1); + strcpy( _task->full_filename, exe_path); + + // ���� ������ ���� ������ Ȯ���Ѵ�. + + if ( 0 != access(_task->full_filename, F_OK)) + { + printf( "%s is not exists!!\n",_task->full_filename); + _task->error = ERR_PATH_TOO_LONG; + return; + } + + // ��� �ʿ��� �μ��� �迭�� �����Ѵ�. + // ù��° �μ��� �������� �̸����� �Ѵ�. + // ������ �μ��� NULL �� �ǵ��� �Ѵ�. + + _task->params[0] = malloc( strlen( exe_name)+1); + strcpy(_task->params[0], exe_name); + + // [0] �μ��� ���� ������ �̸��̹Ƿ�, + // [1] ���� ���α��� �μ��� �����Ѵ�. + // params�� *[20]�� ����Ǿ� �����Ƿ� + // �μ� ������ 19 ���� ���� ���ϰ� �Ѵ�. + + nparam = 1; + while (_data) + { + _data = str_spc(_data, buf); // ���� �μ����� ���Ѵ�. + _task->params[nparam] = malloc( strlen( buf)+1); // param[nparam] <- �μ��� + strcpy(_task->params[nparam], buf); + nparam++; + if ( 19 == nparam) // �μ��� �ʹ� ���ٸ� + { + printf( "%s has too many params!!\n", exe_name); + _task->error = ERR_TOO_MANY_PARAMS; + return; + } + } + _task->params[nparam] = ( char *)0; // ������ �������� NULL + _task->error = ERR_NONE; // ���� ���� +} + +//-------------------------------------------------------------------- +// ini ���Ͽ��� ������ ������ ������ �о� ���̰�, +// ary_task ����� �ۼ��Ѵ�. +//-------------------------------------------------------------------- +void read_task_list( void) +{ + FILE *fp; + char *tag; + char *pos; + char buf[PACKET_SIZE]; + char item[255]; + + cnt_task = 0; // ������ �۾� ���� �ʱ�ȭ + + fp = fopen( "./superdaemon.ini", "r"); // ȯ������ open; + if ( NULL == fp) + { // �о� ���� Ÿ��ũ�� ���� + return; + } + else + { + while( NULL != fgets( buf, PACKET_SIZE, fp)) + { + tag = buf; + remove_white_char( tag); // ���忡 �����ǵ�� ���� ȭ��Ʈ ���ڸ� ���ش�. + + // ���α� ���� �� ���� ���۱����� �ð� ������ ���Ѵ�. + + while ( ' ' == *tag) // �տ� �ִ� ���� ���� + { + tag++; + } + + if ( ( ' ' > *tag) || // ������ ���̰ų� + ( !strncmp( tag, "//", 2)) ) // �ּ����̶�� ���� ������ + { + continue; + } + // ���� ù ��° �����ʹ� ��� �ð� �����̴�. + // ù��° ���ڿ����� �ð� ������ ���Ѵ�. + + tag = str_spc( tag, item); + ary_task[cnt_task].interval = atoi( item); + + // ���α��� ���� ������ ���Ѵ�. + // ���� �������� ��ο� ���α� ���� �־�� �ϹǷ� + // �ּ� ���� ���ڰ� �ϳ� �־�� �Ѵ�. + // �μ��� ���� ���ڰ� ���ٸ� ����Ѵ�. + + if ( ( ' ' > *tag) || // ������ ���̰ų� + ( !strncmp( tag, "//", 2)) ) // �ּ����̶�� ���� ������ + { + continue; + } + + pos = index( tag, ' '); // ���� ���ڰ� ���ٸ� ����Ѵ�. + if (!pos) + { + continue; + } + + get_execinfo( tag, &ary_task[cnt_task]); + + // task �� �ʱⰪ�� �ʱ�ȭ �Ѵ�. + + ary_task[cnt_task].count_down = 0; + ary_task[cnt_task].pid = 0; + cnt_task++; + if ( TASK_ARRAY_SIZE == cnt_task) + { + printf( "***** Task list is over %d. *****\n", TASK_ARRAY_SIZE); + break; + } + } + } + fclose( fp); +} + +//-------------------------------------------------------------------- +// ���ϵ� ���μ����� ������ Ȯ���ϴ� �ñ׳� ��� +//-------------------------------------------------------------------- +void reg_child_signal( void) +{ + struct sigaction sig_child; // ���ϵ��� ������ �˱� ���� �ñ��� + + sig_child.sa_handler = on_check_child; + sigemptyset( &sig_child.sa_mask); + sig_child.sa_flags = 0; + sigaction( SIGCHLD, &sig_child, 0); +} + +//-------------------------------------------------------------------- +// main procedure +//-------------------------------------------------------------------- +int main( int argc, char **argv) +{ +#ifdef NDEBUG + + pid_t pid_daemon; // release ����� ���� endif ������ ������ ����ȴ�. + + pid_daemon = fork(); + if ( 0 > pid_daemon) // fork() ��� �����ߴٸ� + { + printf( "ERR: fork() failed\n"); // ���� ������ �˸���. + exit( 1); + } + else if( 0 != pid_daemon) // �θ� ���μ��� ��� + { + exit( 0); // �����Ѵ�. + } + +#endif + + reg_child_signal(); // child �ñ׳� ��� + read_task_list(); // ������ ���� ����� �ۼ��Ѵ�. + + while( 1 ) + { + check_task_list(); // �۾� ���¸� Ȯ���Ѵ�. + sleep( 1); // 1 �ʸ� ��� + } +} diff --git a/app/superdaemon/main.h b/app/superdaemon/main.h new file mode 100644 index 0000000..f6ffa97 --- /dev/null +++ b/app/superdaemon/main.h @@ -0,0 +1,27 @@ +#ifndef MAIN_H +#define MAIN_H + +#include <sys/types.h> + +#define TRUE 1 +#define FALSE 0 + +#define ERR_NONE 0 +#define ERR_PATH_TOO_LONG -1 +#define ERR_EXE_TOO_LONG -2 +#define ERR_PARAMS_TO0_LONG -3; +#define ERR_TOO_MANY_PARAMS -4; +#define ERR_EXECUTE -5; + +typedef struct +{ + char *full_filename; + char *params[20]; + int interval; + int count_down; + int error; + pid_t pid; +} task_t; + + +#endif diff --git a/app/superdaemon/projectinc.c b/app/superdaemon/projectinc.c new file mode 100644 index 0000000..fc62e09 --- /dev/null +++ b/app/superdaemon/projectinc.c @@ -0,0 +1,33 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "projectinc.h" + +//-------------------------------------------------------------------- +// desc ���ڿ����� /t /n /f �� ���� ȭ��Ʈ ���ڸ� NULL �ڵ�� +// �ٲپ� �ش�. +//-------------------------------------------------------------------- +void remove_white_char( char *_str) +{ + int ndx; + + for ( ndx = 0; ndx < strlen(_str); ndx++) + { + if (' ' > _str[ndx]) + { + _str[ndx] = '\0'; + } + } +} + +//-------------------------------------------------------------------- +// desc ������ �����ϰ� ������ �����Ѵ�. +//-------------------------------------------------------------------- +void error_handling(char *message) +{ + fputs( message, stderr); + fputc( '\n', stderr); + exit(1); +} + + diff --git a/app/superdaemon/projectinc.h b/app/superdaemon/projectinc.h new file mode 100644 index 0000000..85d8fcc --- /dev/null +++ b/app/superdaemon/projectinc.h @@ -0,0 +1,21 @@ +#ifndef _PROJECTINC_ +#define _PROJECTINC_ + +#define NDEBUG + +#ifndef NDEBUG +#define dp(fmt,args...) printf( fmt, ## args ); putchar( '\n') +#define dlp(fmt,args...) printf( "[%s %d]" fmt, __FILE__,__LINE__, ## args ) +#else +#define dp(fmt,args...) +#define dlp(fmt,args...) +#endif + +extern void remove_white_char( char *); +extern void error_handling(char *message); + +//----- SysManager --------------------------------------------------- + +#define PACKET_SIZE 1024 + +#endif diff --git a/app/superdaemon/readme.txt b/app/superdaemon/readme.txt new file mode 100644 index 0000000..d3ff7c3 --- /dev/null +++ b/app/superdaemon/readme.txt @@ -0,0 +1,29 @@ +prj name : superdaemon - 등록된 프로그램을 실행 및 관리 +descript : + + 1. superdaemon.ini 에 등록된 프로그램을 실행하고 + 프로그램 종료를 계속 확인하면서, + 종료되면 지정된 시간 후 다시 실행하게 한다. + + 2. 추후, watch dog 기능을 추가한다. + +version : + 0.0.1 superdaemon.ini 에 등록된 프로그램을 실행 + 0.0.2 execl() 사용하여 구성 + 0.0.3 1. + execl() 을 execv() 로 재 구성 + ref + execl() 은 인수가 ( ) + 2. + 실행파일 정보 문자열에 이상이 없을 때에만 + fork() 실행하도록 수정 + 1.0.0 1. + 파일을 실행할 때, 파일의 존재 유무를 확인하는 + 코드를 추가 + 2. + 환경 파일에서 경로명에 '/' 이 없을 때 발생하던 + 오류를 잡음 + + + 장길석, goguryeo@gmail.com + \ No newline at end of file diff --git a/app/superdaemon/superdaemon.ini b/app/superdaemon/superdaemon.ini new file mode 100644 index 0000000..54dcd46 --- /dev/null +++ b/app/superdaemon/superdaemon.ini @@ -0,0 +1,30 @@ +// superdaemon 에서 사용되는 환경파일입니다. + +// 아래의 리스트는 superdaemon 에서 실행되며, +// 프로그램이 종료되더라도 지정된 시간(초) 후에 다시 +// 자동으로 실행됩니다. + +// 작성 방법은 공백 문자로 분리가 되며, +// [시간] [경로] [실행파일 이름] [인수1] [인수2].... +// 식으로 한개의 행에 하나의 프로그램 실행 정보를 넣어주면 됩니다. + +// 실행 경로와 실행파일의 이름을 합쳐서 255자 이내이어야 하며, +// 인수는 20 개 이상이 될 수 없습니다. + +1 /bin/ ls -al 123 234 456 +3 /bin/ ls -al /tmp 678 90 +5 /bin/ ls -al /usr abc def + +//2 ./ tcp2rx /dev/ttyS05 22549 +//2 ./ tcp2rx /dev/ttyS04 22559 +//2 ./ tcp2rx /dev/ttyS03 22569 + +//2 ./ udp2rx /dev/ttyS06 22539 192.168.10.2 +//2 ./ udp2rx /dev/ttyS05 22549 192.168.10.2 +//2 ./ udp2rx /dev/ttyS04 22559 192.168.10.2 +//2 ./ udp2rx /dev/ttyS03 22569 192.168.10.2 + +//5 . child 1 +//5 ./ child 1 2 +//5 ./ child 1 2 3 + -- 2.1.4