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

linux创建进程和等待进程退出的更多相关文章

  1. Linux系统编程——特殊进程之僵尸进程

    僵尸进程(Zombie Process) 进程已执行结束,但进程的占用的资源未被回收.这种进程称为僵尸进程. 在每一个进程退出的时候,内核释放该进程全部的资源.包含打开的文件.占用的内存等. 可是仍然 ...

  2. python开发进程:共享数据&进程池

    一,共享数据 展望未来,基于消息传递的并发编程是大势所趋 即便是使用线程,推荐做法也是将程序设计为大量独立的线程集合 通过消息队列交换数据.这样极大地减少了对使用锁定和其他同步手段的需求, 还可以扩展 ...

  3. Linux系统编程之进程控制(进程创建、终止、等待及替换)

    进程创建 在上一节讲解进程概念时,我们提到fork函数是从已经存在的进程中创建一个新进程.那么,系统是如何创建一个新进程的呢?这就需要我们更深入的剖析fork函数. 1.1 fork函数的返回值 调用 ...

  4. LINUX编程学习笔记(十四) 创建进程与 父子进程内存空间

    1什么是进程:进程是一个执行中的程序 执行的程序: 代码->资源->CPU 进程有很多数据维护:进程状态/进程属性 所有进程属性采用的一个树形结构体维护 ps  -a//所有进程 ps - ...

  5. linux进程管理之进程创建

    所谓进程就是程序执行时的一个实例. 它是现代操作系统中一个很重要的抽象,我们从进程的生命周期:创建,执行,消亡来分析一下Linux上的进程管理实现. 一:前言 进程管理结构; 在内核中,每一个进程对应 ...

  6. Linux系统编程之--守护进程的创建和详解【转】

    本文转载自:http://www.cnblogs.com/mickole/p/3188321.html 一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终 ...

  7. linux系统编程:守护进程详解及创建,daemon()使用

    一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.它不需要用户输入就能运行而且提供某种服务,不是对整个 ...

  8. Linux之进程的等待与其内核实现解析

    进程通过fork产生子进程,进程也会死亡,进程退出的时候将会进行内核清理,释放所有进程的资源,资源包括:内存资源,文件资源,信号量资源,共享内存资源,或者引用计数减一,或者彻底释放.     不过进程 ...

  9. linux进程管理之进程创建(三)

    在linux系统中,许多进程在诞生之初都与其父进程共同用一个存储空间.但是子进程又可以建立自己的存储空间,并与父进程“分道扬镳”,成为与父进程一样真正意义上的进程. linux系统运行的第一个进程是在 ...

随机推荐

  1. C语言功能 --C

    功能名称: cabs 动力 能够: 计算绝对复数值 使用 法国: double cabs(struct complex z); 程序示例: #include <stdio.h> #incl ...

  2. Android 动画深入分析

    一些娱乐动画安德鲁斯被广泛使用应用上述的.在不牺牲性能,它可以带来非常好的体验,下面会解释具体的实现安卓动画.知识的学校一个明确清晰的白色. 动画类型 Android的animation由四种类型组成 ...

  3. HDU 5052 Yaoge’s maximum profit 光秃秃的树链拆分 2014 ACM/ICPC Asia Regional Shanghai Online

    意甲冠军: 特定n小点的树权. 以下n每一行给出了正确的一点点来表达一个销售点每只鸡价格的格 以下n-1行给出了树的侧 以下Q操作 Q行 u, v, val 从u走v,程中能够买一个鸡腿,然后到后面卖 ...

  4. 《Java并发编程实战》第十四章 构建自己的同步工具定义 札记

    一.状态依赖性的管理 有界缓存实现的基类 @ ThreadSafe public abstract class BaseBoundedBuffer<E> { @GuardeBy( &quo ...

  5. MongoDB初学者的配置环境和基础设施的使用

    一个.mongoDB安装 1.第一MongoDB官方网站下载安装包http://www.mongodb.org/. 依照自己的操作系统进行下载. 2.在硬盘上建立两个文件夹分辨存放mongoDB安装文 ...

  6. Android第一次打开应用程序,实现向导界面

    转载请注明出处,谢谢http://blog.csdn.net/harryweasley/article/details/42079167 先说下思路:1.利用Preference存储数据,来记录是否是 ...

  7. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(11)-验证码实现和底层修改

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(11)-验证码实现和底层修改 ASP.NET MVC+EF框架+EasyUI实现权限管系列  (开篇)   (1):框架搭建    ...

  8. hdu 3449 (有依赖的01背包)

    依赖背包 事实上,这是一种树形DP,其特点是每个父节点都需要对它的各个儿子的属性进行一次DP以求得自己的相关属性. fj打算去买一些东西,在那之前,他需要一些盒子去装他打算要买的不同的物品.每一个盒子 ...

  9. Mysql sql声明召回2 --正则表达式

    这里简单回顾mysql在过滤后的数据使用正则表达式时.主要利用每方法将样品,或添加一些简短的说明. 下面说说提前,使用正则表达式是用来过滤数据 REGEXPkeyword 基本字符相匹配: SELEC ...

  10. uboot中raise:Signal #8 caught的根本原因

    在移植uboot时编译一切正常,但uboot启动中载入自己写的网卡驱动出现故障,一直在打印raise:Signal #8 caught google  百度了一番,也有非常多人遇到了这个问题,大家都说 ...