twemproxy源码分析2——守护进程的创建
twemproxy源码中关于守护进程的创建实现得比较标准,先贴出代码来,然后结合一些资料来分析和列举一些实现守护进程的常用方法,不过不得不说twemproxy的实现确实是不错的,注释都写在了代码中,直接上代码吧:
static rstatus_t
nc_daemonize(int dump_core)
{
rstatus_t status;
pid_t pid, sid;
int fd; /*
* 先fork出一个子进程,把主进程关闭了
*/
pid = fork();
switch (pid) {
case -:
log_error("fork() failed: %s", strerror(errno));
return NC_ERROR; case :
break; default:
/* parent terminates */
_exit();
} /* 1st child continues and becomes the session leader */
/*
* 新fork出的子进程不可能是一个进程组的组长,这就避免了setsid函数调用的失败
* 在调用了setsid函数后该进程就成为新的会话组长和新的进程组长
* 并与原来的登录会话、进程组、控制终端脱离
*/
sid = setsid();
if (sid < ) {
log_error("setsid() failed: %s", strerror(errno));
return NC_ERROR;
} /*
* 处理SIGCHLD信号,内核在子进程结束时不会产生僵尸进程
*/
if (signal(SIGHUP, SIG_IGN) == SIG_ERR) {
log_error("signal(SIGHUP, SIG_IGN) failed: %s", strerror(errno));
return NC_ERROR;
} /*
* 再一次fork的原因是之前的子进程虽然已经脱离了控制终端,该子进程已经成为无终端的会话组长。
* 但它可以重新申请打开一个控制终端,可以通过使进程不再成为会话组长来禁止进程重新打开控制终端
*/
pid = fork();
switch (pid) {
case -:
log_error("fork() failed: %s", strerror(errno));
return NC_ERROR; case :
break; default:
/* 1st child terminates */
_exit();
} /* 2nd child continues */ /* change working directory */
/*
* 切换工作目录
*/
if (dump_core == ) {
status = chdir("/");
if (status < ) {
log_error("chdir(\"/\") failed: %s", strerror(errno));
return NC_ERROR;
}
} /* clear file mode creation mask */
/*
* 重设权限掩码
* 进程从创建它的父进程那里继承了文件创建掩码,它可能修改守护进程所创建的文件的存取位。
*/
umask(); /* redirect stdin, stdout and stderr to "/dev/null" */
/*
* 重定向描述符
*/
fd = open("/dev/null", O_RDWR);
if (fd < ) {
log_error("open(\"/dev/null\") failed: %s", strerror(errno));
return NC_ERROR;
} status = dup2(fd, STDIN_FILENO);
if (status < ) {
log_error("dup2(%d, STDIN) failed: %s", fd, strerror(errno));
close(fd);
return NC_ERROR;
} status = dup2(fd, STDOUT_FILENO);
if (status < ) {
log_error("dup2(%d, STDOUT) failed: %s", fd, strerror(errno));
close(fd);
return NC_ERROR;
} status = dup2(fd, STDERR_FILENO);
if (status < ) {
log_error("dup2(%d, STDERR) failed: %s", fd, strerror(errno));
close(fd);
return NC_ERROR;
} if (fd > STDERR_FILENO) {
status = close(fd);
if (status < ) {
log_error("close(%d) failed: %s", fd, strerror(errno));
return NC_ERROR;
}
} return NC_OK;
}
关于各种ID,先贴上一个图,后面再解释

