《Unix环境高级编程》读书笔记 第13章-守护进程
1. 引言
- 守护进程是生存期长的一种进程。它们常常在系统引导装入时启动,仅在系统关闭时才终止。它们没有控制终端,在后台运行。
- 本章说明守护进程结构、如何编写守护进程程序、守护进程如何报告出错情况。
2. 守护进程的特征
- 基于BSD的系统下执行:
ps -axj-a 显示由其他用户所拥有的进程的状态;-x 显示没有控制终端的进程状态;-j 显示与作业有关的信息
- 基于System V的系统下执行:
ps -efj - Linux下执行以上两个命令输出一致
- 常见的守护进程:
- kswapd,内存换页守护进程。
- flush守护进程在可用内存达到设置的最小阀值时将脏页面冲洗至磁盘。
- sync_supers守护进程定期将文件系统元数据冲洗至磁盘。
- jbd守护进程帮助实现了ext4文件系统中的日志功能。
- rpcbind守护进程提供了将远程过程调用程序号映射为网络端口号的服务。
- rsyslogd守护进程可以被由管理员启用的将系统消息记入日志的任何程序使用。
- inetd守护进程。超级因特网服务进程。
- crond守护进程在定期安排的日期和时间执行命令。
- atd守护进程,允许用户在指定的时间执行任务,但是每个任务只执行一次。
- sshd守护进程提供了安全的远程登录和执行设施。
- cupsd守护进程,打印假脱机进程,处理对系统提出的各个打印请求。
3. 编程规则
- 在编写守护进程程序时需遵循一些基本规则,以防止产生不必要的交互作用。
- 调用umask将文件模式创建屏蔽字设置为一个已知值(通常为0)。
- 调用fork,然后使父进程exit。因为:第一,如果守护进程是通过shell启动的,这可以让shell认为这条命令已经执行完毕;第二,子进程继承了父进程的进程组ID,但获得一个新的进程ID,这保证了子进程不是一个进程组的组长进程。这是setsid的先决条件。
- 调用setsid创建一个新会话。使调用进程:a. 成为新会话的首进程;b. 成为一个新进程组的组长进程;c. 没有控制终端
- 将当期工作目录更改为根目录,以免占有某文件系统,使得其不能被卸载。或者,某写守护进程还可能把当前工作目录更改到某个指定位置。
- 关闭不再需要的文件描述符。使守护进程不再持有从其父进程继承来的任何文件描述符。可以使用open_max函数或getrlimit函数来判定最高文件描述符的值,并关闭直到该值的所有描述符。
- 某些守护进程打开/dev/null使其具有文件描述符0、1、2 。这样,任何一个试图读标准输入、写标准输出或标准错误的库例程都不会产生任何效果。
#include "apue.h"
#include <syslog.h>
#include <fcntl.h>
#include <sys/resource.h>
void daemonize(const char *cmd)
{
int i, fd0, fd1, fd2;
pid_t pid;
struct rlimit rl;
struct sigaction sa; /*
* Clear file creation mask.
*/
umask(0); /*
* Get maximum number of file descriptors.
*/
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
err_quit("%s: can’t get file limit", cmd); /*
* Become a session leader to lose controlling TTY.
*/
if ((pid = fork()) < 0)
err_quit("%s: can’t fork", cmd);
else if (pid != 0) /* parent */
exit(0);
setsid(); /*
* Ensure future opens won’t allocate controlling TTYs.
*/
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0)
err_quit("%s: can’t ignore SIGHUP", cmd);
if ((pid = fork()) < 0)
err_quit("%s: can’t fork", cmd);
else if (pid != 0) /* parent */
exit(0); /*
* Change the current working directory to the root so
* we won’t prevent file systems from being unmounted.
*/
if (chdir("/") < 0)
err_quit("%s: can’t change directory to /", cmd); /*
* Close all open file descriptors.
*/
if (rl.rlim_max == RLIM_INFINITY)
rl.rlim_max = 1024;
for (i = 0; i < rl.rlim_max; i++)
close(i); /*
* Attach file descriptors 0, 1, and 2 to /dev/null.
*/
fd0 = open("/dev/null", O_RDWR);
fd1 = dup(0);
fd2 = dup(0); /*
* Initialize the log file.
*/
openlog(cmd, LOG_CONS, LOG_DAEMON);
if (fd0 != 0 || fd1 != 1 || fd2 != 2) {
syslog(LOG_ERR, "unexpected file descriptors %d %d %d", fd0, fd1, fd2);
exit(1);
}
}
4. 出错记录

