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…

Java编程中“为了性能”需做的26件事

摘要&#xff1a;最近的机器内存又爆满了&#xff0c;除了新增机器内存外&#xff0c;还应该好好review一下我们的代码&#xff0c;有很多代码编写过于随意化&#xff0c;这些不好的习惯或对程序语言的不了解是应该好好打压打压了。 本文参考网络资源总结的一些在Java编程中尽可…

Linux:守护进程详解及实现

转载&#xff1a;守护进程 其实&#xff0c;linux提供了daemon函数用于创建守护进程&#xff0c;实现原理与上文中介绍的是一样的。 #include int daemon(int nochdir, int noclose); 1&#xff0e; daemon()函数主要用于希望脱离控制台&#xff0c;以守护进程形式在后台运行…

如何循环遍历document.querySelectorAll()方法返回的结果

使用JavaScript的forEach方法&#xff0c;我们可以轻松的循环一个数组&#xff0c;但如果你认为document.querySelectorAll()方法返回的应该是个数组&#xff0c;而使用forEach循环它&#xff1a; /* Will Not Work */ document.querySelectorAll(.module).forEach(function() …

软件开发的生命周期描述

软件项目的生命周期: 项目计划 需求分析 设计(概要设计和详细设计) 编码 测试 发布 维护 项目计划阶段&#xff1a;走访客户&#xff0c;进行交流沟通&#xff0c;获得客户原始需求。 对客户的需求和市场等进行调研&#xff0c;分析&#xff0c;编写可行性分析报告。 通过不断的…

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…

PHP 如何判断当前用户已在别处登录

主要思路&#xff1a;1.登录时&#xff0c;将用户的SessionID记录下来2.验证登录时&#xff0c;将记录的该用户SessionID与当前SessionID匹配3.如果不相同&#xff0c;说明在别处登录 出处&#xff1a;http://bbs.lampbrother.net/read-htm-tid-121909-ds-1.html#tpc转载于:htt…

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

一模板&#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…

Unix_03_文件系统介绍_2

目录命令&#xff1a;1 显示目录路径名: pwd (print working directory)login:cnyxj [return]...................................输入登录名(cnyxj)password.................................................. 输入口令Welcome to UNIX!$pwd [return] ................…

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

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

apache mod_xsendfile提高php文件下载速度的方法

说明&#xff1a;在apache服务器中提供一个文件下载&#xff0c;一般使用一个url指向服务器中的文件即可提供下载。缺点&#xff1a;不能进行统计&#xff0c;权限检测等操作。 1&#xff0c;一般使用php提供下载&#xff0c;例如&#xff1a; 复制代码代码示例:<?php $f…

原 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;到达目的地。把该功能做成硬件的话称为路由器。路由通常根据路…

LeetCode--Sum Root to Leaf Numbers

题目&#xff1a; Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number. An example is the root-to-leaf path 1->2->3 which represents the number 123. Find the total sum of all root-to-leaf numbers. For ex…

在树莓派2上折腾kali2.0小记(1)

在树莓派2上折腾kali2.0小记&#xff08;1&#xff09;本文主要是对自己在树莓派2上折腾kali2.0过程的一个记录&#xff0c;主要面向初学者&#xff0c;欢迎各位大神赐教。很久之前就听说过树莓派大名&#xff0c;刚好今年发布2.0版本&#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;进入配置…