守护进程的概念:
守护进程也叫精灵进程,是一种特殊的进程,一般在后台运行,不与任何控制终端相关联,并且周期性地执行某种任务或等待处理某些发生的事件(处理一些系统级的任务)。
守护进程通常在系统启动时就运行,它们以 root 用户或者其他特殊的用户运行(例如 apache)。
常见的守护进程包括系统日志进程syslogd、 web服务器httpd、邮件服务器sendmail和数据库服务器mysqld等。
特点:
- 后台运行,不与终端关联
- 运行周期长,守护进程一般在系统启动时开始运行,除非强行终止,否则直到系统关机都保持运行。
- 一个守护进程的父进程是init进程,因为它真正的父进程在fork出子进程后就先于子进程exit退出了,所以它是一个由init继承的孤儿进程。
- 守护进程是非交互式程序,没有控制终端,所以任何输出,无论是向标准输出设备stdout还是标准出错设备stderr的输出都需要特殊处理。
- 守护进程经常以超级用户(root)权限运行,因为它们要使用特殊的端口(1-1024)或访问某些特殊的资源。
- 习惯上守护进程的名字通常以 d 结尾(如 httpd, sshd),但这不是强制要求的。
会话
每打开一个控制终端,或者在用户登录时,系统就会创建新会话。
每个会话通常都与一个控制终端相关联。
在该会话中运行的第一个进程称作会话首进程,通常这个首进程就是shell。
与会话相关的系统调用
进程组
每个进程都属于某个进程组,进程组是由一个或多个相互间有关联的进程组成的,它的目的是为了进行作业控制。
进程组的主要特征就是信号可以发给进程组中的所有进程:这个信号可以使同一个进程组中的所有进程终止、停止或者继续运行。
每个进程组都由进程组 id 唯一标识,并且有一个组长进程。进程组 id 就是组长进程的 pid。只要在某个进程组中还有一个进程存在,则该进程组就存在。
即使组长进程终止了,该 #include pid_t setsid(void);创建新会话,当前调用进程不能是组长进程 pid_t getsid(pid_t pid); 获取进程所属会话 id, pid=0 是代表当前进程进程组依然存在。
与进程组相关的系统调用
会话、终端、进程组之间的关系
守护进程编程流程
- 在父进程中先 fork()——再退出父进程 。
- 调用 setsid()——创建新会话 。
- 再次 fork 退出父进程(有些书上没有这一步)。
- 调用 chdir(“/”) ——将当前工作目录修改到根目录 。
- 调用 umask()——清除掩码。
- 关闭所有不使用的文件描述符。
- 如果有产生子进程需要处理僵尸进程。
示例:编写一个守护进程实现每隔 5 秒钟向文件中写入一下当前时间 :
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<time.h>
int main()
{
pid_t pid = fork();
if(pid != 0)
{
exit(0);
}
setsid();
pid = fork();
if(pid != 0)
{
exit(0);
}
chdir("/");
umask(0);
int maxfd = getdtablesize();
int i = 0;
for(;i < maxfd;i++)
{
close(i);
}
while(1)
{
time_t tv;
time(&tv);
FILE *fp = fopen("/tmp/maind.log","a");
if(fp == NULL)
{
break;
}
fprintf(fp,"Curent time:%s",asctime(localtime(&tv)));
fclose(fp);
sleep(5);
}
exit(0);
}
图论