Linux:守护进程解析、如何实现守护进程

1、守护进程:

守护进程也称精灵进程(Daemon),是运行在后台的⼀一种特殊进程。它独立于控制终端周期性地执行某种任务或等待处理某些发生的事件。守护进程是⼀一种很有用的进程。Linux的大多数服务器就是用守护进程实现的。比如,Internet服务器inetd,Web服务器httpd等。同时,守护进程完成许多系统任

 

务。比如,作业规划进程crond等。Linux系统启动时会启动很多系统服务进程,

 

这些系统服务进程没有控制终端,不能直接和用户交互。其它进程都是在用户

 

登录或运行程序时创建,在运行结束或用户注销时终止,但系统服务进程不受用户登录注销的影响,它们一直在运行着。这种进程有⼀一个名称叫守护进程(Daemon)。

 

 

2、查看系统中的守护进程:

 

用ps axj命令查看系统中的进程(参数a表示不仅列当前用户的进程,也列

 

出所有其他用户的进程,参数x表示不仅列有控制终端的进程,也列出所有无控

 

制终端的进程,参数j表示列出与 作业控制相关的信息)。

 

凡是TPGID一栏写着-1的都是没有控制终端的进程,也就是守护进程。在

 

COMMAND一列用[] 括起来的 名字表示内核线程,这些线程在内核里创建,没

 

有用户空间代码,因此没有程序文件名和命令行, 通常采用以k开头的名字,表

 

示Kernel。init进程我们已经很熟悉了,udevd负责维护/dev目录下的 设备文

 

件,acpid负责电源管理,syslogd负责维护/var/log下的日志文件,可以看出,守护

 

进程通 常采用以d结尾的名字,表示Daemon。

 

 

3、自己实现守护进程:

(1)、调用umask将文件模式创建屏蔽字设置为0.

文件权限掩码是指屏蔽掉文件权限中的对应位,比如一个文件权限掩码是050它就屏蔽了文件拥有者得可读与可写权限,fork()创建的子进程会继承父进程的文件权限掩码,所以我们把文件权限掩码设为0,可以增加子进程的灵活性,使用umask(0) 即可。

(2)、调用fork,父进程退出(exit)。

原因:

1)如果该守护进程是作为一条简单的shell命令启动的,那么父进程终止使得shell认为该命令已经执行完毕。

2)保证子进程不是一个进程组的组长进程。

 

守护进程需要脱离shell终端,造成一种程序关闭的假象,所有的工作都在子进程中完成,创建子进程,父进程退出,会造成子进程成为一个孤儿进程,在linux中当系统发现一个孤儿进程,就会1号进程(init进程)收养它,这样子进程就变成init子进程了。代码如下:

                                  if(fork() > 0)

                                  {

                                         exit(0);

                                      }

(3)、 调用setsid创建一个新会话。setsid会导致:

1)调用进程成为新会话的首进程。

2)调用进程成为一个进程组的组长进程 。

3)调用进程没有控制终端。(再次fork一次,保证daemon进程,之后不会打开tty设备)。

  NAME

       setsid -creates a session and sets the process group ID

 

SYNOPSIS

       #include<unistd.h>

 

       pid_tsetsid(void);

 

DESCRIPTION

      setsid()  creates a new session ifthe calling process is not a process

       groupleader.  The calling process is theleader of  the  new session,

       the  process group leader of the new processgroup, and has no control-

       lingtty.  The process group ID and session IDof the  calling  process

       are setto the PID of the calling process.  Thecalling process will be

       the onlyprocess in this new process group and in this new session.

 

RETURN VALUE

       Onsuccess, 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.

 

           该函数调用成功时返回新创建的Session的id(其实也就是当前进程的id),

    出错返回-1。注意,调用这个函数之前,当前进程不允许是进程组的Leader,否则该函数返回-1。要保证当前进程不是进 程组的Leader也很容易,只要先fork再调用setsid就行了。fork创建的子进程和父进程在同一个进 程组中,进程组的Leader必然是该组的第⼀一个进程,所以子进程不可能是该组的第一个进程,在子进程中调用setsid就不会有问题了。成功调用该函数的结果是:

1. 创建一个新的Session,当前进程成为Session Leader,当前进程的id就是Session的id。

2. 创建一个新的进程组,当前进程成为进程组的Leader,当前进程的id就是进程组的id。

3. 如果当前进程原本有⼀一个控制终端,则它失去这个控制终端,成为一个没有控制终端的进程。所谓失去控制终端是指,原来的控制终端仍然是打开的,仍然可以读写,但只是一个普通的打开文件而不是控制终端了。

 

(4)、禁止进程重新打开控制终端:
  现在,进程已经成为无终端的会话组长。但它可以重新申请打开一个控制终端。可以通过使进程不再成为会话组长来禁止进程重新打开控制终端:
 
if(pid=fork())
     exit(0); //结束第一子进程,第二子进程继续(第二子进程不再是会话组长)

 

(5)、将当前工作目录更改为根目录。

 

