《APUE》读书笔记—第十三章守护进程_第1页
《APUE》读书笔记—第十三章守护进程_第2页
《APUE》读书笔记—第十三章守护进程_第3页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、APUE读书笔记一第十三章守护进程守护进程也称为精灵进程是一种生存期较长的一种进程。它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件。他们常常在系统引导装入时启动, 在系统关闭时终止。unix系统有很多守护进程,大多数服务器都是用守护进程实现的,例如inetd守护进程。1、守护进程的特征用ps命令察看一些常用的系统守护进程,看一下他们和几个概念:进程组、控制终端和会 话有什么联系。执行:ps -axj ,结果如下所示:ankerkiller-ariken PPTD012N22UIDB0DDaQaao930aoaooDU00:600:G00:020 100O&r *0O

2、G-kthreadd ksoTtLi qd/O nigratton/O watchd&g/G J nigrati&n/l ksofttr qd/1 watchdog/l cpuset Ichelper kdevtnpfs netnssr*c_supers bdi-defaultJ kintegritd kblockd| ata_sff; khubd nd从结果可以看出守护进程没有控制终端,其终端名设置为?,终端前台进程组ID设置为-1 ,init进程ID为1。系统进程依赖于操作系统实现,父进程 ID为0的各进程通常是内核进 程,它们作为系统自举的一部分而启动。内核进程以超级用户

3、特权运行,无控制终端, 无命令行。大多数守护进程的父进程是init进程。守护进程与后台进程的区别:(1 )后台运行程序,即加&启动的程序,(2 )后台运行的程序拥有控制终端,守护进程没有。2、守护进程编程规则(1) 调用umask将文件模式创建屏蔽字设置为0。因为进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除:调用 umask(0)。(2) 调用fork,然后使父进程退出。 这样可避免挂起控制终端将Daemon放入后台执行。(3) 调用setsid以创建一个新会话。这样可以使得调用进程成为新会话的首进程,成为 一个新

4、进程组的组长进程,没有控制终端。(4 )将当前工作目录更改为根目录。进程活动时,其工作目录所在的文件系统不能卸下。一般需要将工作目录改变到根目录。对于需要转储核心,写运行日志的进程将工作目录改变到特定目录如/tmpchdir("/") 。(5) 关闭不再需要的文件描述符。进程从父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。(6) 某些守护进程打开/dev/null使其具有文件描述符 0、1和2。使得任何一个试图读 标准输入、写标准输出或者标准出错的历程都不会产生任何效果。(7 )处理SIGCHLD 信号。

5、处理SIGCHLD 信号并不是必须的。但对于某些进程,特别 是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie )从而占用系统资源。如果父进程等待子进程结束,将增加父 进程的负担,影响服务器进程的并发性能。在Linux下可以简单地将SIGCHLD信号的操作设为SIGGN 。初始化一个守护进程的程序如下:#i nclude <stdio.h>#i nclude <stdlib.h>#i nclude <uni std.h>#i nclude verrno .h>#i nclude <pth

6、read.h>#in clude <sig nal.h>#in clude <fcn tl.h>#in clude <syslog.h>#i nclude <sys/resource.h>void daemonize( const char *cmd)inti,fd0,fd1,fd2;pid_tpid;struct rlimit r1;struct sigact ion sa;umask( 0);/获取文件描述符最大值getrlimit(RLIMIT_NOFILE,&r1);/创建子进程if (pid = fork() <0)

7、perror( "fork() error" );exit( 0);else if (pid >0)/使父进程退出exit( 0);setsid();/创建会话/创建子进程避免获取终端sa.sa_ha ndler = SIGGN;sigemptyset(&sa.sa_mask);sa.sa_flags =0;sigactio n( SIGHUP,&sa,NULL);if (pid = fork() <0)perror( "fork() error" );exit( 0);else if (pid >0)exit( 0);

8、/修改目录chdir( "/");/关闭不需要的文件描述符if (r1.rlim_max = RLIM_INFINITY)r1.rlim_max =1024;for (i= 0;i<r1.rlim_max;+i)close(i);/打开文件描述符fd0 = ope n( "/dev/null" ,0_RDWR);fd1 = dup(0);fd2 = dup(0);ope nl og(cmd,LOG_CONS ,L OG_DAEMON);if (fd0 !=0 | fd1 !=1 | fd2 !=2)syslog(LOG_ERR,"un e

9、xpected filedescriptors %d %d %d" ,fd0,fd1,fd2);exit( 1);int main()daemonize( "ls");sleep( 30);/主进程休眠,以便查看守护进程状态exit( 0);第一次调用fork的目的是保证调用 setsid的调用进程不是进程组长。(而setsid 函数是实现与控制终端脱离的唯一方法);setsid 函数使进程成为新会话的会话头和进程组长,并与控制终端断开连接;第二次调用fork的目的是:即使守护进程将来打开一个终端设备, 也不会自动获得控制终端。(因为在SVR4中,当没有控制终端的

10、会话头进程打开终端设备时,如果这个终端不是其他会话的控制终端,该终端将自动成为这个会话的控制终端),这样可以保证这次生成的进程不再是一个会话头。忽略SIGHUP 信号的原因是,当第次生成的子进程(会话头)终止时,该会话中的所有进程(第二次生成的子进程)都会收 到该信号。程序执行结果,输入 ps -axj命令查看守护进程的信息:1751375127S12 ?-1 s1B0O0:00亠 /daeraonlze *31197S1475143119 pts/17514 R+10869:00ps -axjsnkerkiller-ankeri-/PragransS ps -axj | grep 7513

