守护进程

1什么叫作守护进程shell

守护进程通常在系统引导装入的时候启动,在系统关闭的时候关闭,由于他们没有控制终端,因此说他们是后台运行的,用来执行一些日长的任务编程

利用ps -axj能够查看,其中a是查看其余的用户所拥有的进程,x显示没有控制终端的进程状态,-j显示与做业有关的信息,主要是第一行的信息网络

这个ps命令要正确 的打印,系统必须支持会话,不然不能正确的显示,父进程是0的一般是内核进程,内核进程的生命周期存在于系统的整个生命周期中,他们以超级用户权限运行,没有控制终端,不能使用命令行
tcp

如何判断是不是守护进程,当TPGID=-1的时候就是守护进程,comman命令加了[]就是系统级的守护进程,没有加[]就是用户级的守护进程,要注意,init并非一个内核级的守护进程,他是用户级的守护进程的父进程ide

咱们如何断定是否使用内核守护进程:咱们使用一个内核组件,却不被用户进程的上下文所调用,而且是常驻内存,咱们就应该使用内核守护进程函数

使用守护进程的大致原则:ui

若是一个进程永远都是之后台方式启动,而且不能受到Shell退出影响而退出,一个正统的作法是将其建立为守护进程(daemon)。守护进程值得是系统长期运行的后台进程,相似Windows服务。守护进程信息经过ps –a没法查看到,须要用到–x参数,当使spa

用这条命令的时候,每每还附上-j参数以查看做业控制信息,其中TPGID一栏为-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 r1; struct sigaction sa; umask(0); if(getrlimit(RLIMIT_NOFILE,&r1) < 0)  err_quit("%s:can't get file limit",cmd); if((pid = fork())<0)  err_quit("%s:can't fork",cmd); else if(pid != 0)  exit(0); setsid(); 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) { exit(0); } if(chdir("/") < 0)  err_quit("%s:can't change directory to /",cmd); if(r1.rlim_max == RLIM_INFINITY) r1.rlim_max = 1024; for(i = 0; i < r1.rlim_max;i++)  close(i); fd0 = open("/dev/null",O_RDWR); fd1 = dup(0); fd2 = dup(0); 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(0); }}int main(){ daemonize("my "); sleep(10); return 0;}

将一个进程变成一个守护进程的方法

(1)首先应该改变的是文件模式屏蔽字,由于在本来的进程上下文中,文件屏蔽字是不必定符合规范的,并且守护进程通常须要建立一个具备特定要求的屏蔽字,因此应该本身设置一个合理的屏蔽字,若是有更加严格的要求通常将文件模式设置为007

(2)调用fork,进行建立一个新的子进程,为何要这么作第一,若是在shell中这样启动一个程序,当父进程exit的时候,会让shell认为此程序已经执行完毕第二,这样保证了这个进程不是一个子进程,这是使用setsid的先决条件

(3)调用setsid来进行设置一个新的会话,在建立会话的时候为了保证不分配一个控制终端,一般会在fork一次,这样就必定这个进程不是控制终端进程(其实在第一次fork的时候,而且使用了setsid的时候就肯定了必定不是控制终端)这样作实际上是为了更加肯定(能够这样理解)

(4)更改当前的工做目录成为根目录,由于若是不更改成根目录,原本工做的目录其实就要一直被挂载,这在某些系统中,显然是这样作到,由于有可能这个操做系统会被删除

(5)进行全部的文件描述符的关闭

(6)某些守护进程打开/dev/null等,使其映射到0,1,2

关于程序的运行的结果显示

3守护进程出错记录

首先咱们进行syslog的介绍

 syslog是一种工业标准的协议,可用来记录设备的日志。在UNIX系统,路由器、交换机等网络设备中,系统日志(System Log)记录系统中任什么时候间发生的大小事件。管理者能够经过查看系统记录,随时掌握系统情况。UNIX的系统日志是经过syslogd这个进程记录系统有关事件记录,也能够记录应用程序运做事件。经过适当的配置,咱们还能够实现运行syslog协议的机器间通讯,经过分析这些网络行为日志,藉以追踪掌握与设备和网络有关的情况。

