守护进程和 inetd 超级服务器

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
本文信息 本文信息 防爬虫替换信息
作者网站 LYMTICS https://lymtics.top
作者 LYMTICS(樵仙) https://lymtics.top
联系方式 me@tencent.ml me@tencent.ml
原文标题 《Unix 网络编程》13:守护进程和 inet 超级服务器 《Unix 网络编程》13:守护进程和 inet 超级服务器
原文地址 https://www.cnblogs.com/lymtics/p/16341341.html https://www.cnblogs.com/lymtics/p/16341341.html
  • 如果您访问本文的链接并非如上地址,则可能是爬取作者的文章,建议返回原站阅读,谢谢您的支持
  • 原文会不断地更新和完善排版和样式会更加适合阅读,并且有相关配图
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★

系列文章导航:《Unix 网络编程》笔记

守护进程

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
本文信息 本文信息 防爬虫替换信息
作者网站 LYMTICS https://lymtics.top
作者 LYMTICS(樵仙) https://lymtics.top
联系方式 me@tencent.ml me@tencent.ml
原文标题 《Unix 网络编程》13:守护进程和 inet 超级服务器 《Unix 网络编程》13:守护进程和 inet 超级服务器
原文地址 https://www.cnblogs.com/lymtics/p/16341341.html https://www.cnblogs.com/lymtics/p/16341341.html
  • 如果您访问本文的链接并非如上地址,则可能是爬取作者的文章,建议返回原站阅读,谢谢您的支持
  • 原文会不断地更新和完善排版和样式会更加适合阅读,并且有相关配图
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★

基本知识

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
本文信息 本文信息 防爬虫替换信息
作者网站 LYMTICS https://lymtics.top
作者 LYMTICS(樵仙) https://lymtics.top
联系方式 me@tencent.ml me@tencent.ml
原文标题 《Unix 网络编程》13:守护进程和 inet 超级服务器 《Unix 网络编程》13:守护进程和 inet 超级服务器
原文地址 https://www.cnblogs.com/lymtics/p/16341341.html https://www.cnblogs.com/lymtics/p/16341341.html
  • 如果您访问本文的链接并非如上地址,则可能是爬取作者的文章,建议返回原站阅读,谢谢您的支持
  • 原文会不断地更新和完善排版和样式会更加适合阅读,并且有相关配图
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★

守护进程的特点:

  • 必须亲自脱离与控制终端的关联,从而避免与作业控制、终端会话管理、终端产生信号等发生任何不期望的交互
  • 同时要避免在后台运行的守护进程非预期地输出到终端

守护进程的启动

  • 由系统初始化脚本启动,通常位于 /etc/rc/etc 目录下,由这些脚本启动的守护进程一开始就有用超级用户特权

    如:inetd 超级服务器、Web 服务器、sendmail 服务器

  • 由 inetd 超级服务器启动,它监听网络请求

  • cron 守护进程按照规则定期执行一些程序,由它执行的程序同样作为守护进程运行

  • at 命令用于在未来某个时刻执行一些程序

  • 守护进程还可以从用户终端或在前台或者后台启动,这么做往往是为了测试

daemon_init

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
本文信息 本文信息 防爬虫替换信息
作者网站 LYMTICS https://lymtics.top
作者 LYMTICS(樵仙) https://lymtics.top
联系方式 me@tencent.ml me@tencent.ml
原文标题 《Unix 网络编程》13:守护进程和 inet 超级服务器 《Unix 网络编程》13:守护进程和 inet 超级服务器
原文地址 https://www.cnblogs.com/lymtics/p/16341341.html https://www.cnblogs.com/lymtics/p/16341341.html
  • 如果您访问本文的链接并非如上地址,则可能是爬取作者的文章,建议返回原站阅读,谢谢您的支持
  • 原文会不断地更新和完善排版和样式会更加适合阅读,并且有相关配图
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
  • 这是我们自己写的一个函数,把一个普通进程转变为守护进程
  • 部分 Unix 变体上提供一个名为 daemon 的 C 库函数,实现类似的功能