twemproxy源码分析2——守护进程的创建的更多相关文章
- v76.01 鸿蒙内核源码分析(共享内存) | 进程间最快通讯方式 | 百篇博客分析OpenHarmony源码
百篇博客分析|本篇为:(共享内存篇) | 进程间最快通讯方式 进程通讯相关篇为: v26.08 鸿蒙内核源码分析(自旋锁) | 当立贞节牌坊的好同志 v27.05 鸿蒙内核源码分析(互斥锁) | 同样 ...
- Spark源码分析(三)-TaskScheduler创建
原创文章,转载请注明: 转载自http://www.cnblogs.com/tovin/p/3879151.html 在SparkContext创建过程中会调用createTaskScheduler函 ...
- Spring源码分析(十八)创建bean
本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.创建bean的实例 1. autowireConstructor 2 ...
- Docker源码分析(二):Docker Client创建与命令执行
1. 前言 如今,Docker作为业界领先的轻量级虚拟化容器管理引擎,给全球开发者提供了一种新颖.便捷的软件集成测试与部署之道.在团队开发软件时,Docker可以提供可复用的运行环境.灵活的资源配置. ...
- twemproxy源码分析1——入口函数及启动过程
最近工作中需要写一个一致性哈希的代理,在网上找到了twemproxy,结合网上资料先学习一下源码. 一.Twemproxy简介 Twemproxy是memcache与redis的代理,由twitter ...
- nova-api源码分析(WSGI server的创建及启动)
源码版本:H版 一.前奏 nova api本身作为一个WSGI服务器,对外提供HTTP请求服务,对内调用nova的其他模块响应相应的HTTP请求.分为两大部分,一是服务器本身的启动与运行,一是加载的a ...
- Spark源码分析(二)-SparkContext创建
原创文章,转载请注明: 转载自http://www.cnblogs.com/tovin/p/3872785.html SparkContext是应用启动时创建的Spark上下文对象,是一个重要的入口 ...
- twemproxy源码分析
twemproxy是twitter开源的redis/memcached 代理,数据分片提供取模,一致性哈希等手段,维护和后端server的长连接,自动踢除server,恢复server,提供专门的状态 ...
- mybatis源码分析(1)-----sqlSessionFactory创建
1. 首先了解一下mybatis,包含核心jar ,以及spring相关jar. <!-- Mybatis相关组件 --> <dependency> <groupId&g ...
随机推荐
- Laravel技⃣术⃣特⃣点⃣
1.Bundle是Laravel的扩展包组织形式或称呼.Laravel的扩展包仓库已经相当成熟了,可以很容易的帮你把扩展包(bundle)安装到你的应用中.你可以选择下载一个扩展包(bundle)然后 ...
- python wheel 包命名规则和 abi 兼容
wheel 包的命名规定 wheel 包的命名格式为 {distribution}-{version}(-{build tag})?-{python tag}-{abi tag}-{platform ...
- 流畅的python第十九章元编程学习记录
在 Python 中,数据的属性和处理数据的方法统称属性(attribute).其实,方法只是可调用的属性.除了这二者之外,我们还可以创建特性(property),在不改变类接口的前提下,使用存取方法 ...
- deferred rendering with msaa
https://docs.nvidia.com/gameworks/content/gameworkslibrary/graphicssamples/d3d_samples/antialiasedde ...
- Java笔记16:多线程共享数据
一.Thread实现 public class ThreadDemo4 { publicstaticvoid main(String[] args) { new ThreadTest4().start ...
- scala类型系统 type关键字
和c里的type有点像. scala里的类型,除了在定义class,trait,object时会产生类型,还可以通过type关键字来声明类型. type相当于声明一个类型别名: scala> t ...
- 屏幕录像大师如何把LXE文件转换为EXE文件
EXE 和 LXE 实际上是同一种格式,文件大小完全相同,可以快速相互转换.区别是EXE复制到其它电脑上可以直接播放,LXE需要播放器播放,我们提供LXE播放器,而且是完全免费的.EXE的好处是复制到 ...
- isset() unset()
检测变量是否设置,并且不是 NULL. 如果已经使用 unset() 释放了一个变量之后,它将不再是 isset().若使用 isset() 测试一个被设置成 NULL 的变量,将返回 FALSE. ...
- javascript脚本中使用json2.js解析json
官方地址:https://github.com/douglascrockford/JSON-js 点击页面右下角“Download ZIP”下载 网页中引用json2.js,下面是一个简单的例 ...
- ES6 Reflect
1.Reflect概述 ES6 为了操作对象而提供的新 API 2.Reflect设计目的 (1)将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到 ...