由于守护进程是没有控制终端的,因此通常不能要求守护进程将出错记录写到控制台上,固然也不能写到一个文件中,若是每一个守护进程都写到一个文件中,则无疑再用的时候是很麻烦的


这是日志系统的主要设施,这个设施被称为syslog设施,与用户进程调用syslog不是一个东西,三种能够产生日志的方法

(1)用户守护进程调用syslog函数产生日志消息,这些消息被送往UNIX域数据报套接字(这是一个设备,目前先了解为就是一个设施)而后接下来syslog是不产生UDP数据报的,要注意

(2)经过tcp/ip网络在或者不在此系统上的进程发送消息到UDP端口54

(3)内核经过log发送到klog

其中syslogd这个守护进程读取这三种格式的日志消息,而且根据/etc/syslog.conf发送,该文件决定了不一样种类的消息应该送向何处,列如紧急消息可送往系统管理员,而警告信息能够送往一个文件

该syslog整个设备的接口(这里的接口指的是操做整个syslog的接口,能够往/dev/log或者UDP或者klog里面写,总之就是整个syslog的写入接口,可是能够根据选项选择怎样写,写什么样的小设备

主要有四个接口

#include<syslog.h>

void openlog(const char* ident,int option,int facility);

ident:通常是程序的名字,自动追加到每则日志消息中

option:



打开日志系统,其中这个是可选的,若是没有调用openlog,则在第一次调用syslog的时候,自动调用openlog。    

facility:

facility可让配置文件说明,来自不一样设施的消息将以不一样的方式进行处理

注意:若是不调用openlog,或者以facility为0来调用,那么在调用syslog,可将facility做为priority参数的一个不分进行说明

void syslog(int priority,const char *format,....);

priority:是facility和level的组合,其中level能够是

format:以及其余的全部参数传至vsprintf函数进行格式话,在format中,每一个出现的%m字符都被替换成和errno对应的字符串

void closelog(void );

用来关闭被用于与syslogd函数通讯的描述符

int setlogmask(int makdpri);

设置屏蔽字,若是被设置,则不进行屏蔽,优先级屏蔽字

列如,咱们提供一个范列

4单实例守护进程

什么叫作单实例守护进程

由于出于须要,系统在某个时间只须要一个守护进程运行,列若有的守护进程须要排他性的访问一个设备;好比说,cron进程在具体 的时间内运行某一个进程,此进程是守护进程,若是运行多个这样子的守护进程,则会在相同的时间内运行多个同样的程序,形成混轮,因此这个cron进程须要字任意一个时间内运行一个守护进程!!

守护进程采用文件-和记录锁实现了单实例守护进程,此方法假设,守护进程都须要建立一个文件,而且在第一个守护进程建立文件以后就对整个文件进行加锁,使其余的相同的守护进程不能自进行此文件的加锁,这样就实现了守护进程的单实例运行

  
  
  
  
  
#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;}int main(){ already_running(); return 0;}

如以上的程序,先建立一个文件夹,而且在运用此函数时候锁住该文件,若是再有守护进程调用的时候,则进行锁住,而且将其写入文件,strerror是将错误标志转换成字符串

5守护进程的惯例

在unix系统中,一般的守护进程设计一般是如此设计

(1)若是守护进程使用锁文件,则该锁文件一般位于/var/run目录中。然而须要主义的是,在该目录建立文件一般须要超级用户的权限,锁文件的名字一般是name.pid,例如cron守护进程锁文件的名字是/var/run/crond.pid

(2)若是守护进程支持配置选项,那么该配置文件通常是放在/etc上的,文件名字通常是name.cond,name是该守护进程或服务的名字,

(3)守护进程可使用命令启动,可是该启动命令一班是在系统初始化 的脚本中进行的,若是守护进程终止,应当自动进行重启,而且若是一个守护进程更新了配置文件,则应该从新启动

(4)为了不当更改配置文件,须要中止在启动进程的时候,某些进程将捕捉SIGHUP信号,当接受到此信号的时候,从新读取配置文件。由于守护进程不与终端结合,他们或者是没有控制终端的会话首进程,或者是孤儿进程组的成员,因此守护进程没有里有指望接受SIGHUP,所以,守护进程能够重复使用SIGHUP






相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息