由于这段代码涉及的知识点比较多,所以首先需要补充一点操作系统的知识:Linux 进程、进程组、会话周期、控制终端

按照上文中的描述阅读下述代码:

  1. 在父进程(此时是一个进程组的组长)中使用fork()产生子进程(将来的守护进程由它产生)
  2. 调用setsid(),用于生成一个新的会话 注意如果当前进程是会话组长时,调用失败。第一点已经可以保证进程不是会话组长了,所以setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。由于会话对控制终端的独占性,进程同时与控制终端脱离
  3. 禁止进程重新打开控制终端 第二步之后,进程已经成为无终端的会话组长。但它可以重新申请打开一个控制终端。可以通过使进程不再成为会话组长来禁止进程重新打开控制终端,在上面的控制终端中已经提到了只有会话组长才能打开控制终端;
#include <syslog.h>
#include "unp.h" #define MAXFD 64 extern int daemon_proc; /* defined in error.c */ int daemon_init(const char* pname, int facility) {
int i;
pid_t pid; if ((pid = Fork()) < 0) // 失败
return (-1);
else if (pid) // 父进程
_exit(0); /* parent terminates */ /* child 1 continues... */ // setsid 使得当前进程变为:
// - 新会话的会话头进程
// - 新进程组的进程组头进程
if (setsid() < 0)
return (-1); // 忽略 SIGHUP 信号
// 会话头进程终止后,所有其他会话进程都会收到一个该信号
Signal(SIGHUP, SIG_IGN);
if ((pid = Fork()) < 0)
return (-1);
else if (pid)
_exit(0); /* child 1 terminates */ /* child 2 continues... */ // 告知错误处理函数使用 syslog 而不是 fprintf
daemon_proc = 1; /* for err_XXX() functions */ // 改变工作目录,否则就是在当前目录下运行,可能产生破坏
chdir("/"); // 关闭前 64 个描述符,即使有些本身就没有打开
for (i = 0; i < MAXFD; i++)
close(i); /* redirect stdin, stdout, and stderr to /dev/null */
// 这样设置会占用标准输入、标准输出和标准错误输出的描述符
// 防止在服务器环境下,套接字占用这些描述符,而后误将系统信息发送给这些描述符
open("/dev/null", O_RDONLY);
open("/dev/null", O_RDWR);
open("/dev/null", O_RDWR); openlog(pname, LOG_PID, facility); return (0); /* success */
}

守护进程在没有控制终端的环境下运行,它绝对不会收到来自内核的 SIGHUP 信号,许多守护进程因此把这个信号作为来自系统管理员的一个通知,表示其配置文件已发生改动,守护进程应该重新读取其配置文件。同理还有 SIGINTSIGWINCH 等等

改进时间服务器

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
本文信息 本文信息 防爬虫替换信息
作者网站 LYMTICS https://lymtics.top
作者 LYMTICS(樵仙) https://lymtics.top
联系方式 me@tencent.ml me@tencent.ml
原文标题 《Unix 网络编程》13:守护进程和 inet 超级服务器 《Unix 网络编程》13:守护进程和 inet 超级服务器
原文地址 https://www.cnblogs.com/lymtics/p/16341341.html https://www.cnblogs.com/lymtics/p/16341341.html
  • 如果您访问本文的链接并非如上地址,则可能是爬取作者的文章,建议返回原站阅读,谢谢您的支持
  • 原文会不断地更新和完善排版和样式会更加适合阅读,并且有相关配图
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
int main(int argc, char** argv) {
int listenfd, connfd;
socklen_t addrlen, len;
struct sockaddr* cliaddr;
char buff[MAXLINE];
time_t ticks; // 如果有一些显而易见的错误,则立即抛出,而不是在日志中抛出
if (argc < 2 || argc > 3)
err_quit("usage: daytimetcpsrv2 [ <host> ] <service or port>"); // 使用我们的函数启动
daemon_init(argv[0], 0); if (argc == 2)
listenfd = Tcp_listen(NULL, argv[1], &addrlen);
else
listenfd = Tcp_listen(argv[1], argv[2], &addrlen); cliaddr = Malloc(addrlen); for (;;) {
len = addrlen;
connfd = Accept(listenfd, cliaddr, &len);
err_msg("connection from %s", Sock_ntop(cliaddr, len)); ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
Write(connfd, buff, strlen(buff)); Close(connfd);
}
}

