2-15 守护进程的实现

exit()与析构函数

exit()和析构函数的关系_exit会调用析构函数吗_ZM_iTUDOU的博客-CSDN博客

exit() 函数是用来终止程序的执行,并将控制权返回到操作系统。

        1、不会调用局部对象的析构函数。

        2、会调用全局对象的析构函数

return  会调用局部和全局对象的局部析构函数

exit()和return区别

return是语言级别的,它表示了调用堆栈的返回;return( )是当前函数返回,当然如果是在主函数main, 自然也就结束当前进程了,如果不是,那就是退回上一层调用。在多个进程时。如果有时要检测上个进程是否正常退出。就要用到上个进程的返回值,依次类推。而exit是系统调用级别的,它表示了一个进程的结束

析构函数是在对象被销毁之前自动调用的函数。它用于清理对象在创建时所分配的内存,释放资源以及做一些额外的清理工作。如果在程序结束时不调用析构函数,这些资源可能会被遗漏或泄漏。

因此,exit()函数和析构函数都是用于程序的清理工作,但目的不同。exit()函数用于程序终止,而析构函数用于对象销毁前的清理工作。在正常情况下,应该让程序自然结束,调用析构函数释放资源。只有在特殊情况下,如程序出现无法处理的错误时,才需要使用 exit() 函数强制结束程序执行。


守护进程?竟然如此简单 - 知乎 (zhihu.com)

linux系统编程之进程(八):守护进程详解及创建,daemon()使用 - mickole - 博客园 (cnblogs.com)


 

// 程序运行的日志。
CLogFile logfile;

int main(int argc,char *argv[])
{
  // 程序的帮助。
  if (argc != 2)
  {
    printf("\n");
    printf("Using:./checkproc logfilename\n");

    printf("Example:/project/tools1/bin/procctl 10 /project/tools1/bin/checkproc /tmp/log/checkproc.log\n\n");

    printf("本程序用于检查后台服务程序是否超时,如果已超时,就终止它。\n");
    printf("注意:\n");
    printf("  1)本程序由procctl启动,运行周期建议为10秒。\n");
    printf("  2)为了避免被普通用户误杀,本程序应该用root用户启动。\n");
    printf("  3)如果要停止本程序,只能用killall -9 终止。\n\n\n");

    return 0;
  }

  // 忽略全部的信号和IO,不希望程序被干扰。
  CloseIOAndSignal(true);
  }

  // 忽略全部的信号和IO,不希望程序被干扰。
  CloseIOAndSignal(true);

  // 打开日志文件。
  if (logfile.Open(argv[1],"a+")==false)
  { printf("logfile.Open(%s) failed.\n",argv[1]); return -1; }

  int shmid=0;

  // 创建/获取共享内存,键值为SHMKEYP,大小为MAXNUMP个st_procinfo结构体的大小。
  if ( (shmid = shmget((key_t)SHMKEYP, MAXNUMP*sizeof(struct st_procinfo), 0666|IPC_CREAT)) == -1)
  {
    logfile.Write("创建/获取共享内存(%x)失败。\n",SHMKEYP); return false;
  }

  // 将共享内存连接到当前进程的地址空间。
  struct st_procinfo *shm=(struct st_procinfo *)shmat(shmid, 0, 0);

  // 遍历共享内存中全部的记录。
  for (int ii=0;ii<MAXNUMP;ii++)
  {
    // 如果记录的pid==0,表示空记录,continue;
    if (shm[ii].pid==0) continue;

    // 如果记录的pid!=0,表示是服务程序的心跳记录。

    // 程序稳定运行后,以下两行代码可以注释掉。
    //logfile.Write("ii=%d,pid=%d,pname=%s,timeout=%d,atime=%d\n",\
    //               ii,shm[ii].pid,shm[ii].pname,shm[ii].timeout,shm[ii].atime);

    // 向进程发送信号0,判断它是否还存在,如果不存在,从共享内存中删除该记录,continue;
    int iret=kill(shm[ii].pid,0);
    if (iret==-1)
    {
      logfile.Write("进程pid=%d(%s)已经不存在。\n",(shm+ii)->pid,(shm+ii)->pname);
      memset(shm+ii,0,sizeof(struct st_procinfo)); // 从共享内存中删除该记录。
      continue;
    }

    time_t now=time(0);   // 取当前时间。

    // 如果进程未超时,continue;
    if (now-shm[ii].atime<shm[ii].timeout) continue;

    // 如果已超时。
    logfile.Write("进程pid=%d(%s)已经超时。\n",(shm+ii)->pid,(shm+ii)->pname);

    // 发送信号15,尝试正常终止进程。
    kill(shm[ii].pid,15);

    // 每隔1秒判断一次进程是否存在,累计5秒,一般来说,5秒的时间足够让进程退出。
    for (int jj=0;jj<5;jj++)
    {
      sleep(1);
      iret=kill(shm[ii].pid,0);     // 向进程发送信号0,判断它是否还存在。
      if (iret==-1) break;     // 进程已退出。
    }

    // 如果进程仍存在,就发送信号9,强制终止它。
    if (iret==-1)
      logfile.Write("进程pid=%d(%s)已经正常终止。\n",(shm+ii)->pid,(shm+ii)->pname);
    else
    {
      kill(shm[ii].pid,9);  // 如果进程仍存在,就发送信号9,强制终止它。
      logfile.Write("进程pid=%d(%s)已经强制终止。\n",(shm+ii)->pid,(shm+ii)->pname);
    }

    // 从共享内存中删除已超时进程的心跳记录。
    memset(shm+ii,0,sizeof(struct st_procinfo)); // 从共享内存中删除该记录。
  }

  // 把共享内存从当前进程中分离。
  shmdt(shm);

  return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值