进程组
● 每个进程属于一个进程组
● 每个进程组都有一个进程组好,该号等于该进程组组长的PID
● 一个进程智能为自己或子进程设置进程组ID号
会话期
会话期session是一个或多个进程组的集合
建立一个会话期:setsid(),调用该函数的进程不是一个进程组组长,则创建一个新的会话期:
● 此进程变成该session首进程
● 此进程变成一个新进程组的组长进程
● 此进程无控制终端。若调用前有,则与终端联系被解除,若该进程为一个进程组组长则返回错误。
守护进程
守护进程是在后台运行不受终端控制的进程。一般的网络服务都是以守护进程的方式运行。 独立于控制终端并且周期性的执行某种任务或等待处理某些发生的时间。
守护进程脱离终端原因:1、终端在启动守护进程后需要执行其他任务;2、由终端上一些键产生的信号不应对从该终端启动的守护进程造成影响。
创建守护进程过程:
1、 创建fork子进程,父进程退出exit,子进程在后台继续执行
2、 在子进程中创建新会话:setsid
3、 改变当前目录为根目录:chdir
4、 重设文件权限掩码:umask,设置进程的umask为0。进程从父进程那里继承了文件创建掩码。他可能修改守护进程所创建的文件存取位,为防止这一点需将其清除umask(0)
5、 关闭文件描述符:子进程中关闭任何不需要的文件描述符。进程从父进程那里继承了打开的文件描述符,不关闭会浪费系统资源。
6、 处理SIGCHLD信号:并不是必须得,对于某些进程(服务器进程)往往在请求到来时生成子进程处理请求。若父进程不等待子进程结束,子进程就会变成僵尸进程从而占用系统资源。若等待会增加父进程负担影响服务器并发性能。Linux可以将SIGCHLD信号操作设为SIG_IGN,内核在子进程结束时不会产生僵尸进程。
void creat_daemon(void)
{
pid_t pid;
pid = fork();
if( pid == -1)
ERR_EXIT("fork error");
if(pid > 0 )
exit(EXIT_SUCCESS);
if(setsid() == -1)
ERR_EXIT("SETSID ERROR");
chdir("/");
int i;
for( i = 0; i < 3; ++i)
{
close(i);
open("/dev/null", O_RDWR);
dup(0);
dup(0);
}
umask(0);
return;
}