守护进程(Daemon进程)
与终端无关的进程,运行在后台,生存期较长,系统关闭时终止或可以通过命令终止或通过ps找到进程用kill杀死,有的以d结尾
终端是人与电脑交互的界面:
要以管理员身份启动:service httpd start
查看命令:ps -ef|grep httpd
关闭:service httpd stop
用命令ps -axj
查看常用的守护进程:
从结果可以看出守护进程没有控制终端,其终端名设置为?,终端前台进程组ID设置为-1,init进程ID为1。系统进程依赖于操作系统实现,父进程ID为0的各进程通常是内核进程,它们作为系统自举的一部分而启动。内核进程以超级用户特权运行,无控制终端,无命令行。大多数守护进程的父进程是init进程。会话:打开一个终端,就建立了会话。关闭终端就关闭了会话。比如:两个人打电话就建立了会话,挂掉电话就关闭了会话。一般以整个会话运行起来的第一个进程的id命名会话(一般为shell)。
进程组:一个进程组里面有一个或多个进程。一般以组长进程id命名进程组。比如:ls为一个进程组,ls即为组长也为组员,ls命令结束进程组也结束。
会话包括一个或多个进程组,一个进程组包括一个或多个进程。
获得会话id:getsid();
获得进程组id:getpgid();
获得进程id:getpid();
参数传0,表示当前会话或进程。
守护进程的创建流程:
1.fork();创建子进程,退出父进程。只有组员才能创建新会话。
2.setsid();创建新会话,进程变成会话首进程,组长。
3.chdir();将当前工作目录更改为根目录。进程活动时,其工作目录所在的文件系统不能卸下。一般需要将工作目录改变到根目录。
4.调用umask将文件模式创建屏蔽字设置为0。因为进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除:调用umask(0)。
5.close();进程从父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。
示例
实现一个简单的守护进程,获取本地时间,用mytest.log记录并测试
#include <stdio.h>
#include <time.h>
#include <assert.h>
#include <unistd.h>
int main()
{
pid_t pid=fork();
if(pid!=0)
{
exit(0);
}
setsid();
pid=fork();
if(pid!=0)
{
exit(0);
}
chdir("/");
umask(0);
int i=0;
for(; i<getdtablesize(); i++)
{
close(i);
}
///////////////////////////////////////////////////////////////
//守护程序写完,下面是要做什么事
//////////////////////////////////////////////////////////////
while(1)
{
FILE *fp=fopen("/tmp/mytest.log","a");
assert(fp != NULL);
time_t t;
time(&t);
fprintf(fp,"time is:%s", localtime(&t));
fclose(fp);
sleep(5);
}
}
测试
kill守护进程
拷贝文件到/etc/init.d底下,可以使用service daemond start启动自己写的守护进程