文章目录

一、基本概念

  • 守护进程: 后台执行,运行周期长,无需和用户交互
  • 会话:打开一个终端,就会随之产生一个会话
  • 会话首进程:会话中运行的第一个进程,一般来说是​​/usr/bin/bash​
  • 进程组:对于单进程程序,进程组中只有一个进程;对于多进程程序,进程组有多个进程
  • 组长进程:进程组的第一个进程

Linux守护进程_子进程


对于服务而言,不应该随着终端的结束而结束,启动了服务就需要一直在后台运行。我们可以新建一个会话,然后把服务对应的进程移动到新的会话。

而用于建立新会话的进程需要是普通的组员进程(不能是组长进程,更不能是会话首进程),因为会使用进程的id作为会话的id,如果原来这个进程就是一个会话首进程,那么这个进程的id已经标识了一个会话,再使用这个进程id标识会话就会重复

1. 会话id == 会话首进程id

int main(){
printf("sid=%d, pid=%d\n", getsid(0), getpid());
return 0;
}

Linux守护进程_运维_02


2. 组长进程id == 进程组id

int main(){
// 会话id,进程id,进程组id
printf("sid=%d, pid=%d, gid=%d\n", getsid(0), getpid(), getpgrp());
return 0;
}

Linux守护进程_子进程_03

3. 父子进程同一进程组,同一会话

int main(){
pid_t pid = fork();
if(pid == 0){
printf("子进程:sid=%d, pid=%d, gid=%d\n", getsid(0), getpid(), getpgrp());
}else{
printf("父进程:sid=%d, pid=%d, gid=%d\n", getsid(0), getpid(), getpgrp());
}
return 0;
}
父进程:sid=303, pid=1106, gid=1106
子进程:sid=303, pid=1107, gid=1106

进程组什么时候消失?
进程组中最后一个进程消失的时候进程组就消失,而不是组长进程结束就消失

二、创建守护进程

面试可能问到的编程流程:

  1. fork():产生子进程后,退出父进程
  2. setsid():创建新的会话,使得原来的进程脱离会话,进入新的会话,成为会话首进程
  3. fork():产生孙子进程后,退出儿子进程。这一步可省略,使得留下的孙子进程没有会话首进程的身份,这样留下的进程就不会和某个终端关联起来,起保险作用
  4. 为了守护进程能长久运行做准备,由于不用stdin、stdout等,关闭所有不用的描述符
  5. 由于守护进程运行时间长,所以需要把该进程的工作目录移动至​​/​​目录,防止守护进程占用长期占用工作空间,其他进程无法使用
  6. 若产生子进程,需要处理僵尸进程。因为父进程一直不结束,也不处理,就会产生大量僵尸进程
  7. umask(0),掩码设置为0后,创建出来的文件权限就是当前用户所具有的全部权限

Linux守护进程_运维_04

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>

void set_demon(){
pid_t pid = fork();
if(pid != 0){
// 退出父进程
exit(0);
}
// 创建新会话
setsid();
// 退出当前会话的首进程,孙子进程成为会话唯一进程
pid = fork();
if(pid != 0){
// 退出父进程
exit(0);
}
// 设置工作路径
chdir("/");
umask(0);
// 拿到打开文件描述符的最大数量
int open_size = getdtablesize();
for(int i = 0; i < open_size; i++){
// 关闭所有能打开的描述符
close(i);
}
}


int main(){
set_demon(); // 当前进程设置为守护进程
while(1){
// 任何用户都可在/tmp下创建文件
FILE* fp = fopen("/tmp/guard_process.log", "a");
if(NULL == fp){
break;
}
time_t tv;
// 获取从1970年经过的秒数
time(&tv);
fprintf(fp, "%s", asctime(localtime(&tv)));
fclose(fp); // 这里不关闭,下次循环再fopen,返回的fp不一样,日志文件也无法写入新的信息
sleep(5);
}
return 0;
}

Linux守护进程_linux_05


看日志文件,一般使用:​​tail -f 1.log​​,tail命令动态追踪文件并打印到终端