Linux进程实践(5) --守护进程
概述
守护进程是在需要在后台长期运行不受终端控制的进程,通常情况下守护进程在系统启动时自动运行,在服务器关闭的时候自动关闭;守护进程的名称通常以d结尾,比如sshd、xinetd、crond、atd等。
守护进程编程规则
调用umask将文件模式创建屏蔽字设置为一个已知值(通常是0)
调用fork(),创建新进程,它会是将来的守护进程
然后使父进程exit,保证子进程不是进程组组长
调用setsid创建新的会话
会话:是一个或者多个进程组的集合,通常一个会话开始与用户登录,终止于用户退出。在此期间,该用户运行的所有进程都属于这个会话期。
将进程的当前目录改为根目录 (如果把当前目录作为守护进程的目录,当前目录不能被卸载,它作为守护进程的工作目录了。)
关闭不再需要的文件描述符
将标准输入、标准输出、标准错误重定向到/dev/null
setsid
pid_t setsid(void);
setsid() creates a new session if the calling process is not a process group leader. The calling process is the leader of the new session, the process group leader of the new process group, and has no controlling terminal. The process group ID and session ID of the calling process are set to the PID of the calling process. The calling process will be the only process in this new process group and in this new session.
/*当调用进程不是一个进程组的组长时,Setsid创建一个新的会话;调用者进程会是这个会话期唯一的一个进程,且是该进程组的组长;调用者进程id是组id,也是会话期的id。不能用进程组组长去调用setsid函数*/
//示例:
int main()
{
pid_t pid = fork();
if (pid == -1)
err_exit("fork error");
else if (pid != 0)
exit(EXIT_SUCCESS);
// //查看下面这一部分代码在注释的前后有什么变化
// pid_t id = setsid();
// if (id == -1)
// err_exit("setsid error");
// else
// cout << "new session id = " << id << endl;
cout << "getpid = " << getpid() << endl;
cout << "getpgid = " << getpgid(getpid()) << endl;
return 0;
}
RETURN VALUE
On success, the (new) session ID of the calling process is returned. On error, (pid_t) -1 is returned, and errno is set to indicate the error.
Linux中的守护进程API
int daemon(int nochdir, int noclose);
参数:
nochdir:=0将当前目录更改至“/”
noclose:=0将标准输入、标准输出、标准错误重定向至“/dev/null”
DESCRIPTION
The daemon() function is for programs wishing to detach themselves from the controlling terminal and run in the background as system daemons. If nochdir is zero, daemon() changes the calling process's current working directory to the root directory ("/"); otherwise, the current working directory is left unchanged. If noclose is zero, daemon() redirects standard input, standard output and standard error to /dev/null; otherwise, no changes are made to these file descriptors.
//示例:自己动手写daemon函数(一个比较简单的示例)
bool myDaemon(bool nochdir, bool noclose)
{
umask(0);
pid_t pid = fork();
if (pid == -1)
err_exit("fork error");
else if (pid != 0) //parent
exit(0);
setsid();
if (nochdir == 0)
chdir("/");
if (noclose == 0)
{
int i;
for (i=0; i < 3; ++i)
close(i);
open("/dev/null", O_RDWR); //相当于把0号文件描述符指向/dev/null
dup(0); //把0号文件描述符 赋值给空闲的文件描述符 1
dup(0); //把0号文件描述符 赋值给空闲的文件描述符 2
}
return true;
}
//测试
int main(int argc, char *argv[])
{
myDaemon(0, 0); //0表示做出改变(当前目录,文件描述符),1表示不改变
printf("test ...\n");
while (true)
{
sleep(1);
}
return 0;
}
//一个比较经典和完善的实例;来自《APUE》
#include "apue.h"
#include <syslog.h>
#include <fcntl.h>
#include <sys/resource.h>
bool myDaemon(const char *cmd);
int main(int argc, char *argv[])
{
myDaemon("xiaofang");
while (true)
{
sleep(1);
}
return 0;
}
bool myDaemon(const char *cmd)
{
umask(0);
//Get maximum number of file descriptors.
rlimit rlt;
if (getrlimit(RLIMIT_NOFILE,&rlt) < 0)
{
err_quit("%s: can't get file limit",cmd);
}
//Become a session leader to lose controlling TTY.
pid_t pid = fork();
if (pid == -1)
{
err_quit("%s: can't fork",cmd);
}
if (pid != 0) //parent
{
exit(0);
}
setsid();
//Ensure future opens won't allocate controlling TTYs.
struct sigaction sa;
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGHUP,&sa,NULL) < 0)
{
err_quit("%s can't ignore SIGHUP",cmd);
}
if ((pid = fork()) < 0)
{
err_quit("%s: can't fork",cmd);
}
else if (pid != 0) //Second Parent
{
exit(EXIT_SUCCESS);
}
//change the current working directory to the root
if (chdir("/") < 0)
{
err_quit("%s: can't change directory to /",cmd);
}
//close all open file description
if (rlt.rlim_max == RLIM_INFINITY)
{
rlt.rlim_max = 1024;
}
for (unsigned int i = 0; i < rlt.rlim_max; ++i)
{
close(i);
}
//Attach file descriptors 0, 1, and 2 to /dev/null.
int fd0 = open("/dev/null",O_RDWR);
int fd1 = dup(0);
int fd2 = dup(0);
//Initialize the log file.
openlog(cmd,LOG_CONS,LOG_DAEMON);
if (fd0 != 0 || fd1 != 0 || fd2 != 0)
{
syslog(LOG_ERR,"unexpected file descriptors %d %d %d",
fd0,fd1,fd2);
exit(EXIT_FAILURE);
}
return true;
}
Linux进程实践(5) --守护进程的更多相关文章
- Linux编程之《守护进程》
Intro ----- 守护进程,也就是通常说的Daemon进程,是Linux中的后台服务进程.它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程常 ...
- Linux 下Qt实现守护进程实例(转)
原文地址:Linux守护进程的编程方法(含实例) 作者:lingdxuyan 参考文献 Linux信号列表(zz) Linux 守护进程的编程方法 linux上编写守护进程的例程 Linux下后台守 ...
- Linux进程托管与守护进程设置
引言 在上一篇<Linux启动之旅>中,我们了解了Linux启动过程,在该过程的最后一步,init进程拉起/etc/init.d/rcN.d/目录下指定的守护进程(daemon).假若自定 ...
- Linux下一个简单守护进程的实现 (Daemon)
在Linux/UNIX系统引导的时候会开启很多服务,这些服务称为守护进程(也叫Daemon进程).守护进程是脱离于控制终端并且在后台周期性地执行某种任务或等待处理某些事件的进程,脱离终端是为了避免进程 ...
- 一只简单的网络爬虫(基于linux C/C++)————守护进程
守护进程,也就是通常说的Daemon进程,是Linux中的后台服务进程.它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程常常在系统引导装入时启动, ...
- (七) 一起学 Unix 环境高级编程(APUE) 之 进程关系 和 守护进程
. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...
- python 进程锁 生产者消费者模型 队列 (进程其他方法,守护进程,数据共享,进程隔离验证)
#######################总结######### 主要理解 锁 生产者消费者模型 解耦用的 队列 共享资源的时候 是不安全的 所以用到后面的锁 守护进程:p.daem ...
- python开发 *进程数据隔离.守护进程,进程同步工具 * 180725
进程数据隔离.守护进程,进程同步工具 一.进程之间的数据隔离: from multiprocessing import Process n=100 #主程序中变量n= def func(): glob ...
- Python 之并发编程之进程中(守护进程(daemon)、锁(Lock)、Semaphore(信号量))
五:守护进程 正常情况下,主进程默认等待子进程调用结束之后再结束守护进程在主进程所有代码执行完毕之后,自动终止kill -9 进程号 杀死进程.守护进程的语法:进程对象.daemon = True设置 ...
随机推荐
- markdowm写博客测试
markdowm测试文档 #include <bits/stdc++.h> using namespace std; int main() { printf("Hello Wor ...
- python笔记三(list、tuple)
一.list list的增删改查 #增, classmates.append("nadech") #在末尾追加一个元素 classmates.insert(1,"agui ...
- webpack4.1.1的使用详细教程
安装全局webpack cnpm install -g webpack 安装全局webpack-cli npm install -g webpack-cli 初始化:生成package.json文件 ...
- 无法启动postgresql的错误
chown postgres /etc/ssl/private/ssl-cert-snakeoil.key chgrp postgres /etc/ssl/private/ssl-cert-snake ...
- Android自定义View(LimitScrollerView-仿天猫广告栏上下滚动效果)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/53303872 本文出自:[openXu的博客] 1分析 2定义组合控件布局 3继承最外层控件 ...
- 熟悉Python的各种基础小算法
网上有一个Python100小例子的栏目,里面代码良莠不齐,于是下面就自己实现了其中的一些案例. 01.py # coding:utf-8 import sys reload(sys) sys.set ...
- 小小聊天室 Python实现
相对于Java方式的聊天室,Python同样可以做得到.而且可以做的更加的优雅.想必少了那么多的各种流的Python Socket,你一定会喜欢的. 至于知识点相关的内容,这里就不多说了. UDP方式 ...
- introduction of velocity
一.velocity 简介 基于java 的模板引擎,apache 旗下的开源软件项目. 目的在于隔离 表示层和业务逻辑层,当然现在做的不仅仅是这些. 二.应用场景 web 应用程序:创建html页面 ...
- OpenMP与MPI联合编程
研究一下如何一起使用mpi和openmp 先上程序: #include <stdio.h> #include <stdlib.h> #ifdef _OPENMP #includ ...
- 同步图计算:GraphLite的安装和使用
http://blog.csdn.net/pipisorry/article/details/51350908 export HADOOP_HOME=/usr/local/hadoop-2.6.4ex ...