守护进程的三种实现方式 您所在的位置:网站首页 开启桌面进程命令是什么 守护进程的三种实现方式

守护进程的三种实现方式

2024-07-10 05:30| 来源: 网络整理| 查看: 265

实现守护进程 (1)nohup(2)fork()按步骤创建(3)deamon函数创建    Linux Daemon(守护进程)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。它不需要用户输入就能运行而且提供某种服务,不是对整个系统就是对某个用户程序提供服务。Linux系统的大多数服务器就是通过守护进程实现的。常见的守护进程包括系统日志进程syslogd、 web服务器httpd、邮件服务器sendmail和数据库服务器mysqld等。

  守护进程一般在系统启动时开始运行,除非强行终止,否则直到系统关机都保持运行。守护进程经常以超级用户(root)权限运行,因为它们要使用特殊的端口(1-1024)或访问某些特殊的资源。

  一个守护进程的父进程是init进程,因为它真正的父进程在fork出子进程后就先于子进程exit退出了,所以它是一个由init继承的孤儿进程。守护进程是非交互式程序,没有控制终端,所以任何输出,无论是向标准输出设备stdout还是标准出错设备stderr的输出都需要特殊处理。

守护进程的名称通常以d结尾,比如sshd、xinetd、crond等,下面我们就来介绍三种守护进程的创建方式。

(1)nohup nohup ——英文全称 no hang up(不挂起),用于在系统后台不挂断地运行命令,退出终端不会影响程序的运行。nohup 命令,在默认情况下(非重定向时),会输出一个名叫 nohup.out 的文件到当前目录下,如果当前目录的 nohup.out 文件不可写,输出重定向到 $HOME/nohup.out 文件中。

使用权限

所有使用者

语法格式

nohup Command [ Arg … ] [ & ]

参数说明:

Command:要执行的命令。Arg:一些参数,可以指定输出文件。&:让命令在后台执行,终端退出后命令仍旧执行。

实例 以下命令在后台执行 root 目录下的 runoob.sh 脚本:

nohup /root/runoob.sh &

在终端如果看到以下输出说明运行成功:

appending output to nohup.out

这时我们打开 root 目录 可以看到生成了 nohup.out 文件。

如果要停止运行,你需要使用以下命令查找到 nohup 运行脚本到 PID,然后使用 kill 命令来删除:

ps -aux | grep "runoob.sh"

参数说明:

a : 显示所有程序u : 以用户为主的格式来显示x : 显示所有程序,不区分终端机

找到 PID 后,就可以使用 kill PID 来删除。

kill -9 进程号PID

以下命令在后台执行 root 目录下的 runoob.sh 脚本,并重定向输入到 runoob.log 文件:

nohup /root/runoob.sh > runoob.log 2>&1 &

2>&1 解释:

将标准错误 2 重定向到标准输出 &1 ,标准输出 &1 再被重定向输入到 runoob.log 文件中。

0 – stdin (standard input,标准输入)1 – stdout (standard output,标准输出)2 – stderr (standard error,标准错误输出) (2)fork()按步骤创建

步骤如下:

将程序进入后台执行。由于守护进程最终脱离控制终端,到后台去运行。方法是在进程中调用 fork 使父进程终止,让 Daemon 在子进程中后台执行。这就是常说的“脱壳”。子进程继续函数 fork()的定义如下:pid_t fork(void);脱离控制终端、登录会话和进程组。开发人员如果要摆脱它们,不受它们的影响,一般使用 setsid() 设置新会话的领头进程,并与原来的登录会话和进程组脱离。 有必要先介绍一下Linux中的进程与控制终端,登录会话和进程组之间的关系:进程属于一个进程组,进程组号(GID)就是进程组长的进程号(PID)。登录会话可以包含多个进程组。这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终端。 控制终端,登录会话和进程组通常是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法是在第1点的基础上,调用setsid()使进程成为会话组长: setsid(); 说明:当进程是会话组长时setsid()调用失败。但第一点已经保证进程不是会话组长。setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。由于会话过程对控制终端的独占性,进程同时与控制终端脱离。禁止进程重新打开控制终端。现在,进程已经成为无终端的会话组长。但它可以重新申请打开一个控制终端。可以通过使进程不再成为会话组长来禁止进程重新打开控制终端。 if(pid=fork()) exit(0);//结束第一子进程,第二子进程继续(第二子进程不再是会话组长)重设文件权限掩码关闭打开的文件描述符,并重定向标准输入、标准输出和标准错误输出的文件描述符。进程从创建它的父进程那里继承了打开的文件描述符。如果不关闭,将会浪费系统资源,引起无法预料的错误。改变工作目录到根目录或特定目录进程活动时,其工作目录所在的文件系统不能卸下守护进程实例包括两部分:主程序 test.c 和初始化程序 init.c。主程序每隔一分钟向/tmp 目录中的日志test.log 报告运行状态。初始化程序中的 init_daemon 函数负责生成守护进程。读者可以利用 init_daemon函数生成自己的守护进程。

首先我们看一下要用到的函数

(1) setsid(); 说明:当进程是会话的领头进程时setsid()调用失败并返回(-1)。setsid()调用成功后,返回新的会话的ID,调用setsid函数的进程成为新的会话的领头进程,并与其父进程的会话组和 进程组脱离。由于会话对控制终端的独占性,进程同时与控制终端脱离。之前parent和child运行在同一个session里,parent是会话(session)的领头进程, parent进程作为会话的领头进程,如果exit结束执行的话,那么子进程会成为孤儿进程,并被init收养。执行setsid()之后,child将重新获得一个新的会话(session)id。这时parent退出之后,将不会影响到child了。 (2) umask 每个文件都有权限,每新创建一个文件就要指定文件权限(mode &umask)新创建的文件pathname 的 文件权限 = (umask & mode) 例: #include int main() { int fd; umask(0026); fd = open(“test.txt”,O_RDWR | O_CREAT,0666); if(fd < 0) perror(“open”); return 0; } //文件权限结果为 666 - 26 = 640 = rw-r----- (3)getdtablesize () getdtablesize ()是返回所在进程的文件描述附表的项数,即该进程打开的文件数目

代码如下:

#include < unistd.h > #include < sys/types.h > #include < sys/stat.h > #include void init_daemon(void) { int pid; int i; if (pid = fork()) { exit(0); } //是父进程,结束父进程 else if (pid exit(0); } //是第一子进程,结束第一子进程 else if (pid


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有