阿里云服务器

Linux守护进程详解

作者:it_tech 浏览量:220   发表于 2024-10-29 15:00 标签:

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

守护进程一般在系统启动时由init进程(或其他机制)启动,并且一直运行直到系统关闭。它们也常常为已经在运行的进程和将要运行的进程提供服务。

一、守护进程的概念

在UNIX,Linux,以及类UNIX系统中,守护进程(Daemon)是一种运行在后台的特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程是一种很有用的进程,它提供了一种执行有用任务的途径,同时为那些不需要或不能与控制台交互的任务提供了运行环境。

守护进程常常在系统引导装入时启动,在系统关闭时终止。它们独立于任何终端并且周期性地执行它们的任务。守护进程一般总是作为系统进程运行在后台,并且它们会占用很少的系统资源。它们一般在非常确定的时刻启动,可以响应其他进程的服务请求。

二、守护进程的名称

守护进程通常以字母d结尾,例如httpd、sshd、mysqld等。但是,这不是强制性的,也有不以d结尾的守护进程,如cron。

三、守护进程的工作原理

在UNIX和类UNIX系统中,守护进程通常在系统引导时由init进程启动,或者由其他守护进程启动。守护进程作为在后台运行的进程,不占用终端。

守护进程有两种运行方式:

独立运行的守护进程:独立运行的守护进程由init进程启动,并且始终运行。它们经常为系统提供关键服务,例如网络服务和系统日志。这些进程在启动时由init进程调用,并且可以在系统关闭时终止。

被请求启动的守护进程:被请求启动的守护进程在系统需要时才启动,它们可以由用户、系统管理员或某个程序启动。一旦启动,它们就像独立运行的守护进程一样运行。

守护进程通过监听特定的端口或文件系统来等待来自其他进程的服务请求。当它们接收到一个请求时,它们就处理该请求,然后等待下一个请求。

四、守护进程的创建

在Linux中,创建守护进程的方式有几种,包括使用nohup命令、&符号、setsid命令、fork()创建子进程然后让父进程退出等。但是,最标准的方法是使用fork()和setsid()系统调用来创建一个新的会话并成为该会话的领头进程,然后改变工作目录和文件权限掩码,并关闭文件描述符。

编写脚本或程序:首先,需要编写一个脚本或程序,该程序将作为守护进程执行的任务或服务。

创建子进程:使用fork()系统调用创建一个子进程。父进程继续执行,而子进程将进行后续步骤以成为守护进程。

终止父进程:父进程通过调用exit()退出,使得子进程成为孤儿进程,并由init进程(PID为1的进程)接管。

创建新会话:在子进程中,使用setsid()函数创建一个新的会话,并使子进程成为该会话的领导者。这一步确保了子进程与父进程的控制终端和会话组脱离关系。

改变当前目录:为了避免占用不必要的文件系统资源,守护进程会将当前工作目录更改为根目录“/”。

重设文件权限掩码:使用umask(0)重设文件权限掩码,确保新创建的文件具有适当的权限。

关闭文件描述符:守护进程会关闭所有不必要的文件描述符,通常将标准输入、输出和错误输出重定向到/dev/null,以避免产生不必要的输出。

以下是一个创建守护进程的示例代码:


