前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >守护进程

守护进程

作者头像
看、未来
发布2020-08-26 10:48:47
1.6K0
发布2020-08-26 10:48:47
举报

5.1 概念

(1)什么是守护进程

Daemon(守护进程)是运行在后台的一种特殊进程。**它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。**它不需要用户输入就能运行而且提供某种服务,不是对整个系统就是对某个用户程序提供服务。Linux系统的大多数服务器就是通过守护进程实现的。

(2)为什么需要守护进程

守护进程是脱离于终端并且在后台运行的进程。守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息所打断。

(3)守护进程实例

常见的守护进程包括系统日志进程syslogd、 web服务器httpd、邮件服务器sendmail和数据库服务器mysqld等。

5.2 模型
(1)守护进程编程步骤

a.创建子进程,父进程退出,一切工作在子进程中执行,形式上脱离了控制终端 b.在子进程中创建新的会话(会话后面章节会提到),使子进程完全独立出来,脱离控制 c.改变当前目录为根目录,防止占用其他可卸载的文件系统 d.重设文件权限掩码,防止继承的文件创建屏蔽字拒绝某些权限,增加守护进程的灵活性 e.关闭文件描述符 f.守护进程退出处理

在这里插入图片描述
在这里插入图片描述

代码模型:

代码语言:javascript
复制
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
 
static bool flag = true;
void create_daemon();
void handler(int);
 
int main()
{
	time_t t;
	int fd;
	create_daemon();  //进
	struct sigaction act;
	act.sa_handler = handler;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;

	// 函数执行开始
	if(sigaction(SIGQUIT, &act, NULL))
	{
		printf("sigaction error.\n");
		exit(0);
	}
	while(flag)
	{
		fd = open("/home/mick/daemon.log", O_WRONLY | O_CREAT | O_APPEND, 0644);
		if(fd == -1)
		{
			printf("open error\n");
		}
		t = time(0);
		char *buf = asctime(localtime(&t));
		write(fd, buf, strlen(buf));
		close(fd);
		sleep(60);
	}
	return 0;
}

void handler(int sig)
{
	printf("I got a signal %d\nI'm quitting.\n", sig);
	flag = false;
}
void create_daemon()
{
	pid_t pid;
	pid = fork();  //创建子进程
	
	if(pid == -1)
	{
		printf("fork error\n");
		exit(1);
	}
	else if(pid)  //关闭父进程
	{
		exit(0);
	}
 
	if(-1 == setsid())  //在子进程中创建新的会话
	{
		printf("setsid error\n");
		exit(1);
	}
 
	pid = fork();  //再次分离,更加稳定
	if(pid == -1)
	{
		printf("fork error\n");
		exit(1);
	}
	else if(pid)  
	{
		exit(0);
	}
 
	chdir("/"); //改变当前目录为根目录
	int i;
	for(i = 0; i < 3; ++i)
	{
		close(i); //关闭原始三个流
		//反正也失去了控制终端,再留着这三个也没意义
	}
	umask(0);  //重设文件掩码
	return;
}

注意守护进程一般需要在 root 权限下运行。

通过

ps -ef | grep ‘daemon’

如果想退出守护进程,kill -9 就好

其实,上面那套还有更直接的,直接通过库函数来创建守护进程:
代码语言:javascript
复制
#include <unistd.h>
 
int daemon(int nochdir, int noclose);

然后这个是官方解释,反正我看得懂 If nochdir is zero, daemon() changes the process’s current working directory to the root directory ("/"); otherwise, the current working directory is left unchanged.

代码语言:javascript
复制
   If noclose is zero, daemon() redirects standard input, standard
   output and standard error to /dev/null; otherwise, no changes are
   made to these file descriptors.

然后我们对上面那串代码简化一下:

代码语言:javascript
复制
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
 
static bool flag = true;
void handler(int);
 
int main()
{
	time_t t;
	int fd;
	if(-1 == daemon(0, 0))
	{
		printf("daemon error\n");
		exit(1);
	}
	struct sigaction act;
	act.sa_handler = handler;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	if(sigaction(SIGQUIT, &act, NULL))
	{
		printf("sigaction error.\n");
		exit(0);
	}
	while(flag)
	{
		fd = open("/home/mick/daemon.log", O_WRONLY | O_CREAT | O_APPEND, 0644);
		if(fd == -1)
		{
			printf("open error\n");
		}
		t = time(0);
		char *buf = asctime(localtime(&t));
		write(fd, buf, strlen(buf));
		close(fd);
		sleep(60);
	}
	return 0;
}
void handler(int sig)
{
	printf("I got a signal %d\nI'm quitting.\n", sig);
	flag = false;
}

其实就是用库函数替换掉我们自己的函数。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-01-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 5.1 概念
    • 5.2 模型
    相关产品与服务
    数据库专家服务
    数据库专家服务(Database Expert Service,DBexpert)为您提供专业化的数据库服务。仅需提交您的具体问题和需求,即可获得腾讯云数据库专家的专业支持,助您解决各类专业化问题。腾讯云数据库专家服务团队均有10年以上的 DBA 经验,拥有亿级用户产品的数据库管理经验,以及丰富的服务经验。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档