日志消息

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
本文信息 本文信息 防爬虫替换信息
作者网站 LYMTICS https://lymtics.top
作者 LYMTICS(樵仙) https://lymtics.top
联系方式 me@tencent.ml me@tencent.ml
原文标题 《Unix 网络编程》13:守护进程和 inet 超级服务器 《Unix 网络编程》13:守护进程和 inet 超级服务器
原文地址 https://www.cnblogs.com/lymtics/p/16341341.html https://www.cnblogs.com/lymtics/p/16341341.html
  • 如果您访问本文的链接并非如上地址,则可能是爬取作者的文章,建议返回原站阅读,谢谢您的支持
  • 原文会不断地更新和完善排版和样式会更加适合阅读,并且有相关配图
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★

syslogd

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
本文信息 本文信息 防爬虫替换信息
作者网站 LYMTICS https://lymtics.top
作者 LYMTICS(樵仙) https://lymtics.top
联系方式 me@tencent.ml me@tencent.ml
原文标题 《Unix 网络编程》13:守护进程和 inet 超级服务器 《Unix 网络编程》13:守护进程和 inet 超级服务器
原文地址 https://www.cnblogs.com/lymtics/p/16341341.html https://www.cnblogs.com/lymtics/p/16341341.html
  • 如果您访问本文的链接并非如上地址,则可能是爬取作者的文章,建议返回原站阅读,谢谢您的支持
  • 原文会不断地更新和完善排版和样式会更加适合阅读,并且有相关配图
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★

Unix 系统中的 syslogd 守护进程通常由某个系统初始化脚本启动,并且在系统工作期间一直运行