NAME

       setsid - creates a session and sets theprocess group ID

 

SYNOPSIS

       #include <unistd.h>

 

       pid_t setsid(void);

 

DESCRIPTION

       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 control-

       ling tty.  The process group ID and session ID ofthe  calling  process

       are set to the PID of the callingprocess.  The calling process will be

       the only process in this new processgroup and in this new session.

 

RETURN VALUE

       On success, the (new) session ID of thecalling  process  is returned.

       On error,  (pid_t) -1  is returned,  and errno is set toindicate the

       error.

 

(6)、关闭不再需要的文件描述符。

 

             进程从父进程中继承了一些打开的文件描述符,不再需要使用时及时关闭,否则将会引起无法预料的错误和资源浪费。

      Close(0);

      Close(1);

      Close(2);

      即标准输入、输出、错误。

 

(7)、其他:忽略SIGCHLD信号。

                  处理SIGCHLD信号并不是必须的。 但对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。

    如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下可以简单地将 SIGCHLD信号的操作设为SIG_IGN。

 

signal(SIGCHLD,SIG_IGN);

 

   这样,内核在子进程结束时不会产生僵尸进程。

    这一点与BSD4不同,BSD4下必须显式等待子进程结束才能释放僵尸进程。

 

 

 

守护进程的完整代码:

 

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <signal.h>

#include <sys/stat.h>

 

void create_daemon()

{

   pid_tpid;

   umask(0);//设置文件掩码

 

   if(pid= fork() > 0)//调用fork()函数,父进程退出

   {

          exit(0);

   }

   setsid();//设置新会话

   signal(SIGCHLD,SIG_IGN);//处理SIGCHLD信号

 

   if(pid= fork() < 0)// 禁止进程重新打开控制终端

   {

          printf("forkerror");

          return;

   }

   elseif(pid != 0)

   {

          exit(0);

   }

 

   chdir("/");//改变当前工作目录

 

   close(0);//关闭打开的不再需要的文件描述符

   close(1);

   close(2);

 

}

 

int main()

{

   create_daemon();

   while(1)

   {

          sleep(1);

   }

 

   return0;

}

 

 

测试:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/459408.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CAS实现单点登录方案(SSO完整版)

一、简介 1、cas是由耶鲁大学研发的单点登录服务器 2、本教材所用环境 Tomcat7.2JDK1.7CAS Service 版本 cas-server-3.4.8-releaseCAS Client版本 cas-client-3.2.1-release 二、生成证书 证书对于实现此单点登录非常之重要&#xff0…

PHP、C#、通用的DES加密