11、Larnir>gz bad ps syntax ( perhaps a bogio ' -' ?bee http:1751375127512 ?-1 51000a:BO3119751675153119 pts/17515 S+1000O:0Ggrep -colorruto 7S133、出错记录守护进程没有控制终端,不能将错误写到标准输错上。大多数进程使用集中的守护进程出错syslog设施,该设施的接口是syslog函数,原型如下:#in elude <syslog.h>void ope nl og(c onst char *ide nt, i nt opti

12、on, int facility);void syslog(int priority, const char *format, .);void closelog(void);int setlogmask(i nt mask);#in clude <stdarg.h>void vsyslog(int priority, const char *format, va_list ap);大多数syslog实现将使消息多时间处于队列中,如果在此时间中到达了重复消息,那么syslog守护进程将不把它写到日志记录中,而是打印输出重复消息。4、单实例守护进程为了正常运作,某些守护进程实现为单实例

13、,即在任一时刻只运行该守护进程的一个副 本。采用文件锁和记录锁机制可以实现单实例守护进程,如果每一个守护进程创建一个文件,并且在整个文件上加上一把锁,那就只允许创建一把这样的写锁,之后试图再创建这样的一把写锁将会失败。这样就保证守护进程只有一个副本在运行。使用文件和记录锁保证只运行某守护进程的一个副本,守护进程的每个副本都试图创建一个文件,并将其进程ID写到该文件中。程序如下:#i nclude <stdio.h>#i nclude <stdlib.h>#include < string .h>#i nclude <uni std.h>#i nc

14、lude <errno .h>#in clude <sig nal.h>#in clude <fcn tl.h>#in clude <syslog.h>#i nclude <sys/stat.h>#define LOCKFILE ”/var/run/daemon.pid"#define LOCKMODE (SRUSR | SWUSR | SRGRP | SROTH ) extern int lockfile( int );int alreadyunning(void ) _int fd;char buf 16;/打开文件,不

15、存在则创建fd = ope n(LOCKFILE,O-RDWR|O_CREAT 丄 OCKMODE);if (fd <0)syslog(LOG_ERR,"can't ope n %s : %s" 丄 OCKFILE,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" 丄 OCKFILE,strerror(

16、errno); exit( 1);ftruncate(fd,0); /将文件长度截短为0sprintf(buf,"%ld" ,( long )getpid();write(fd,buf,strle n( buf)+1);return 0;百5、守护进程的惯例(1 )若守护进程使用锁文件,那么该文件通常存放在/var/run 目录中。(2) 若守护进程支持配置选项,那么配置文件通常存放在/etc中目录中。(3) 守护进程可以用命令行启动,通常是系统初始化脚本。(4) 若一守护进程有一配置文件,那么当该守护进程启动时,读取该文件,此后一把不会 在查看它。使用sigwait及多线

17、程实现守护进程重读配置文件程序如下:#i nclude <stdio.h>#i nclude <stdlib.h>#include < string .h>#i nclude <uni std.h>#i nclude <errno .h>#in clude <sig nal.h>#in clude vfcn tl.h>#in clude <syslog.h>#i nclude <sys/stat.h>#i nclude <sys/resource.h>#define LOCKFIL

18、E ”/var/run/daemon.pid"#define LOCKMODE (SRUSR | SWUSR | SRGRP | SROTH )sigset_t mask;int lockfile( int fd)struct flock f1;f1.l_type = F_WRLCK;f1. l_start =0;f1.l _whe nee = SEEK_SET;f1.l_le n =0;return fcntl(fd,F_SETLK,&f1); _int already_running( void ) _int fd;char buf 16;fd = ope n(LOCKF

19、ILE,O_RDWR|O_CREAT ,L OCKMODE);if (fd <0)syslog(LOG_ERR,"can't ope n %s : %s" 丄 OCKFILE,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" 丄 OCKFILE,strerror(errno); exit( 1);ftrun cat

20、e(fd,0);sprintf(buf,"%ld" ,( long )getpid();write(fd,buf,strle n( buf)+1);return 0; void daemonize( const char *cmd)inti,fd0,fd1,fd2;pid_tpid;struct rlimit r1; struct sigact ion sa;umask( 0);getrlimit(RLIMIT_NOFILE,&r1);if (pid = fork() <0)perror( "fork() error" );exit( 0)

21、;else if (pid >0)exit( 0);setsid();sa.sa_ha ndler = SIGGN;sigemptyset(&sa.sa_mask);sa.sa_flags =0;sigactio n( SIGHUP,&sa,NULL);if (pid = fork() <0)perror( "fork() error" ); exit( 0);else if (pid >0)exit( 0);chdir( "/");if (r1.rlim_max = RLIM_INFINITY) r1.rlim_max

22、 =1024;for (i= 0;i<r1.rlim_max;+i) close(i);fd0 = ope n("/dev/null" ,O_RDWR);fd1 = dup(0);fd2 = dup(0);ope nl og(cmd,LOG_CONS ,L OG_DAEMON); if (fd0 !=0 | fd1 !=1 | fd2 !=2)syslog(LOG_ERR, "un expected file descriptors %d %d %d" ,fd0,fd1,fd2);exit( 1);void reread()printf( "read daem on config file aga in.n" );void * thread_func(void *arg)int err,signo;while (1)sigwait(&mask,&sig no);switch (signo)case SIGHUP: syslog(LOGNFO, reread();break;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论