Linux守护进程

 Linux守护进程的创建

          Linux守护进程又称为Daemon进程,为Linux的后台服务进程(独立于控制终端)。该进程通常周期性地执行某种任务或等待处理某些发生的事件。其生命周期较长,通常在系统启动时开始执行,在系统关闭时终止。Linux中很多系统服务都是通过守护进程实现的。

        在Linux中,每一个从终端开始运行的进程都会依附于一个终端(系统与用户进行交互的界面),这个终端为进程的控制终端。当控制终端关闭时,这些进程就会自动结束,但守护进程不受终端关闭的影响。

        如何将一个进程变成一个守护进程,只需要遵循一些特定的流程。

1.创建子进程(子进程不退出,父进程退出)

        很明显,由于父进程先于子进程退出,造成子进程成为孤儿进程。此时子进程的父进程变成init进程。

2.在子进程中创建新会话

        使用的函数是 setsid() 。该函数将会创建一个新会话,并使进程担任该会话组的组长。同时,在会话组中创建新的进程组,该进程依然也是进程组的组长。该进程成为新会话组和进程组中唯一的进程。最后使该进程脱离终端的控制,运行在后台。

        之所以需要这样处理,是因为子进程在被创建时,复制了父进程的会话、进程组和终端控制等。虽然父进程退出,但原先的会话、进程组和控制终端等并没有改变。因此,子进程并没有实现真正意义上的独立。

3.改变当前的工作目录

        使用fork() 函数创建的子进程继承了父进程的当前工作目录。系统通常的做法是让根目录成为守护进程的当前工作目录。改变工作目录的函数是chdir()。

#include<unistd.h>
int chdir(const char *path);

4.重设文件权限掩码

        文件权限掩码的作用是屏蔽文件权限中的对应位。文件被创建后,其用户操作权限mode,将会被执行mode&~umask(umask为文件权限掩码,通常用八进制数表示)。由于创建的子进程继承了父进程的文件权限掩码,这给子进程操作文件带来一定的影响。因此,通常把文件权限掩码设置为0,这样可以增强守护进程的灵活性。此时,文件权限掩码取反全为1,与任何文件权限相与,都可保持文件最原始的状态值。

        使用函数umask(),改变文件权限掩码,参数即为要修改的掩码值。

#include<sys/types.h>
#include<sys/stat.h>
mode_t umask(mode_t mask);

5.关闭文件描述符

        新创建的子进程会从父进程继承一些已经打开的文件描述符。这些描述符可能永远都不会被守护进程访问,但他们却占有一定的资源。特别注意的是,守护进程脱离了终端的控制,所以与终端相关的标准输入、输出、错误输出的文件描述符0、1、2,已经没有了任何价值,应当关闭。

for(i=0;i<getdtablesize();i++)
{
    close(i);
}

其中,getdtablesize() 函数的功能为获取文件描述符表的大小,也可以理解为获取进程打开的文件描述符的最大数量。

其流程图为:

 创建守护进程代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<fcntl.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>
#include<sys/stat.h>

int main(int argc,const char *argv[])
{	
	pid_t pid;
	int i,fd;
	char *buf = "This is a Daemon\n";

	pid = fork();  //第一步
	if(pid < 0)
	{
		perror("fork error");
		return -1;
	}
	else if(pid > 0)
	{
		exit(0);  //父进程瑞出
	}
	else
	{
		setsid(); //第二步
		chdir("/tmp"); //第三步
		umask(0); //第四步
		for(i = 0;i < getdtablesize();i++) //第五步
		{
			close(i);
		}
	/* 守护进程创建完成,以下代码为进入守护进程的工作 */
	if((fd = open("daemon.log",O_CREAT|O_WRONLY|O_TRUNC,0600)) < 0)
	{
		perror("open error");
		return -1;
	}
	
	while(1)
	{
		write(fd,buf,strlen(buf));
		sleep(3);
	}
	close(fd);
	}
	return 0;
}

终端输入ps axj ,可以查看守护进程信息,可以看到进程的ID与组ID、会话组ID保持一致,说明当前守护进程为组长。其父进程为init进程(ID为1),TTY选项为 "?" ,表示其为后台进程

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值