【原文】https://www.toutiao.com/i6566814959966093837/

Linux守护进程

一、 守护进程概述

守护进程,也就是通常所说的Daemon进程,是Linux中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件。守护进程常常在系统启动时开始运行,在系统关闭时终止。

Linux系统有很多守护进程,大多数服务都是用守护进程实现的。例如常见的常见的守护进程包括系统日志进程syslogd、 web服务器httpd、邮件服务器sendmail和数据库服务器mysqld等。

二、进程与终端

在Linux中,每一个系统与用户进行交流的界面称为终端。从该终端开始运行的进程都会依附于这个终端,这个终端称为这些进程的控制终端。当控制终端被关闭时,相应的进程都会被自动关闭。

守护进程能够突破这种限制,它从开始运行,直到整个系统关闭才会退出。如果想让某个进程不会因为用户或终端的变化而受到影响,就必须把这个进程变成一个守护进程。

三、 查看守护进程

命令: ps axj

父进程ID : PPID

进程ID : PID

进程组ID : PGID

会话期ID : SID

终端ID : TTY

终端进程组ID : TPGID

状态 : STAT

用户 : UID

运行时间 : TIME

指令: COMMAND

四、 Linux守护进程编写(五步)

1. 创建子进程,父进程退出

第一步完成以后,子进程就在形式上做到了与控制终端的脱离

由于父进程已经先于子进程退出,子进程变成孤儿进程

pid = fork();
if (pid > 0) /*父进程退出*/
{
exit(0);
}

由于守护进程是脱离控制终端的,因此,完成第一步后就会在shell终端里造成一程序已经运行完毕的假象。之后的所有后续工作都在子进程中完成,而用户在shell终端里则可以执行其他的命令,从而在形式上做到了与控制终端的脱离

由于父进程已经先于子进程退出,会造成子进程没有父进程,从而变成一个孤儿进程。在Linux中,每当系统发现一个孤儿进程,就会自动由1号进程收养。原先的子进程就会变成init进程的子进程。

2. 在子进程中创建新会话

setsid()函数作用

setsid函数用于创建一个新的会话,并使得当前进程成为新会话组的组长setsid函数能够使进程完全独立出来,从而脱离所有其他进程的控制。

进程属于一个进程组,进程组号(GID)就是进程组长的进程号(PID)。登录会话可以包含多个进程组。这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终端。控制终端,登录会话和进程组通常是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法是在第1点的基础上,调用setsid()使进程成为会话组长。

进程组: 一个或多个进程的集合。进程组由进程组ID来唯一标识。每个进程组都有一个组长进程,进程组ID就是组长进程的进程号。

会话期: 会话组是一个或多个进程组的集合

进程组 对话期 终端

3. 修改当前工作目录

chdir(“/tmp”);

通常的做法是让“/”或”/tmp”作为守护进程的当前工作目录 。

在进程运行过程中,当前目录所在的文件系统是不能卸载的。

chdir函数可以改变进程当前工作目录

4. 重设置文件权限掩码

umask(0);

文件权限掩码是指文件权限中被屏蔽掉的对应位。把文件权限掩码设置为0,可以增加该守护进程的灵活性。设置文件权限掩码的函数umask();

5. 关闭文件描述符

fdtablesize = getdtablesize();

for (fd = 0; fd < fdtablesize; fd++)

close(fd);

新建的子进程会从父进程那里继承所有已经打开的文件。在创建完新的会话后,守护进程已经脱离任何控制终端,应当关闭用不到的文件。这些被打开的文件可能永远不会被守护进程读或写,但它们一样消耗系统资源,而且可能导致所在的文件系统无法卸载

从终端输入的字符不可能达到守护进程,守护进程中用常规的方法(如printf)输出的字符也不可能在终端上显示出来。所以,文件描述符为0、1和2的三个文件(对应标准输入、标准输出和标准错误这三个流)已经失去了存在的意义,也应被关闭。

五、 应用代码举例

创建一个守护进程每隔1s向daemon.txt文件中写入一次系统时间。

#include
int main()
{
pid_t pid;
int num,i;
int fd;
time_t t;
char buf[100];
pid = fork();
//第一步:创建子进程,父进程结束(子进程有init进程托管);
if(pid == 0){
//第二步:创建新会话,脱离原来的进程,脱离控制终端,脱离原来的进程组;
setsid();
//第三步:修改当前目录,每一个进程都有一个当前目录;(不是必须的)
chdir("/tmp");
//第四步:重新设置文件权限掩码(不是必须的)
umask(0);
//第五步:关闭打开的文件描述符(如果父进程打开的文件,子进程会继承过来)
num = getdtablesize(); //获得当前打开的文件描述符表
for(i = 0; i < num; i++){
close(i);
}
fd = open("daemon.txt",O_WRONLY | O_CREAT ,0666);
while(1){
t = time(0);
sprintf(buf,"time: %s ",ctime(&t));
write(fd,buf,strlen(buf));
sleep(1);
}
}else if(pid > 0){
exit(0);
}
return 0;
}

