什么是守护进程,创建守护进程的步骤是什么?

作者: 云计算机网 分类: 精华 发布时间: 2019-09-09 10:30
可能很多伙伴对于守护进程都很陌生,甚至都不知道守护进程是什么。守护进程是操作系统后台的一种特殊进程,像Linux系统的大多数服务器都是通过守护进程实现的。今天给大家科普一下什么是守护进程以及linux系统如何创建守护进程。  一、守护进程是什么?  Linux Daemon(守护进程)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。它不需要用户输入就能运行而且提供某种服务,不是对整个系统就是对某个用户程序提供服务。Linux系统的大多数服务器就是通过守护进程实现的。常见的守护进程包括系统日志进程syslogd、 web服务器httpd、邮件服务器sendmail和数据库服务器mysqld等。  守护进程一般在系统启动时开始运行,除非强行终止,否则直到系统关机都保持运行。守护进程经常以超级用户(root)权限运行,因为它们要使用特殊的端口(1-1024)或访问某些特殊的资源。  一个守护进程的父进程是init进程,因为它真正的父进程在fork出子进程后就先于子进程exit退出了,所以它是一个由init继承的孤儿进程。守护进程是非交互式程序,没有控制终端,所以任何输出,无论是向标准输出设备stdout还是标准出错设备stderr的输出都需要特殊处理。  守护进程的名称通常以d结尾,比如sshd、xinetd、crond等  二、创建守护进程的步骤  首先我们要了解一些基本概念:  1、进程组 :  每个进程也属于一个进程组  每个进程主都有一个进程组号,该号等于该进程组组长的PID号 。  一个进程只能为它自己或子进程设置进程组ID号  2、会话期:  会话期(session)是一个或多个进程组的集合。  setsid()函数可以建立一个对话期:  如果,调用setsid的进程不是一个进程组的组长,此函数创建一个新的会话期。  (1)此进程变成该对话期的首进程  (2)此进程变成一个新进程组的组长进程。  (3)此进程没有控制终端,如果在调用setsid前,该进程有控制终端,那么与该终端的联系被解除。 如果该进程是一个进程组的组长,此函数返回错误。  (4)为了保证这一点,我们先调用fork()然后exit(),此时只有子进程在运行  现在我们来给出创建守护进程的所需步骤:  编写守护进程的一般步骤:  (1)在父进程中执行fork并exit推出;  (2)在子进程中调用setsid函数创建新的会话;  (3)在子进程中调用chdir函数,让根目录 / 成为子进程的工作目录;  (4)在子进程中调用umask函数,设置进程的umask为0;  (5)在子进程中关闭任何不需要的文件描述符  说明:  (1)在后台运行。  为避免挂起控制终端将Daemon放入后台执行。方法是在进程中调用fork使父进程终止,让Daemon在子进程中后台执行。  if(pid=fork())  exit(0);//是父进程,结束父进程,子进程继续  (2)脱离控制终端,登录会话和进程组  有必要先介绍一下Linux中的进程与控制终端,登录会话和进程组之间的关系:进程属于一个进程组,进程组号(GID)就是进程组长的进程号(PID)。登录会话可以包含多个进程组。这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终端。  控制终端,登录会话和进程组通常是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法是在第1点的基础上,调用setsid()使进程成为会话组长:  setsid();  说明:当进程是会话组长时setsid()调用失败。但第一点已经保证进程不是会话组长。setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。由于会话过程对控制终端的独占性,进程同时与控制终端脱离。  (3) 禁止进程重新打开控制终端  现在,进程已经成为无终端的会话组长。但它可以重新申请打开一个控制终端。可以通过使进程不再成为会话组长来禁止进程重新打开控制终端:  if(pid=fork())  exit(0);//结束第一子进程,第二子进程继续(第二子进程不再是会话组长)  (4)关闭打开的文件描述符  进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。按如下方法关闭它们:  for(i=0;i 关闭打开的文件描述符close(i);gt;  (5) 改变当前工作目录  进程活动时,其工作目录所在的文件系统不能卸下。一般需要将工作目录改变到根目录。对于需要转储核心,写运行日志的进程将工作目录改变到特定目录如/tmpchdir(/)  (6)重设文件创建掩模  进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除:umask(0);  (7)处理SIGCHLD信号  处理SIGCHLD信号并不是必须的。但对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下可以简单地将SIGCHLD信号的操作设为SIG_IGN。  signal(SIGCHLD,SIG_IGN);  这样,内核在子进程结束时不会产生僵尸进程。这一点与BSD4不同,BSD4下必须显式等待子进程结束才能释放僵尸进程。  三、创建守护进程  在创建之前我们先了解setsid()使用:#include lt;unistd.hgt; 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 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.  //调用进程必须是非当前进程组组长,调用后,产生一个新的会话期,且该会话期中只有一个进程组,且该进程组组长为调用进程,没有控制终端,新产生的group ID 和 session ID 被设置成调用进程的PIDRETURN 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.  现在根据上述步骤创建一个守护进程:  以下程序是创建一个守护进程,然后利用这个守护进程每个一分钟向daemon.log文件中写入当前时间01#include lt;stdio.hgt;02#include lt;unistd.hgt;03#include lt;stdlib.hgt;04#include lt;time.hgt;05#include lt;fcntl.hgt;06#include lt;string.hgt;07#include lt;sys/stat.hgt;08#define ERR_EXIT(m) \09do\10{\11perror(m);\12exit(EXIT_FAILURE);\13}\14while (0);\15void creat_daemon(void);16int main(void)17{18time_t t;19int fd;20creat_daemon();21while(1){22fd = open(daemon.log,O_WRONLY|O_CREAT|O_APPEND,0644);23if(fd == -1)24ERR_EXIT(open error);25t = time(0);26char *buf = asctime(localtime(amp;t));27write(fd,buf,strlen(buf));28close(fd);29sleep(60);30}31return 0;32}33void creat_daemon(void)34{35pid_t pid;36pid = fork();37if( pid == -1)38ERR_EXIT(fork error);39if(pid gt; 0 )40exit(EXIT_SUCCESS);41if(setsid() == -1)42ERR_EXIT(SETSID ERROR);43chdir(/);44int i;45for( i = 0; i lt; 3; ++i)46{47close(i);48open(/dev/null, O_RDWR);49dup(0);50dup(0);51}52umask(0);53return;54}复制代码  结果:
守护进程是什么?linux创建守护进程的步骤详解  结果显示:当我一普通用户执行a.out时,进程表中并没有出现新创建的守护进程,但当我以root用户执行时,成功了,并在/目录下创建了daemon.log文件,cat查看后确实每个一分钟写入一次。为什么只能root执行,那是因为当我们创建守护进程时,已经将当前目录切换我/目录,所以当我之后创建daemon.log文件是其实是在/目录下,那肯定不行,因为普通用户没有权限,或许你会问那为啥没报错呢?其实是有出错,只不过我们在创建守护进程时已经将标准输入关闭并重定向到/dev/null,所以看不到错误信息。  四、利用库函数daemon()创建守护进程  其实我们完全可以利用daemon()函数创建守护进程,其函数原型:#include lt;unistd.hgt;int daemon(int nochdir, int noclose);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 processrsquo;s current working directory to the root directory (/); otherwise, 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.  功能:创建一个守护进程  参数:  nochdir:=0将当前目录更改至/  noclose:=0将标准输入、标准输出、标准错误重定向至/dev/null  返回值:  成功:0  失败:-1  现在我们利用daemon()改写刚才那个程序:01#include lt;stdio.hgt;02#include lt;unistd.hgt;03#include lt;stdlib.hgt;04#include lt;time.hgt;05#include lt;fcntl.hgt;06#include lt;string.hgt;07#include lt;sys/stat.hgt;08#define ERR_EXIT(m) \09do\10{\11perror(m);\12exit(EXIT_FAILURE);\13}\14while (0);\15void creat_daemon(void);16int main(void)17{18time_t t;19int fd;20if(daemon(0,0) == -1)21ERR_EXIT(daemon error);22while(1){23fd = open(daemon.log,O_WRONLY|O_CREAT|O_APPEND,0644);24if(fd == -1)25ERR_EXIT(open error);26t = time(0);27char *buf = asctime(localtime(amp;t));28write(fd,buf,strlen(buf));29close(fd);30sleep(60);31}32return 0;33}复制代码  当daemon(0,0)时:守护进程是什么?linux创建守护进程的步骤详解  结果同刚才一样,也是只有root才能成功,普通用户执行时看不到错误信息  现在让daemon(0,1),就是不关闭标准输入输出结果:守护进程是什么?linux创建守护进程的步骤详解  可以看到错误信息  现在让daemon(1,0),就是不重定向,结果如下:守护进程是什么?linux创建守护进程的步骤详解  这次普通用户执行成功了,以为没有切换到/目录下,有权限  其实我们可以利用我们刚才写的创建守护进程程序默认daemon()实现:  代码如下:01#include lt;stdio.hgt;02#include lt;unistd.hgt;03#include lt;stdlib.hgt;04#include lt;time.hgt;05#include lt;fcntl.hgt;06#include lt;string.hgt;07#include lt;sys/stat.hgt;08#define ERR_EXIT(m) \09do\10{\11perror(m);\12exit(EXIT_FAILURE);\13}\14while (0);\15void creat_daemon(int nochdir, int noclose);16int main(void)17{18time_t t;19int fd;20creat_daemon(0,0);21while(1){22fd = open(daemon.log,O_WRONLY|O_CREAT|O_APPEND,0644);23if(fd == -1)24ERR_EXIT(open error);25t = time(0);26char *buf = asctime(localtime(amp;t));27write(fd,buf,strlen(buf));28close(fd);29sleep(60);30}31return 0;32}33void creat_daemon(int nochdir, int noclose)34{35pid_t pid;36pid = fork();37if( pid == -1)38ERR_EXIT(fork error);39if(pid gt; 0 )40exit(EXIT_SUCCESS);41if(setsid() == -1)42ERR_EXIT(SETSID ERROR);43if(nochdir == 0)44chdir(/);45if(noclose == 0){46int i;47for( i = 0; i lt; 3; ++i)48{49close(i);50open(/dev/null, O_RDWR);51dup(0);52dup(0);53}54umask(0);55return;56}复制代码  关于linux系统创建守护进程的操作步骤就给大家讲解到这里了,在这方面有需要的,不妨按上述操作一下。
  • 在Linux中有一些有些程序即使执行完了任务,还是会留在进程中,这些程序被称作为僵尸进程,它们残留无任何用处还会消耗硬件资源,,虽然无害,但一直存在本身就是个问题了。那么该怎么处理僵尸进程呢?  Linux中的僵尸进程如何产生的?僵尸进程怎么杀?  什么是僵尸进程?  我们都知道进程的工作原理。我们启动一个程序,开始我们的任务,然后等任务结束了,我们就停止这个进程。 进程停止后, 该进程就会从进程表中移除。  你可以通过 System-Monitor 查看当前进程。  Linux中的僵尸进程如何产生的?僵尸进程怎么杀?  但是,有时候有些程序即使执行完了也依然留在进程表中。  那么,这些完成了生命周期但却依然留在进程表中的进程,我们称之为 僵尸进程。  僵尸进程如何产生的?  当你运行一个程序时,它会产生一个父进程以及很多子进程。 所有这些子进程都会消耗内核分配给它们的内存和 CPU 资源。  这些子进程完成执行后会发送一个 Exit 信号然后死掉。这个 Exit 信号需要被父进程所读取。父进程需要随后调用 wait 命令来读取子进程的退出状态,并将子进程从进程表中移除。  若父进程正确第读取了子进程的 Exit 信号,则子进程会从进程表中删掉。  但若父进程未能读取到子进程的 Exit 信号,则这个子进程虽然完成执行处于死亡的状态,但也不会从进程表中删掉。  僵尸进程对系统有害吗?  不会。由于僵尸进程并不做任何事情, 不会使用任何资源也不会影响其它进程, 因此存在僵尸进程也没什么坏处。 不过由于进程表中的退出状态以及其它一些进程信息也是存储在内存中的,因此存在太多僵尸进程有时也会是一些问题。  你可以想象成这样:  你是一家建筑公司的老板。你每天根据工人们的工作量来支付工资。 有一个工人每天来到施工现场,就坐在那里, 你不用付钱, 他也不做任何工作。 他只是每天都来然后呆坐在那,仅此而已!  这个工人就是僵尸进程的一个活生生的例子。但是, 如果你有很多僵尸工人, 你的建设工地就会很拥堵从而让那些正常的工人难以工作。  那么如何找出僵尸进程呢?  打开终端并输入下面命令:  01ps aux | grep Z  复制代码  会列出进程表中所有僵尸进程的详细内容。  僵尸进程怎么杀?  正常情况下我们可以用 SIGKILL 信号来杀死进程,但是僵尸进程已经死了, 你不能杀死已经死掉的东西。 因此你需要输入的命令应该是  01kill -s SIGCHLD pid  复制代码  将这里的 pid 替换成父进程的进程 id,这样父进程就会删除所有以及完成并死掉的子进程了。  你可以把它想象成:  你在道路中间发现一辆废弃的汽车,于是你联系了拖车,之后拖车就会将这辆废弃的汽车带离道路。  以上内容便是关于僵尸进程的一些描述和结束,有的程序编写的不是很好,所以关闭子程序有时候是起不了关键作用,必须得关闭父程序才行。
  • 相关推荐:

  • Linux中僵尸进程是什么?
  • 什么是MAC地址?如何修改
  • 交换机的使用方法
  • 微软这是要取代搜狗的节
  • Win10禁止连接U盘的方法
  • win10系统热点总是自动关
  • 怎么查看Win10是不是创意
  • Win10快速修复SD卡的方法
  • 什么是显卡,显卡的作用
  • 什么是“交换机”以及“
  • 网站内容禁止违规转载,转载授权联系中国云计算网