关于守护进程可以查看apue的笔记 http://www.cnblogs.com/runnyu/p/4645046.html

daemon_init函数

下面给出名为daemon_init函数,通过调用它(通常从服务器程序中),我们能够把一个普通进程转变为守护进程

 #include    "unp.h"
#include <syslog.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()) < )
return (-);
else if (pid)
_exit(); /* parent terminates */ /* child 1 continues... */ if (setsid() < ) /* become session leader */
return (-); Signal(SIGHUP, SIG_IGN);
if ( (pid = Fork()) < )
return (-);
else if (pid)
_exit(); /* child 1 terminates */ /* child 2 continues... */ daemon_proc = ; /* for err_XXX() functions */ chdir("/"); /* change working directory */ /* close off file descriptors */
for (i = ; 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 (); /* success */
}

作为守护进程运行的时间获取服务器程序

 #include    "unp.h"
#include <time.h> int
main(int argc, char **argv)
{
int listenfd, connfd;
socklen_t addrlen, len;
struct sockaddr *cliaddr;
char buff[MAXLINE];
time_t ticks; if (argc < || argc > )
err_quit("usage: daytimetcpsrv2 [ <host> ] <service or port>"); daemon_init(argv[], ); if (argc == )
listenfd = Tcp_listen(NULL, argv[], &addrlen);
else
listenfd = Tcp_listen(argv[], argv[], &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);
}
}

inetd守护进程

典型的UNIX系统可能存在许多服务器,它们只是等待客户请求的到达,例如:FTP、Telnet、Rlogin、TFTP等等。

在之前,所有这些服务都有一个进程与之关联,而且每个进程执行几乎相同的启动任务。这个模型存在以下两个问题:

1.所有这些守护进程含有几乎相同的启动代码。

2.每个守护进程在进程表中占据一个表项,然后它们大部分时间处于睡眠状态。

4.3BSD版本基于TCP或UDP的服务器都可以使用inetd守护进程来解决上述两个问题:

1.通过由inetd处理普通守护进程的大部分启动细节以简化守护进程的编写。

2.单个进程(inetd)就能为多个服务等待外来的客户请求,以此取代每个服务一个进程的做法。

inetd进程使用我们随daemon_init函数讲解的技巧把自己演变成一个守护进程。

接着读入并处理自己的配置文件。通常是/etc/inetd.conf的配置文件制定本超级服务器处理哪些服务以及当一个服务请求到达时该怎么做。该文件中每行包含的字段如下图所示:

下面是inetd.conf文件中作为例子的若干行:

下面展示inetd守护进程的工作流程

1.在启动阶段,读入/etc/inetd.conf文件并给该文件中指定的每个服务创建一个适当类型的套接字。新创建的每个套接字都被加入到将由某个select调用使用的一个描述符。

2.位每个套接字调用bind,指定捆绑相应服务器的总所周知的端口和通配地址。端口号通过getservbyname获得。

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

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

5.当select返回指出某个套接字可读之后,如果该套接字时一个TCP套接字,而且其服务器的wait-flag值为nowait,那么调用accept接受这个新连接。

6.inetd守护进程调用fork派生进程,并由子进程处理服务请求。(子进程首先与终端脱离,然后调用exec执行相应的server-program字段指定的程序来具体处理请求)

7.如果第五步中select返回的是一个字节流套接字,那么父进程必须关闭已连接套接字(就像标准并发服务器那样)。父进程再次调用select,等待下一个变为可读的套接字。

daemon_inetd函数

下面给出一个名为daemon_inetd的函数,可用于已知由inetd启动的服务器程序中。

 #include    "unp.h"
#include <syslog.h> extern int daemon_proc; /* defined in error.c */ void
daemon_inetd(const char *pname, int facility)
{
daemon_proc = ; /* for our err_XXX() functions */
openlog(pname, LOG_PID, facility);
}

与daemon_init相比,所有的守护进程化步骤已由inetd在启动时执行。本函数的任务仅仅是为错误处理函数设置daemon_proc标志,并调用openlog

下面给出由inetd作为守护进程启动的时间获取服务器程序

 #include    "unp.h"
#include <time.h> int
main(int argc, char **argv)
{
socklen_t len;
struct sockaddr *cliaddr;
char buff[MAXLINE];
time_t ticks; daemon_inetd(argv[], ); cliaddr = Malloc(sizeof(struct sockaddr_storage));
len = sizeof(struct sockaddr_storage);
Getpeername(, cliaddr, &len);
err_msg("connection from %s", Sock_ntop(cliaddr, len)); ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
Write(, buff, strlen(buff)); Close(); /* close TCP connection */
exit();
}

可以看到,所有套接字创建代码都消失了。这些步骤改由inetd执行。