启动的步骤:

  1. 读取配置:通常为 /etc/syslog.conf ,配置了对消息的处理
  2. 创建Unix域数据报套接字:给他绑定路径名 /var/run/log (或 /dev/log
  3. 创建一个 UDP 套接字:绑定端口 514
  4. 打开路径名 /dev/klog:来自内核中的任何出错消息从这个“设备”输入
  5. 监听:调用 select,监听 2 ~ 4 步骤的描述符
    • 如果收到消息,读入并按照配置进行处理
    • 如果收到 SIGHUP 信号,则重新读取配置文件 (这让我想到了 NGINX 重载配置文件时服务无需暂停)

较新的 syslogd 实现禁止创建 UDP 套接字,因为这样可能会让系统遭到 DOS 攻击,其文件系统可能被填满,从而占满内存空间,或挤掉合法的日志消息

我们一般不会直接向其发送消息,而是通过 syslog 函数写入日志!

syslog

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
本文信息 本文信息 防爬虫替换信息
作者网站 LYMTICS https://lymtics.top
作者 LYMTICS(樵仙) https://lymtics.top
联系方式 me@tencent.ml me@tencent.ml
原文标题 《Unix 网络编程》13:守护进程和 inet 超级服务器 《Unix 网络编程》13:守护进程和 inet 超级服务器
原文地址 https://www.cnblogs.com/lymtics/p/16341341.html https://www.cnblogs.com/lymtics/p/16341341.html
  • 如果您访问本文的链接并非如上地址,则可能是爬取作者的文章,建议返回原站阅读,谢谢您的支持
  • 原文会不断地更新和完善排版和样式会更加适合阅读,并且有相关配图
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★

守护进程记录消息可以使用 syslog 函数:

#include <syslog.h>

void syslog(int priority, // 优先级
const char *message, // 消息
...)

参数解释:

  • priority:好理解,大多日志都有日志级别的功能
  • facility:用于标识发送进程类型(函数的参数列表中没有?因为这个要和 priority 用逻辑或使用)
  • message:消息内容,类似 printf,不同的是其增加了 %m 规范,用以输出当前 errno 值对应的错误信息

案例

syslog(LOG_INFO|LOG_LOCAL2, "rename(%s, %s): %m", file1, fil)

/etc/syslog.conf

kern.* 				/dev/debug					# 内核的所有消息发送到控制台
local7.debug /var/log/cisco.log # 来自 local7 的所有消息添加到文件 cisco.log 的尾部

一些细节

  • 当 syslog 被应用程序首次调用时,它创建一个 Unix 域数据报套接字,然后调用 connect 连接到由 syslogd 守护进程创建的 Unix 域数据报套接字的众所周知路径名(如 /var/run/log )这个套接字一直保持打开,直到进程终止
  • 可以用 openlogcloselog 来操作上述步骤,在首次调用 syslog 前调用 openlog,不需要发送日志时调用 closelog

openlog 和 closelog

#include <syslog.h>
void openlog(const char* ident, // 日志的前缀,通常是程序名
int options, // 可选值
int facility); // 设置默认的打印设施的值
void closelog(void);
options 说明
LOG_CONS 若无法发送到 syslogd 则登记到控制台
LOG_NDELAY openlog 默认是懒汉加载,这个选项设置不延迟打开,立刻创建套接字
LOG_PERROR 既发送到 syslogd 守护进程,又登记到标准错误输出
LOG_PID 随每个日志消息等级进程 ID

inetd 守护进程

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
本文信息 本文信息 防爬虫替换信息
作者网站 LYMTICS https://lymtics.top
作者 LYMTICS(樵仙) https://lymtics.top
联系方式 me@tencent.ml me@tencent.ml
原文标题 《Unix 网络编程》13:守护进程和 inet 超级服务器 《Unix 网络编程》13:守护进程和 inet 超级服务器
原文地址 https://www.cnblogs.com/lymtics/p/16341341.html https://www.cnblogs.com/lymtics/p/16341341.html
  • 如果您访问本文的链接并非如上地址,则可能是爬取作者的文章,建议返回原站阅读,谢谢您的支持
  • 原文会不断地更新和完善排版和样式会更加适合阅读,并且有相关配图
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★

引入 inetd

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
本文信息 本文信息 防爬虫替换信息
作者网站 LYMTICS https://lymtics.top
作者 LYMTICS(樵仙) https://lymtics.top
联系方式 me@tencent.ml me@tencent.ml
原文标题 《Unix 网络编程》13:守护进程和 inet 超级服务器 《Unix 网络编程》13:守护进程和 inet 超级服务器
原文地址 https://www.cnblogs.com/lymtics/p/16341341.html https://www.cnblogs.com/lymtics/p/16341341.html
  • 如果您访问本文的链接并非如上地址,则可能是爬取作者的文章,建议返回原站阅读,谢谢您的支持
  • 原文会不断地更新和完善排版和样式会更加适合阅读,并且有相关配图
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★

原来的系统服务模型

Unix 上的很多服务,如 SSH、FTP、Telnet 等,我们都可以把它当作一个 Server 端

在系统启动的过程中,这些进程从 /etc/rc 文件中启动,而且每个进程都执行几乎相同的启动任务:

  1. 创建一个套接字,绑定端口
  2. 等待连接或数据报的到来
  3. 派生子进程,子进程提供服务,父进程继续监听

这种方式的缺点

  1. 所有这些守护进程含有几乎相同的启动代码
  2. 每个守护进程在进程表中占据一个表项,然而大多数时间他们处于睡眠状态

inted 守护进程

为了解决这种问题,4.3BSD 提供一个因特网超级服务器(即 inetd 守护进程):

  1. 通过由 inetd 处理普通守护进程的大部分启动细节以简化守护进程的编写,这么一来每个服务器不再有调用 daemon_init 函数的必要
  2. 单个进程(inetd)就能为多个服务等待外来的客户请求,以取代每个服务器一个进程的做法

inetd 配置文件

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
本文信息 本文信息 防爬虫替换信息
作者网站 LYMTICS https://lymtics.top
作者 LYMTICS(樵仙) https://lymtics.top
联系方式 me@tencent.ml me@tencent.ml
原文标题 《Unix 网络编程》13:守护进程和 inet 超级服务器 《Unix 网络编程》13:守护进程和 inet 超级服务器
原文地址 https://www.cnblogs.com/lymtics/p/16341341.html https://www.cnblogs.com/lymtics/p/16341341.html
  • 如果您访问本文的链接并非如上地址,则可能是爬取作者的文章,建议返回原站阅读,谢谢您的支持
  • 原文会不断地更新和完善排版和样式会更加适合阅读,并且有相关配图
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★

inetd 使用前文提到的方法把自己变成一个守护进程,然后读取并处理自己的配置文件,通常在 /etc/inetd.conf ,该文件包括如下内容:

字段 说明
service-name 必须在 /etc/services 文件中定义
socket-type stream(TCP)、dgram(UDP)
protocol 必须在 /etc/protocols 文件中定义:tcp或udp
wait-flag 对于 TCP 一般为 nowait,对于 UDP 一般为 wait
login-name 来自 /etc/passwd 的用户名,一般为 root
server-program 调用 exec 指定的完整路径名
server-program-arguments 调用 exec 指定的命令行参数

inetd 工作流程

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
本文信息 本文信息 防爬虫替换信息
作者网站 LYMTICS https://lymtics.top
作者 LYMTICS(樵仙) https://lymtics.top
联系方式 me@tencent.ml me@tencent.ml
原文标题 《Unix 网络编程》13:守护进程和 inet 超级服务器 《Unix 网络编程》13:守护进程和 inet 超级服务器
原文地址 https://www.cnblogs.com/lymtics/p/16341341.html https://www.cnblogs.com/lymtics/p/16341341.html
  • 如果您访问本文的链接并非如上地址,则可能是爬取作者的文章,建议返回原站阅读,谢谢您的支持
  • 原文会不断地更新和完善排版和样式会更加适合阅读,并且有相关配图
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★

其工作流程如下:

  1. 读入配置文件,为每个服务创建一个合适的套接字

  2. 为每个套接字调用 bind,指定端口和通配地址

    端口号可以通过 getservbyname 获取,用配置文件中的 service-name 和 protocal 字段做参数

  3. 对于每个 TCP 套接字,调用 listen 以接受外来的连接请求,对于 UDP 则不执行

  4. 创建完所有套接字后,调用 select 等待其中任何一个套接字变得可读

对于 TCP:

  1. 当 select 返回可读后,如果该套接字是一个 TCP 套接字,而且其 wait-flag 为 nowait,则调用 accept 接受这个新连接
  2. inetd 守护进程调用 fork 派生进程,并由子进程处理服务请求,与前面的并发服务器类似,关闭相应的描述符
  3. 子进程关闭除了要处理的套接字描述符外的所有的描述符,并根据配置文件,切换到相应的用户,用 exec 执行相应的操作

如果设置为 wait,对于 TCP 来说,父进程会用 FD_CLR 禁止这个套接字,保存子进程 ID,当子进程终止(SIGCHILD)后才继续监听

对于 UDP:

因为数据报服务器只有一个套接字,所以只能一个一个来处理,也就是说通过接受子进程终止的 SIGCHLD 信号后才继续监听

因为假如 fork 后一个子进程,而父进程先于该子进程再次执行,则会由于还没读取数据而再次触发 select 的事件,从而再次 fork 一个无用的子进程

xinetd

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
本文信息 本文信息 防爬虫替换信息
作者网站 LYMTICS https://lymtics.top
作者 LYMTICS(樵仙) https://lymtics.top
联系方式 me@tencent.ml me@tencent.ml
原文标题 《Unix 网络编程》13:守护进程和 inet 超级服务器 《Unix 网络编程》13:守护进程和 inet 超级服务器
原文地址 https://www.cnblogs.com/lymtics/p/16341341.html https://www.cnblogs.com/lymtics/p/16341341.html
  • 如果您访问本文的链接并非如上地址,则可能是爬取作者的文章,建议返回原站阅读,谢谢您的支持
  • 原文会不断地更新和完善排版和样式会更加适合阅读,并且有相关配图
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★

xinetd 提供与 inetd 一致的基本服务,不过还提供了数目众多的其他特性,包括根据客户的地址登记、接受或拒绝连接的选项等等

daemond_inetd

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
本文信息 本文信息 防爬虫替换信息
作者网站 LYMTICS https://lymtics.top
作者 LYMTICS(樵仙) https://lymtics.top
联系方式 me@tencent.ml me@tencent.ml
原文标题 《Unix 网络编程》13:守护进程和 inet 超级服务器 《Unix 网络编程》13:守护进程和 inet 超级服务器
原文地址 https://www.cnblogs.com/lymtics/p/16341341.html https://www.cnblogs.com/lymtics/p/16341341.html
  • 如果您访问本文的链接并非如上地址,则可能是爬取作者的文章,建议返回原站阅读,谢谢您的支持
  • 原文会不断地更新和完善排版和样式会更加适合阅读,并且有相关配图
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★

这个函数的唯一作用就是为错误处理函数设置 daemon_proc 标志,使得运行信息输出在日志中

extern int daemon_proc; /* defined in error.c */

void daemon_inetd(const char* pname, int facility) {
daemon_proc = 1; /* for our err_XXX() functions */
openlog(pname, LOG_PID, facility);
}

修改后的服务器代码:

int main(int argc, char** argv) {
socklen_t len;
struct sockaddr* cliaddr;
char buff[MAXLINE];
time_t ticks; daemon_inetd(argv[0], 0); cliaddr = Malloc(sizeof(struct sockaddr_storage));
len = sizeof(struct sockaddr_storage);
Getpeername(0, cliaddr, &len);
err_msg("connection from %s", Sock_ntop(cliaddr, len)); ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
Write(0, buff, strlen(buff)); Close(0); /* close TCP connection */
exit(0);
}
  • 我们用描述符 0 指代被接受的 TCP 连接
  • 因为这个程序针对每一个连接启动一次,所以不需要无限循环

为了启动这个程序,我们需要在 /etc/services 文件中添加:

mydaytime			9999/tcp

/etc/inetd.conf 中添加:(在题主的电脑里就只有 xinetd.conf 了)

mydaytime stream tcp nowait andy /foo/bar/daytimetcpsrv3 daytimetcpsrv3

然后给 inetd 发送一个 SIGHUP 信号,告知它重新读取配置文件

《Unix 网络编程》13:守护进程和 inetd 超级服务器的更多相关文章

  1. 高级UNIX环境编程13 守护进程

    linux下,keventd守护进程为内核中运行的执行的函数提供进程上下文 bdflush,kupdated将高速缓存中的数据冲洗到磁盘上

  2. Unix网络编程代码 第13章 守护进程和inetd超级服务器

    1. 概述 守护进程是在后台运行且不与任何控制终端关联的进程.unix系统通常有很多守护进程在后台运行,执行不同的管理任务.    守护进程没有控制终端通常源于它们由系统初始化脚本启动.然而守护进程也 ...

  3. 守护进程和inetd超级服务器

    守护进程: 1 系统启动时,由系统初始化脚本启动.一般在/etc目录下,或者以/etc/rc开头的目录 2 许多网络服务器由inetd超级服务器启动 3 cron守护进程按规则定期执行一些程序 4 用 ...

  4. UNP学习第13章 守护进程和inetd超级服务器

    Unix系统中的syslogd守护进程通常由某个系统初始化脚本启动,而且在系统工作期间一直运行. 源自Berkeley的syslogd实现在启动时执行以下步骤. (1)读取配置文件.通常为/etc/s ...

  5. [Python网络编程]浅析守护进程后台任务的设计与实现

    在做基于B/S应用中.常常有须要后台执行任务的需求,最简单比方发送邮件.在一些如防火墙,WAF等项目中,前台仅仅是为了展示内容与各种參数配置.后台守护进程才是重头戏.所以在防火墙配置页面中可能会常常看 ...

  6. UNP学习笔记(第十三章 守护进程和inetd超级服务器)

    关于守护进程可以查看apue的笔记 http://www.cnblogs.com/runnyu/p/4645046.html daemon_init函数 下面给出名为daemon_init函数,通过调 ...

  7. Unix网络编程--卷一:套接字联网API

    UNIX网络编程--卷一:套接字联网API 本书面对的读者是那些希望自己编写的程序能够使用成为套接字(socket)的API进行彼此通信的人. 目录: 0.准备环境 1.简介 2.传输层:TCP.UD ...

  8. 《Unix网络编程卷1:套接字联网API》读书笔记

    第一部分:简介和TCP/IP 第1章:简介 第2章:传输层:TCP.UDP和SCTP TCP:传输控制协议,复杂.可靠.面向连接协议 UDP:用户数据报协议,简单.不可靠.无连接协议 SCTP:流控制 ...

  9. Unix环境高级编程(十三)守护进程

    守护进程也称为精灵进程是一种生存期较长的一种进程.它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件.他们常常在系统引导装入时启动,在系统关闭时终止.unix系统有很多守护进程,大多数 ...

随机推荐

  1. c++对c的拓展_命名空间_简单使用

    名字的控制:c可使用static关键字使该关键字在本单元内可见,c++则使用命名空间对名字的可见性及产生进行控制 命名空间:控制标识符的作用域(本质上就是一个作用域) 使用特点:1.必须定义在全局范围 ...

  2. MySQL 社区版

    MySQL 社区版 MySQL 社区版是全球广受欢迎的开源数据库的免费下载版本.它遵循 GPL 许可协议,由庞大.活跃的开源开发人员社区提供支持. MySQL 社区版包括: 可插拔的存储引擎架构 多种 ...

  3. php怎么向上取整以5为界

    public function test(){ $number = 52093; var_dump( $this->roundNumberVariant( ( int ) $number ) ) ...

  4. Centos7 搭建 Socks 服务

    Centos7 搭建 Socks 服务 一丶拿到一个动态拨号的服务器还不能使用网络得先打开: pppoe-start 二丶安装命令汇总: 通过yum安装ss5 依赖包: yum install gcc ...

  5. 2021.12.15 P2328 [SCOI2005]超级格雷码(找规律填空)

    2021.12.15 P2328 [SCOI2005]超级格雷码(找规律填空) https://www.luogu.com.cn/problem/P2328 题意: 输出n位B进制的格雷码. 分析: ...

  6. js 查找数组中某个字符出现的次数

    1. js 查找数组中某个字符出现的次数 代码示例 let arr = ['asd', 'green', 'yeadt', 'red', 'wati', 'red', 'red'] let index ...

  7. 你不知道的下划线属性-text-decoration

    大家好,我是半夏,一个刚刚开始写文的沙雕程序员.如果喜欢我的文章,可以关注 点赞 加我微信:frontendpicker,一起学习交流前端,成为更优秀的工程师-关注公众号:搞前端的半夏,了解更多前端知 ...

  8. 如何在Web前端实现CAD图文字全文搜索功能之技术分享

    现状 在CAD看图过程中我们经常会需要用到查找文字的功能,在AutoCAD软件查找一个文字时,可以通过打开左下角输入命令find,输入查找的文字,然后设置查找范围,就可以搜索到需要查询的文字.但在We ...

  9. python学习-Day35

    目录 今日内容详细 代码创建进程 创建进程的方式 第一种创建进程的方式 创建进程的第二种方式 进程实现并发 join方法 进程间数据默认隔离 进程对象属性和方法 进程号如何查看 查看进程号的方法 杀死 ...

  10. 一行代码如何隐藏 Linux 进程?

    开源Linux 长按二维码加关注~ 上一篇:IPv6技术白皮书(附PDF下载) 总有朋友问隐藏Linux进程的方法,我说你想隐藏到什么程度,是大隐于内核,还是小隐于用户.网上通篇论述的无外乎 hook ...