2019独角兽企业重金招聘Python工程师标准>>> PHP class JoDES {private static $_instance NULL;/*** return JoDES*/public static function share() {if (is_null(self::$_instance)) {self::$_instance new JoDES();}return self::$_instance;}/*** 加密* para…

如何防止头文件被重复包含或引用?

一、#pragma once ( 比较常用&#xff09; 只要在头文件的最开始加入这条指令就能够保证头文件被编译一次&#xff0c;这条指令实际上在VC6中就已经有了&#xff0c;但是考虑到兼容性并没有太多的使用。 #pragmaonce是编译相关&#xff0c;就是说这个编译系统上能用&#xff…

如何解决类模板的分离编译问题?

一模板&#xff1a; 模板不是数据类型&#xff0c;只能算是一种行为集合的表示。编译器在使用模板时&#xff0c;通过更换模板参数来创建数据类型。这个过程就是模板实例化(Instantiation)&#xff0c; 从模板类创建得到的类型称之为特例(specialization)&#xff0c;说白了就是…

结对项目 刘静 201303014059 计科高职13-2

结对&#xff1a;人&#xff1a;孙帅 博客地址&#xff1a; http://www.cnblogs.com/s3366181/p/4509260.html一、 题目简介 1.所选题目&#xff1a;输出圆的面积 2.编程工具&#xff1a;Eclipse 3、实现功能&#xff1a;用户给定一圆的半径运行程序系统会给出给定半径圆的面…

弹出div或者弹出新窗口的固定位置、固定大小

2019独角兽企业重金招聘Python工程师标准>>> js代码&#xff1a; //打开一个新窗口&#xff0c;固定的位置&#xff0c;固定的大小 //window.open("push_add.html",newwindow, height550, width1000, top200, left500, toolbarno, menubarno, scro…

NAT(网络地址转换)技术与代理服务器原理

一、 Nat技术&#xff1a; NAT英文全称是“Network Address Translation”&#xff0c;中文意思是“网络地址转换”&#xff0c;它是一个IETF(Internet Engineering Task Force,Internet工程任务组)标准&#xff0c;允许一个整体机构以一个公用IP&#xff08;Internet Prot…

原 Linux搭建SVN 服务器2

原 Linux搭建SVN 服务器 发表于1年前(2014-08-05 17:55) 阅读&#xff08;12257&#xff09; | 评论&#xff08;3&#xff09; 31人收藏此文章, 我要收藏赞3摘要 Linux搭建SVN 服务器目录[-] Linux搭建SVN 服务器1 安装SVN2 使用客户端连接2.1 使用…

网络层核心:路由和路由生成算法

一、路由和路由算法简介&#xff1a; 路由就是通过互连的网络把信息从源地址传送到目的地址的活动。路由发生在OSI网络参考模型的第三层即网络层。 路由引导封包转送&#xff0c;经过一些中间的节点后&#xff0c;到达目的地。把该功能做成硬件的话称为路由器。路由通常根据路…

网络:常见的端口号及分类

一、端口号概念 在网络技术中&#xff0c;端口&#xff08;Port&#xff09;包括逻辑端口和物理端口两种类型。物理端口指的是物理存在的端口&#xff0c;如ADSL Modem、集线器、交换机、路由器上用 于连接其他网络设备的接口&#xff0c; 如RJ-45端口、SC端口等等。逻辑端口…

EditPlus 技巧大全:[1]怎么配置PHP编译环境

editplus是一款小巧但功能强大易扩展的文本编辑器&#xff0c;可以通过设置用户工具将其作为C,Java,Php等等语言的一个简单的IDE。 工具/原料 EditPlus v3.3.1 php 5.3.14 方法/步骤 1.打开editplus 2.点击菜单栏“工具” 3.选择下拉菜单的“配置用户工具”&#xff0c;进入配置…

网络:传输层 TCP报文格式解析

一、TCP报文格式 1、为了提供可靠的数据传输&#xff0c;TCP报文首部字段有较多的字段&#xff0c;TCP报文格式如下图&#xff1a; 图2 TCP报文格式 16位源和目标端口&#xff08;16位&#xff09;&#xff1a;用于多路复用/多路分解来自或送至上层应用的数据&#xff0c;可以…

MATLAB图像小波变换

为什么80%的码农都做不了架构师&#xff1f;>>> 小波变换与小波包变换 人脸图像f(x,y) 的一层小波变换如下图所示&#xff1a; 图中L 和H 分别表示低通滤波器和高通滤波器&#xff0c;l(n) 和h(n) 分别表示它们相应的脉冲响应&#xff0c;2↓1表示降2采样fLL和fHH分…

grunt之Gruntfile(1)

grunt 执行的时候&#xff0c;他会找该目录下的Gruntfile文件&#xff0c;所以&#xff0c;要在目录下创建Gruntfile文件。 下面我demo一个copy任务&#xff1a; 执行copy&#xff0c;首先我们要一个copy的模块&#xff0c;那么我们先安装下copy模块 首先&#xff0c;我到H盘&a…

MyEclipse从数据库反向生成实体类之Hibernate方式 反向工程

2019独角兽企业重金招聘Python工程师标准>>> 开发项目涉及到的表太多&#xff0c;一个一个的写JAVA实体类很是费事。MyEclipse提供简便的方法&#xff1a;反向数据库 步骤大致如下: 第一步&#xff1a; window-->open Perspective-->MyEclipse Java Persisten…

开始nodejs+express的学习+实践(8)

为什么80%的码农都做不了架构师&#xff1f;>>> 1.session使用 介绍的非常详细&#xff1a; http://www.cnblogs.com/chenchenluo/p/4197181.html 对比我们的app.js需要引入express-session模块和使用这个模块&#xff0c;在package依赖&#xff0c;并加载。 我们修…

maven项目部署到linux上的奇葩问题

2019独角兽企业重金招聘Python工程师标准>>> 经常会遇到这样子的问题&#xff0c;maven项目在本地的eclipse配置的好好的&#xff0c;结果一到服务器就运行不起来。 当然遇到这种情况&#xff0c;我们首先会想到环境变量和相关的路径问题&#xff0c;但是当这两个条…

网络:TCP通讯之 time_wait 状态

基于TCP协议的通讯流程1、TCP建立连接2、TCP断开连接3、TCP状态转换TCP状态解释&#xff1a; SYN-RECVD&#xff1a;再收到和发送一个连接请求后等待对方对连接请求的确认 ESTABLISHED&#xff1a;代表一个打开的连接 FIN-WAIT-1&#xff1a;等待远程TCP连接中断请求&#xff0…

linux下echo与time服务的程序实现

一、针对ECHO服务的TCP客户软件的实现 1.网络拓扑结构&#xff1a; 2.源码&#xff1a; 1 #include <stdio.h>2 #include <stdlib.h>3 #include <unistd.h>4 #include <string.h>5 #include <stdarg.h>6 #include <sys/types.h>7 #include…

Linux高性能服务器编程:进程池和线程池原理及应用(有图有代码有真相!!!)

一、问题引入 在前面编写多进程、多线程服务器时通过动态创建子进程和子线程来实现并发服务器&#xff0c;这样做有以下缺点&#xff1a; 1&#xff09;动态创建进程、线程将会比较耗费时间&#xff0c;将导致较慢的客户响应。 2&#xff09;动态创建的子进程只为一个客户服…