#pragma once
#include <string>
#include <iostream>
// PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
// 73491 73539 73539 73539 pts/5 74474 Ss 0 0:00 -bash
// 73539 74347 74347 73539 pts/5 74456 S 0 0:00 sleep 1000
// 73539 74451 74451 73539 pts/5 74456 S 0 0:00 sleep 1000
// 73539 74452 74451 73539 pts/5 74456 S 0 0:00 sleep 2000
// 73539 74453 74451 73539 pts/5 74456 S 0 0:00 sleep 30000
// 父进程(bash) 进程组id 会话id
// 登录云服务器,其实就是系统提供一个bash和命令行解释(构建一个会话),后续启动的其他进程组
// 只要在一个窗口,会话id和bash一样,属于同一个会话
// 守护进程是一个新的独立的会话(可以理解为又打开一个窗口,登录云服务器,只不过这次没有bash)
// (只有你刚才启动的进程)
// 注意:守护进程不能是一个进程组的组长
// 每个会话都必须有一个会话组长(session leader),并且这个组长在会话的生命周期内是唯一的。
// 会话组长负责代表该会话接收来自系统的信号,比如来自终端的信号(如SIGHUP,当终端被关闭时发送)
// 当一个进程调用setsid()时,它实际上是在请求系统创建一个新的会话,并让该进程成为这个新会话的组长。
// 然而,如果进程已经是某个会话的组长,那么它就不能再成为另一个会话的组长,
// 我一旦去做别的组长了,我原来的组组长就没了,原来的组怎么接受系统的信号
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
const std::string root = "/";
// 凡是向null文件写的直接被丢弃,凡是向null里面读的直接读到文件结尾
const char *dev_null = "/dev/null";
void MY_Daemon(bool ischdir)
{
// 忽略sigchld信号,不用等待回收子进程
signal(SIGCHLD, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
// 创建子进程让自己不成为组长
if (fork())
exit(0);
// 后续都是子进程
// 让自己成为一个新的会话
setsid();
// 是否改变当前进程的cwd,
if (ischdir)
chdir(root.c_str());
// 已经是新的回话了,prinf的内容就别再往显示器上打了
int fd = open(dev_null,O_RDWR);
if(fd>0)
{
dup2(fd,0);
dup2(fd,1);
dup2(fd,2);
}
}
【守护进程】
最新推荐文章于 2024-08-19 11:45:37 发布