【tag-005】Linux C++ 网络编程架构之守护进程

本节我们实现一个守护进程,使得我们的程序可以脱离终端,运行在后台。

  • 配置
    我们希望通过配置文件,可以选择程序是否以守护进程的方式启动,因此首先在配置文件 nginx_sim.conf 中进行如下配置
# 注释行
# 每个有效配置项用 = 处理,= 前不超过40字符,= 后不超过400字符

# 以 [ 开头表示组信息,也等价于注释行
Log = logs/error2.log
LogLevel = 5

#表示程序是否以守护进程启动
Daemon = 1

  • 实现一个守护进程函数
    在文件 ngx_func.h 中声明函数 int ngx_deamon();在我们的目录结构中已经创建了专门存放进程相关的目录 proc,在此目录下新建 ngx_deamon.cxx 文件,在此文件我们实现这个函数。
/**
 * @brief 守护进程的初始化
 * @return -1: 执行失败; 子进程:0;父进程:1
 * 
 */
int ngx_deamon()
{
    switch(fork())
    {
    case -1:
        ngx_log_error_core(NGX_LOG_EMERG,errno,"ngx_deamon()中的fork()失败!");
        return -1;
    case 0:
        break;
    default:
        return 1;
    }

    //记录进程的ID
    ngx_parent = ngx_pid;
    ngx_pid = getpid();

    //脱离终端
    if(-1 == setsid())
    {
        ngx_log_error_core(NGX_LOG_EMERG,errno,"进程脱离终端失败!");
    }

    //取消文件权限的限制
    umask(0);

    int fd = open("/dev/null", O_RDWR);
    if (fd == -1) 
    {
        ngx_log_error_core(NGX_LOG_EMERG,errno,"ngx_daemon()中open(\"/dev/null\")失败!");        
        return -1;
    }
    //先关闭STDIN_FILENO,类似于指针指向null,让/dev/null成为标准输入;
    if (dup2(fd, STDIN_FILENO) == -1) 
    {
        ngx_log_error_core(NGX_LOG_EMERG,errno,"ngx_daemon()中dup2(STDIN)失败!");        
        return -1;
    }
    //再关闭STDIN_FILENO,类似于指针指向null,让/dev/null成为标准输出;
    if (dup2(fd, STDOUT_FILENO) == -1) 
    {
        ngx_log_error_core(NGX_LOG_EMERG,errno,"ngx_daemon()中dup2(STDOUT)失败!");
        return -1;
    }
    if (fd > STDERR_FILENO)
     {
        //释放资源这样这个文件描述符就可以被复用;不然这个数字【文件描述符】会被一直占着;
        if (close(fd) == -1)  
        {
            ngx_log_error_core(NGX_LOG_EMERG,errno, "ngx_daemon()中close(fd)失败!");
            return -1;
        }
    }
    return 0; //子进程返回0
}
  • 测试
    我们在 main 函数中,设置进程名之后加入以下代码测试
//守护进程
if(CConfig::GetInstance()->GetIntDefault("Daemon",0) == 1)
{
    int cdaemonresult = ngx_deamon();
    if(cdaemonresult == -1) //fork()失败
    {
        goto lblexit;
    }
    if(cdaemonresult == 1)
    {
        //这是原始的父进程
        freereSource();   //只有进程退出了才goto到 lblexit,用于提醒用户进程退出了
                          //而我现在这个情况属于正常fork()守护进程后的正常退出,不应该跑到lblexit()去执行,因为那里有一条打印语句标记整个进程的退出,这里不该限制该条打印语句;
        return 0;  //整个进程直接在这里退出
    }
    //走到这里,成功创建了守护进程并且这里已经是fork()出来的进程,现在这个进程做了master进程
    g_daemonized = 1;    //守护进程标记,标记是否启用了守护进程模式,0:未启用,1:启用了
}

运行我们的程序,可以看到已经脱离了终端
在这里插入图片描述
查看一下后台进程可以看到我们的进程正在运行
在这里插入图片描述
Note: 我们的程序中 master 进程其实并非最原始的进程,最原始的进程其实退出了,master 进程也是由最原始的进程 fork 出来的子进程。至于为何这样做,主要是这个原始的主进程是进程组的组长,调用 setsid 函数脱离终端会失败。

至此,我们的程序已经可以以守护进程的方式启动了,下一节将继续我们的进程话题,为我们的程序创建多个 worker 子进程。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一门linuxc++通讯架构实战课程,针对c/c++语言已经掌握的很熟并希望进一步深造以将来用c++linux下从事网络通讯领域/网络服务器的开发和架构工作。这门课程学习难度颇高但也有着极其优渥的薪水(最少30K月薪,最高可达60-80K月薪),这门课程,会先从nginx源码的分析和讲解开始,逐步开始书写属于自己的高性能服务器框架代码,完善个人代码库,这些,将会是您日后能取得高薪的重要筹码。本课程原计划带着大家逐行写代码,但因为代码实在过于复杂和精细,带着写代码可能会造成每节课至少要4~5小时的超长时间,所以老师会在课前先写好代码,主要的时间花费在逐行讲解这些代码上,这一点望同学们周知。如果你觉得非要老师领着写代码才行的话,老师会觉得你当前可能学习本门课程会比较吃力,请不要购买本课程,以免听不懂课程并给老师差评,差评也会非常影响老师课程的销售并造成其他同学的误解。 这门课程要求您具备下面的技能:(1)对c/c++语言掌握的非常熟练,语言本身已经不是继续学习的障碍,并不要求您一定熟悉网络或者linux;(2)对网络通讯架构领域有兴趣、勇于挑战这个高难度的开发领域并期望用大量的付出换取高薪;在这门课程中,实现了一个完整的项目,其中包括通讯框架和业务逻辑框架,浓缩总结起来包括如下几点:(1)项目本身是一个极完整的多线程高并发的服务器程序;(2)按照包头包体格式正确的接收客户端发送过来的数据包, 完美解决收包时的数据粘包问题;(3)根据收到的包的不同来执行不同的业务处理逻辑;(4)把业务处理产生的结果数据包正确返回给客户端;本项目用到的主要开发技术和特色包括:(1)epoll高并发通讯技术,用到的触发模式是epoll中的水平触发模式【LT】;(2)自己写了一套线程池来处理业务逻辑,调用适当的业务逻辑处理函数处理业务并返回给客户端处理结果;(3)线程之间的同步技术包括互斥量,信号量等等;(4)连接池中连接的延迟回收技术,这是整个项目中的精华技术,极大程度上消除诸多导致服务器程序工作不稳定的因素;(5)专门处理数据发送的一整套数据发送逻辑以及对应的发送线程;(6)其他次要技术,包括信号、日志打印、fork()子进程、守护进程等等;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值