#include <stdio.h>  #include <stdlib.h>  #include <unistd.h>  #include <fcntl.h>  #include <sys/types.h>  #include <sys/stat.h>  #include <sys/wait.h>  #include <syslog.h>  #include <string.h>  
void daemonize() {      pid_t pid;  
    // Fork off the parent process      pid = fork();  
    // An error occurred      if (pid < 0)          exit(EXIT_FAILURE);  
    // Parent process, exit      if (pid > 0)          exit(EXIT_SUCCESS);  
    // At this point we are executing as the child process  
    // Create a new SID for the child process      if (setsid() < 0)          exit(EXIT_FAILURE);  
    // Change the file mode creation mask      umask(0);  
    // Change to a known directory      if (chdir("/") < 0)          exit(EXIT_FAILURE);  
    // Close out the standard file descriptors      close(STDIN_FILENO);      close(STDOUT_FILENO);      close(STDERR_FILENO);  
    // Redirect standard files to /dev/null      open("/dev/null", O_RDONLY); // stdin      open("/dev/null", O_WRONLY); // stdout      open("/dev/null", O_RDWR);   // stderr  
    // Now we can do any additional daemon-specific setup      // ...  
    // Daemon-specific code goes here      // ...  
    // Never returns      exit(EXIT_SUCCESS);  }  
int main() {      // Open the syslog      openlog("daemon_example", LOG_PID | LOG_CONS, LOG_USER);  
    // Daemonize      daemonize();  
    // Log a message to syslog      syslog(LOG_INFO, "Daemon started by user %d", getuid());  
    // Daemon-specific code goes here      // ...  
    // Close the syslog      closelog();  
    // Never returns      return 0;  }

在这个示例中,daemonize函数负责将当前进程转换为一个守护进程。它首先通过fork()创建一个子进程,然后让父进程退出。子进程调用setsid()创建一个新的会话并成为该会话的领头进程,这使得它脱离了控制终端。然后,它改变工作目录到根目录,改变文件权限掩码,并关闭标准文件描述符。最后,它将标准文件描述符重定向到/dev/null。

在main函数中,程序首先通过openlog()打开syslog,然后调用daemonize()函数将当前进程转换为守护进程。接着,它使用syslog()函数向syslog记录一条消息,表明守护进程已经启动。最后,它关闭syslog并退出。

五、守护进程的优点

守护进程在Linux系统中具有许多优点:

提供后台服务:守护进程可以在后台运行,提供系统或用户所需的服务,如网络服务、数据库服务等。

独立于控制终端:守护进程独立于控制终端,不会占用终端资源,也不会受到终端关闭的影响。

节省系统资源:守护进程通常占用较少的系统资源,因为它们不需要与用户交互,也不需要显示输出。

提高系统安全性:通过将服务运行在守护进程中,可以限制它们对系统资源的访问,从而提高系统的安全性。

易于管理:Linux系统提供了许多工具来管理守护进程,如systemctl、service等,使得守护进程的管理变得容易。

六、守护进程的缺点

尽管守护进程具有许多优点,但它们也存在一些缺点:

难以调试:由于守护进程在后台运行,没有与用户交互的界面,因此难以进行调试和故障排除。

潜在的安全风险:如果守护进程存在安全漏洞,它们可能会被恶意用户利用来攻击系统。

资源占用:尽管守护进程通常占用较少的系统资源,但在某些情况下,它们可能会消耗大量的CPU、内存或磁盘空间,从而影响系统的性能。

七、守护进程的管理

在Linux系统中,可以使用多种工具来管理守护进程:

systemctl:systemctl是systemd的命令行工具,用于管理系统和服务。它可以用来启动、停止、重启、启用、禁用和检查守护进程的状态。

service:service是一个用于启动、停止、重启和检查系统服务的脚本。尽管它已经被systemctl取代,但在一些旧版本的Linux系统中仍然可以使用。

init.d脚本:在基于SysVinit的系统中,可以使用/etc/init.d/目录下的脚本来管理守护进程。这些脚本通常提供了start、stop、restart、status等选项来控制系统服务的状态。

crontab和at:虽然crontab和at主要用于定时任务调度,但它们也可以用来启动和管理守护进程。通过将它们配置为在系统启动时运行或在特定时间运行,可以确保守护进程在需要时启动。

配置文件:许多守护进程都使用配置文件来指定它们的运行参数和行为。通过编辑这些配置文件,可以更改守护进程的默认设置,以满足特定的需求。

八、常见的守护进程

在Linux系统中,有许多常见的守护进程,它们提供了各种系统服务和功能。以下是一些常见的守护进程及其功能:

sshd:安全外壳(SSH)守护进程,用于提供远程登录和文件传输服务。

httpd/apache2:Apache HTTP服务器守护进程,用于提供Web服务。

mysqld/mariadb:MySQL或MariaDB数据库服务器守护进程,用于提供数据库服务。

postfix/sendmail:邮件传输代理(MTA)守护进程,用于发送和接收电子邮件。

cron:计划任务守护进程,用于在特定时间执行指定的命令或脚本。

syslogd/rsyslogd:系统日志守护进程,用于收集、处理和存储系统日志消息。

ftpd:文件传输协议(FTP)守护进程,允许用户通过FTP协议在远程计算机和本地计算机之间传输文件。

ntpd:网络时间协议(NTP)守护进程,用于同步网络中计算机的系统时钟。

这些守护进程在Linux系统中扮演着重要的角色,为系统提供了各种服务和功能。了解这些守护进程的工作原理和管理方法对于维护Linux系统的稳定性和安全性至关重要。