为了运行本例子的程序,我们首先赋予本服务一个名字和端口,将如下行加到/etc/services文件中:

mydaytime     /tcp

接着把如下行加到/etc/inetd.conf文件中:

mydaytime stream tcp nowait andy /home/andy/daytimetcpsrv3 daytimetcpsrv3

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

接着我们执行netstat命令验证inetd已在TCP端口9999上创建一个监听套接字

UNP学习笔记(第十三章 守护进程和inetd超级服务器)的更多相关文章

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

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

  2. 《APUE》读书笔记第十三章-守护进程

    守护进程 守护进程是生存期较长的一种进程,它们常常在系统自举时启动,仅在系统关闭时才终止.因为它们没有控制终端,所以说它们是在后台运行的.UNIX系统由很多守护进程,它们执行日常事务活动. 本章主要介 ...

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

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

  4. 《Unix 网络编程》13:守护进程和 inetd 超级服务器

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

  5. APUE读书笔记-第13章-守护进程

    第13章 守护进程 13.1 引言 *守护进程也称精灵进程(daemon)是生存期较长的一种进程.它们常常在系统自举时启动,仅在系统关闭时才终止.因为它们没有控制终端,所以说它们是在后台运行的.UNI ...

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

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

  7. apue学习笔记(第十三章 守护进程)

    本章将说明守护进程结构,以及如何编写守护进程程序. 守护进程,也就是通常说的Daemon进程,是Unix中的后台服务进程.它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理 ...

  8. 《Unix环境高级编程》读书笔记 第13章-守护进程

    1. 引言 守护进程是生存期长的一种进程.它们常常在系统引导装入时启动,仅在系统关闭时才终止.它们没有控制终端,在后台运行. 本章说明守护进程结构.如何编写守护进程程序.守护进程如何报告出错情况. 2 ...

  9. Linux学习笔记(9)-守护进程

    明天学这个!! ---------------------------------------------------------- 守护进程(Daemon)是运行在后台的一种特殊进程.它独立于控制终 ...

随机推荐

  1. vue - computed

    computed 的作用主要是对原数据进行改造输出.改造输出:包括格式的编辑,大小写转换,顺序重排,添加符号……. 一.格式化输出结果: 我们先来做个读出价格的例子:我们读书的原始数据是price:1 ...

  2. 洛谷P3832 [NOI2017]蚯蚓排队 【链表 + 字符串hash】

    题目链接 洛谷P3832 题解 字符串哈希然后丢到hash表里边查询即可 因为\(k \le 50\),1.2操作就暴力维护一下 经复杂度分析会发现直接这样暴力维护是对的 一开始自然溢出WA了,还以为 ...

  3. jsp导出table数据excel表

    <html> <head> <meta http-equiv="content-Type" content="text/html;chars ...

  4. mysql安装配置、主从复制配置详解【转】

    仅限 centos7以下 版本 #yum install mysql #yum install mysql-server #yum install mysql-devel 启动服务 [root@loc ...

  5. 洛谷 P1653 == COGS 2043 猴子

    P2107 可爱的猴子 时间限制:1000MS  空间限制:65535KB 问题描述: 树上有n只猴子.它们编号为 1 到n.1 号猴子用它的尾巴勾着树枝.剩下的猴子都被其他的猴子用手抓着.每只猴子的 ...

  6. C#.NET中使用存储过程的方法及其优点

    原文发布时间为:2008-09-26 -- 来源于本人的百度文章 [由搬家工具导入] 一.使用存储过程的优点    作为服务器端的代码,存储过程具有以下优点:1) 存储过程是预先编译过的,是执行查询或 ...

  7. hdu 1403 Longest Common Substring 后缀数组 模板题

    题目链接 题意 问两个字符串的最长公共子串. 思路 加一个特殊字符然后拼接起来,求得后缀数组与\(height\)数组.扫描一遍即得答案,注意判断起始点是否分别在两个串内. Code #include ...

  8. C语言中的基础知识变量探讨

    C语言中的变量是编程的基础,主要有四个要素:存储类型.存储大小.存储名称和存储地址. 一.变量的要素: 1.存储类型:主要表明名变量存储的特征,主要有auto.extern.static和regist ...

  9. Android Studio中删除所有的断点

    直接上图,我相信你们能看的懂,骚年们. 第1个图:Run–>>View Breakpoints.. 第2个图:现在可以看到所有的断点了,在左侧栏全选,然后点"-",就全 ...

  10. 8大排序算法的java实现--做个人收藏

    排序算法分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因为数据量太大,一次不能容纳全部的排序记录,在排序过程中需要访问外存.这里只讨论内部排序,常见的内部排序算法有:插入排序 ...