- 有以下3种产生日志消息的方法:
- 内核例程可以调用log函数。
- 大多数用户进程(守护进程)调用syslog函数来产生日志消息。
- 无论一个用户进程是在此主机上,还是在通过TCP/IP网络连接到此主机的其他主机上,都可将日志消息发送到UDP端口514 。
#include <syslog.h>void openlog(const char *ident, int option, int facility);void syslog(int priority, const char *format, ...);void closelog(void);int setlogmask(int maskpri); Returns: previous log priority mask value5. 单实例守护进程
- 为了正常运作,某些守护进程会实现为,在任一时刻只运行该守护进程的一个副本。
- 文件和记录锁机制提供了一种保证一个守护进程只有一个副本在运行的方法。
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <syslog.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <sys/stat.h>
#define LOCKFILE "/var/run/daemon.pid"
#define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
extern int lockfile(int); int already_running(void)
{
int fd;
char buf[16];
fd = open(LOCKFILE, O_RDWR|O_CREAT, LOCKMODE);
if (fd < 0) {
syslog(LOG_ERR, "can’t open %s: %s", LOCKFILE, strerror(errno));
exit(1);
}
if (lockfile(fd) < 0) {
if (errno == EACCES || errno == EAGAIN) {
close(fd);
return(1);
}
syslog(LOG_ERR, "can’t lock %s: %s", LOCKFILE, strerror(errno));
exit(1);
}
ftruncate(fd, 0);
sprintf(buf, "%ld", (long)getpid());
write(fd, buf, strlen(buf)+1);
return(0);
}
6. 守护进程的惯例
- 在Unix系统中,守护进程遵循以下通用惯例:
- 若守护进程使用锁文件,那么该文件通常存储在/var/run目录中。守护进程可能需要具有超级用户权限才能在此目录中创建文件。锁文件的名字通常是name.pid。
- 若守护进程支持配置选项,那么配置文件通常存放在/etc目录中。配置文件的名字通常是name.conf。
- 守护进程可用命令行启动,但通常它们是由系统初始化脚本之一启动的。
- 某些守护进程捕捉SIGHUP信号,当它们接收到该信号时,重新读配置文件。
7. 客户进程-服务器进程模型
- 守护进程常常用作服务器进程。
- 一般而言,服务器进程等待客户进程与其联系,提出某种类型的服务要求。
- 在服务器进程中调用fork然后exec另一个程序来项客户进程提供服务是很常见的。服务器进程通常管理着多个文件描述符:通信端点、配置文件、日志文件和类似的文件。为保证安全,可设置所有对于被执行程序不需要的文件描述符的执行关闭标志close-on-exec。
原创文章,转载请声明出处:http://www.cnblogs.com/DayByDay/p/3948402.html
《Unix环境高级编程》读书笔记 第13章-守护进程的更多相关文章
- [置顶] 文件和目录(二)--unix环境高级编程读书笔记
在linux中,文件的相关信息都记录在stat这个结构体中,文件长度是记录在stat的st_size成员中.对于普通文件,其长度可以为0,目录的长度一般为1024的倍数,这与linux文件系统中blo ...
- APUE读书笔记-第13章-守护进程
第13章 守护进程 13.1 引言 *守护进程也称精灵进程(daemon)是生存期较长的一种进程.它们常常在系统自举时启动,仅在系统关闭时才终止.因为它们没有控制终端,所以说它们是在后台运行的.UNI ...
- unix环境高级编程-读书笔记与习题解答-第一篇
从这周开始逐渐的进入学习状态,每天晚上都会坚持写c程序,并且伴随对这本书的深入,希望能写出更高质量的读书笔记和程序. 本书的第一章,介绍了一些关于unix的基础知识,在这里我不想去讨论linux到底是 ...
- unix 环境高级编程-读书笔记与习题解答-第二篇
第四节 输入与输出 上次的笔记中写到的 open, read, write, lseek 以及close ,都是不带缓存的IO函数,这些函数都使用文件描述符进行工作. 上一篇笔记用到的 read(ST ...
- [置顶] 文件io(一)--unix环境高级编程读书笔记
unix-like(后面以linux为例)系统中的文件操作只需要五个函数就足够了,open.close.read.write以及lseek.这些操作被称为不带缓存的io,这里有必要说一下带缓存和不带缓 ...
- unix 环境高级编程 读书笔记与习题解答第四篇
第一章 第六节 第一小节 这一章没有程序设计和API方面的深入学习,而是注重介绍了unix操作系统中的原始数据类型和系统原型函数,错误处理方面的知识. ____unistd.h____ 该文件包含了u ...
- unix进程的环境--unix环境高级编程读书笔记
http://blog.csdn.net/xiaocainiaoshangxiao/article/category/1800937
- unix环境高级编程 读书笔记
1.上班业余时间把书下载下来,第一章读完了,但是程序只能回家运行啦!Fighting!
- Unix环境高级编程学习笔记——fcntl
写这篇文正主要是为了介绍下fcntl,并将我自己在学习过程中的一些理解写下来,不一定那么官方,也有错误,希望指正,共同进步- fcntl: 一个修改一打开文件的性质的函数.基本的格式是 int fcn ...
随机推荐
- Java NIO(六)选择器
前言 Selector选择器是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件.这样使得一个单独的线程可以管理多个Channel,从而管理多个网络连接.选择 ...
- swift使用查阅资料备份1
SnapKit RxSwift R.swift https://www.jianshu.com/p/68e12b966d86 iOS - RxSwift 项目实战记录 https://blog.csd ...
- nsrunloop与模式
scrollview的模式切换:退出原来的模式使用新模式. 2018-04-18 18:16:41.208113+0800 CEMonitor[5014:410604] kCFRunLoopDefau ...
- CDR入门教程-CorelDRAW排版教程
CorelDRAW是一个绘制矢量图,排版的软件.今天给大家带来一片教程就是关于排版的.大家快来试试吧. CDR下载:http://pan.baidu.com/s/1cD4buQ 步骤一:新建一个A4文 ...
- 我用windows live Writer 写个日志试试看
我用windows live Writer 写个日志试试看. 哈哈 播放幻灯片 全部下载
- Java语言特点与学习
Java语言是一款面向对象的一款高级语言是由Sun Microsystems公司(现已被oracle公司收购).由James Gosling和同事们共同研发,并在1995年正式推出,据oracle官方 ...
- vue2 在methods 中无法获取this对象
在methods中使用箭头函数无法获取this ExamName:()=> { console.log(this);} 这样就行了: ExamName:function() { console. ...
- 流媒体应用程序Mobdro或存在安全隐患
Mobdro是一款流媒体应用程序,可以安装在任何Android设备上,包括手机,平板电脑,亚马逊的Fire TV Stick和Google的Chromecast.它现在已经流行了一段时间,特别是在围绕 ...
- 多个 WindowsFormsHost 叠加顺序调整
原文:多个 WindowsFormsHost 叠加顺序调整 工作中遇到多个 WindowsFormsHost 包装的控件叠加顺序的调整问题,用了 BingToFront 和 BringToBack,不 ...
- JQuery封装ajax的方法
1.$.post方法 $.post(url[,data][,callback][,type]) url:请求的后台程序地址 data:发送到后台的数据 callback:载入成功时回调函数,该函数参数 ...