在WIN32下,在一个进程里我们可以使用CreateProcess()创建一个进程,然后通过调用WaitForSingleObect(), WaitForMultipleObject()等待进程退出。那么在linux下该如何实现呢?
以下的代码实现了一个daemon程序, daemon程序负责系统启动其它所有App,当其它应用出现异常退出的时候,daemon程序会重新启动它们。
/******************************************************************** filename: daemon.c created: 2013-07-17 author: firehood purpose: daemon implement *********************************************************************/ #include <sys/types.h> #include <sys/stat.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <errno.h> #include <unistd.h> #include <syslog.h> #include <string.h> typedef enum APP_ID_ { APP_ID_MIN, APP_ID_RTMP = APP_ID_MIN, APP_ID_VIDTRANSFILT, APP_ID_SOS, ////////////////////// APP_ID_MAX, }APP_ID; typedef struct APP_INFO_ { APP_ID id; // app id const char* app_path; // app file path const char* cmdline; // app cmdline int start_interval; // waitting time before starting the app. (unit:ms) }APP_INFO; static APP_INFO APP_INFO_Array[] = { {APP_ID_RTMP, "/opt/exe/crtmpserver/sbin/crtmpserver", "/opt/exe/crtmpserver/etc/crtmpserver.lua" ,0}, {APP_ID_VIDTRANSFILT, "./VidTransFilt", NULL, 2000}, {APP_ID_SOS, "/opt/exe/sos", NULL, 5000}, }; pid_t APP_pid[APP_ID_MAX]; int ExecuteApp(const char *app_path,const char *argv[]); int GetAppIdByPid(pid_t pid); int main(void) { /* Our process ID and Session ID */ pid_t pid, sid; /* Fork off the parent process */ pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } /* If we got a good PID, then we can exit the parent process. */ if (pid > 0) { exit(EXIT_SUCCESS); } #if 0 /* Change the file mode mask */ umask(0); /* Open any logs here */ /* Create a new SID for the child process */ sid = setsid(); if (sid < 0) { /* Log the failure */ exit(EXIT_FAILURE); } /* Change the current working directory */ if ((chdir("/")) < 0) { /* Log the failure */ exit(EXIT_FAILURE); } /* Close out the standard file descriptors */ close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); #endif /* Daemon-specific initialization goes here */ printf("Daemon is running..\n"); int nAppCount = sizeof(APP_INFO_Array)/sizeof(APP_INFO); printf("Daemon: AppCount is [%d]\n",nAppCount); int i = 0; for(i =0; i<nAppCount;i++) { usleep(APP_INFO_Array[i].start_interval*1000); if(APP_INFO_Array[i].cmdline) { char* argv[3] ={0}; argv[0] = strrchr(APP_INFO_Array[i].app_path,'/')+1; argv[1] = APP_INFO_Array[i].cmdline; argv[2] = NULL; APP_pid[APP_INFO_Array[i].id] = ExecuteApp(APP_INFO_Array[i].app_path,argv); } else { APP_pid[APP_INFO_Array[i].id] = ExecuteApp(APP_INFO_Array[i].app_path,NULL); } printf("Daemon: %s is running pid = [%d]\n",APP_INFO_Array[i].app_path,APP_pid[APP_INFO_Array[i].id]); } int status; while(1) { pid_t ret_pid = wait(&status); if(ret_pid == -1) { printf("Daemon: all app are exited!\n"); break; } printf("Daemon: app [%d] returns\n",ret_pid); if(!WIFEXITED(status)) { printf("Daemon: app [%d] terminated abnormally\n",ret_pid); } else { printf("Daemon: app [%d] exited with code[%d]\n",ret_pid,WEXITSTATUS(status)); } int app_id = GetAppIdByPid(ret_pid); if(app_id>=0 && app_id!=APP_ID_RTMP) { // restart the app APP_pid[app_id] = ExecuteApp(APP_INFO_Array[app_id].app_path,APP_INFO_Array[app_id].cmdline); } } exit(EXIT_SUCCESS); } int GetAppIdByPid(pid_t pid) { int i = 0; for(i = 0; i<APP_ID_MAX;i++) { if(pid == APP_pid[i] & i != APP_ID_RTMP) { return i; } } return -1; } int ExecuteApp(const char *app_path,const char *argv[]) { if(app_path == NULL) { return 0; } pid_t pid = fork(); int ret; switch(pid) { case -1: perror("fork failed"); exit(-1); case 0 : ret = execv(app_path,argv); printf("start app[%s] failed, ret= [%d]\n",app_path,ret); break; default: break; } return pid; }