linux创建进程和等待进程退出

         在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;
}

猜你喜欢

转载自blog.csdn.net/feihu521a/article/details/9386939