【转】学习Linux守护进程详细笔记的更多相关文章

  1. 笔记整理--Linux守护进程

    Linux多进程开发(三)进程创建之守护进程的学习 - _Liang_Happy_Life__Dream - 51CTO技术博客 - Google Chrome (2013/10/11 16:48:2 ...

  2. CentOS 7.4 初次手记:第一章 Linux守护进程(daemon)

    第一节 init & sysvinit 6 I sysvinit 运行顺序... 6 II Sysvinit和系统关闭... 7 III Sysvinit 的小结... 7 IV 运行级别.. ...

  3. Linux守护进程编写指南

    Linux守护进程编写指南 守护进程(Daemon)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程是一种很有用的进 程.Linux的大多数服务器 ...

  4. .NET跨平台实践:用C#开发Linux守护进程

    Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon也能在后台正常工作. 一句话,为L ...

  5. .NET跨平台实践:用C#开发Linux守护进程(转)

    Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon也能在后台正常工作. 一句话,为L ...

  6. [转]❲阮一峰❳Linux 守护进程的启动方法

    ❲阮一峰❳Linux 守护进程的启动方法 "守护进程"(daemon)就是一直在后台运行的进程(daemon). 本文介绍如何将一个 Web 应用,启动为守护进程. 一.问题的由来 ...

  7. Server Develop (七) Linux 守护进程

    守护进程 守护进程,也就是通常说的Daemon进程,是Linux中的后台服务进程.它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程常常在系统引导装 ...

  8. Linux 守护进程和超级守护进程(xinetd)

    一 .Linux守护进程 Linux 服务器在启动时需要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户.提供这些服务的程序是由运行在后台的守护进程来执行的 ...

  9. Linux守护进程详解(init.d和xinetd) [转]

    一 Linux守护进程 Linux 服务器在启动时需要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户.提供这些服务的程序是由运行在后台 的守护进程来执行的 ...

随机推荐

  1. Jetty学习四:部署到Jetty

    转自:http://www.tuicool.com/articles/NrENjq Web应用的框架 标准Jetty发布版本能部署标准servlet Spec Web应用和Jetty内部Context ...

  2. Java设计模式学习记录-适配器模式

    前言 之前已经将五个创建型设计模式介绍完了,从这一篇开始介绍结构型设计模式,适配器模式就是结构型模式的一种,适配器要实现的效果是把“源”过渡到“目标”. 适配器模式 在开发过程中,使用一个已经存在的类 ...

  3. 几种常见算法的Python实现

    1.选择排序 选择排序是一种简单直观的排序算法.它的原理是这样:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的后 ...

  4. 小程序实例:用js方法splict()、indexOf()、push()、replace()等操作数组Array的增删改查

    一.增加数组子级 1.Array.push() 定义和用法 向数组的末尾处添加一个或多个子集,并返回新数组的长度 语法 var array=["好","扎在那个" ...

  5. 进程监控工具supervisor

    supervisor是一个python编写的进程管理工具, 可以方便的管理和监控进程. supervisor分为服务端supervisord和客户端supervisorctl. supervisor由 ...

  6. 网络之NSURLSession

    NSUrlSession参考的这篇博客,自己也调试了它的代码:http://www.it165.net/pro/html/201406/15223.html ,对NSUrlSession还不太理解,先 ...

  7. HTML5 FileReader实现图片上传前预览

    如果你的浏览器支持Html5的FileReader的话,实现图片上传前进行预览是一件非常容易之事情. 在控制器,创建一个视图Action: jQuery代码: 实时演示一下: 下面内容于2014-11 ...

  8. 不要62(hdu2089)

    不要62 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissi ...

  9. Java - Iterator源码解析

    java提高篇(三十)-----Iterator 迭代其实我们可以简单地理解为遍历,是一个标准化遍历各类容器里面的所有对象的方法类,它是一个很典型的设计模式.Iterator模式是用于遍历集合类的标准 ...

  10. LeetCode DB: Duplicate Emails

    Write a SQL query to find all duplicate emails in a table named Person. +----+---------+ | Id | Emai ...