守护进程(Daemon Process),也就是通常说的 Daemon 进程(精灵进程),是 Linux 中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。一般采用以d结尾的名字。
守护进程是个特殊的孤儿进程,这种进程脱离终端,为什么要脱离终端呢?之所以脱离于终端是为了避免进程被任何终端所产生的信息所打断,其在执行过程中的信息也不在任何终端上显示。由于在 Linux 中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。
Linux 的大多数服务器就是用守护进程实现的。比如,Internet 服务器 inetd,Web 服务器 httpd 等。
1.创建子进程,父进程退出(必须)
2.在子进程中创建新会话(必须)
3.改变当前目录为根目录(不是必须)
4.重设文件权限掩码(不是必须)
5.关闭文件描述符(不是必须)
6.开始执行守护进程核心工作(必须)
守护进程退出处理程序模型
写一个守护进程, 每隔2s获取一次系统时间, 将这个时间写入到磁盘文件:
void write_time(int num)
{
time_t rawtime;
struct tm * timeinfo;
// 获取时间
time(&rawtime);
#if 0
// 转为本地时间
timeinfo = localtime(&rawtime);
// 转为标准ASCII时间格式
char cur = asctime(timeinfo);
#else
char cur = ctime(&rawtime);
#endif
// 将得到的时间写入文件中
int fd = open(“/home/edu/timelog.txt”, O_RDWR | O_CREAT | O_APPEND, 0664);
if (fd == -1)
{
perror(“open error”);
exit(1);
}
// 写文件
int ret = write(fd, cur, strlen(cur) + 1);
if (ret == -1)
{
perror(“write error”);
exit(1);
}
// 关闭文件
close(fd); } int main(int argc, const char* argv[]) {pid_t pid = fork(); if (pid == -1) { perror("fork error"); exit(1); }
if (pid > 0) { // 父进程退出 exit(1); } else if (pid == 0) { // 子进程 // 提升为会长,同时也是新进程组的组长 setsid(); // 更改进程的执行目录 chdir("/home/edu"); // 更改掩码 umask(0022); // 关闭文件描述符 close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); // 注册信号捕捉函数 //先注册,再定时 struct sigaction sigact; sigact.sa_flags = 0; sigemptyset(&sigact.sa_mask); sigact.sa_handler = write_time; sigaction(SIGALRM, &sigact, NULL); // 设置定时器 struct itimerval act; // 定时周期 act.it_interval.tv_sec = 2; act.it_interval.tv_usec = 0; // 设置第一次触发定时器时间 act.it_value.tv_sec = 2; act.it_value.tv_usec = 0; // 开始计时 setitimer(ITIMER_REAL, &act, NULL); // 防止子进程退出 while (1); } return 0; }