html5教育网站,南平高速建设有限公司网站,做一个营销型网站有哪些内容,外贸营销模板目录
一、守护进程的定义与特点
1、定义
2、特点
二、守护进程的原理
三、守护进程与会话#xff08;Session#xff09;的关系
四、C实现守护进程 守护进程#xff08;Daemon Process#xff09;是一个在后台运行、通常不与用户直接交互的进程。守护进程是操作系统中…目录
一、守护进程的定义与特点
1、定义
2、特点
二、守护进程的原理
三、守护进程与会话Session的关系
四、C实现守护进程 守护进程Daemon Process是一个在后台运行、通常不与用户直接交互的进程。守护进程是操作系统中非常重要的一部分常见的应用包括系统日志、网络服务、数据库管理等。在这篇博客中我们将详细探讨守护进程的原理、如何与会话管理联系并通过C实现一个简单的守护进程。将服务器守护进程化的主要目的是确保服务器在后台持续运行并在意外崩溃或重启后自动恢复。这样可以使服务在没有人工干预的情况下长期稳定运行并减少系统管理的复杂度。
一、守护进程的定义与特点
1、定义
守护进程是一个没有终端控制的进程它通常在系统启动时启动独立于任何用户会话session并且在后台持续运行。守护进程的特点是它不依赖于用户的输入输出运行时不会产生终端交互。
2、特点
后台运行守护进程通常在操作系统启动时启动或者在用户登录后由系统服务启动并在后台持续运行。无终端守护进程不与任何终端或用户会话关联它通常不与标准输入输出stdin, stdout, stderr相关联。独立性守护进程与用户的登录会话是独立的它在后台静静运行执行系统级任务如日志记录、定时任务、文件清理等。父进程为init进程守护进程在系统启动时由父进程通常是init进程启动运行时不会退出。PID进程ID守护进程的PID是由操作系统分配的它通常会被写入到某个文件中以供后续管理和终止。 二、守护进程的原理
守护进程是通过脱离控制终端、使自己成为一个独立的后台进程来实现的。这是通过几个步骤实现的 创建子进程守护进程首先会创建一个子进程父进程退出子进程继续执行这样可以让守护进程避免与任何用户会话或终端直接交互。 创建新的会话Session守护进程通常会调用 setsid() 系统调用创建一个新的会话成为该会话的首进程。新会话的创建意味着它不再与原始的控制终端和进程组相关联。 改变工作目录守护进程通常会调用 chdir() 来更改工作目录。为了避免占用终端的目录守护进程通常会将工作目录更改为 /。 关闭文件描述符守护进程还会关闭与终端相关的文件描述符包括标准输入stdin、标准输出stdout、标准错误stderr。通常会将它们重定向到 /dev/null以防止输出到终端。 忽略信号守护进程会设置适当的信号处理避免因收到如SIGHUP等信号导致进程退出。
void Daemon(const std::string cwd )
{// 1. 忽略其他异常信号 signal(SIGCLD, SIG_IGN);signal(SIGPIPE, SIG_IGN);signal(SIGSTOP, SIG_IGN);// 2. 将自己变成独立的会话if (fork() 0)//0说明是父进程让父进程直接退出exit(0);setsid(); //子进程// 3. 更改当前调用进程的工作目录if (!cwd.empty())chdir(cwd.c_str());// 4. 标准输入标准输出标准错误重定向至/dev/null 垃圾桶int fd open(nullfile.c_str(), O_RDWR);if(fd 0){dup2(fd, 0);dup2(fd, 1);dup2(fd, 2);close(fd);}
} 三、守护进程与会话Session的关系
会话Session是与进程、终端和进程组密切相关的概念。会话的作用是管理一组相关的进程。 会话的创建每个登录的用户会话都有一个会话IDSession ID一个会话可以有多个进程组Process Group而每个进程组中的进程共享同一个控制终端。 脱离控制终端守护进程通过 setsid() 系统调用来脱离当前会话及其控制终端成为一个新的会话的首进程。这样守护进程就不再与任何终端关联它可以自由地运行而不受用户的控制。 控制终端一旦守护进程创建了新的会话并成为首进程它就不再与任何控制终端关联。控制终端通常与用户的登录会话相关联但守护进程会断开这一关系避免终端输入或输出干扰其运行。 进程组与信号处理会话中的进程通常共享进程组而进程组的控制由会话首进程管理。守护进程通常会设置信号处理机制使其能够管理来自进程组的信号。 四、C实现守护进程
#pragma once#include iostream
#include cstdlib
#include unistd.h
#include signal.h
#include string
#include sys/types.h
#include sys/stat.h
#include fcntl.hconst std::string nullfile /dev/null;void Daemon(const std::string cwd )
{// 1. 忽略其他异常信号 signal(SIGCLD, SIG_IGN);signal(SIGPIPE, SIG_IGN);signal(SIGSTOP, SIG_IGN);// 2. 将自己变成独立的会话if (fork() 0)//0说明是父进程让父进程直接退出exit(0);setsid(); //子进程// 3. 更改当前调用进程的工作目录if (!cwd.empty())chdir(cwd.c_str());// 4. 标准输入标准输出标准错误重定向至/dev/null 垃圾桶int fd open(nullfile.c_str(), O_RDWR);if(fd 0){dup2(fd, 0);dup2(fd, 1);dup2(fd, 2);close(fd);}
}
#pragma once#include iostream
#include string
#include cstdlib
#include cstring
#include unistd.h
#include sys/wait.h
#include sys/types.h
#include sys/socket.h
#include arpa/inet.h
#include netinet/in.h
#include pthread.h
#include signal.h
#include signal.h
#include Log.hpp
#include ThreadPool.hpp
#include Task.hpp
#include Daemon.hppconst int defaultfd -1;
const std::string defaultip 0.0.0.0;
const int backlog 10; // 但是一般不要设置的太大
extern Log lg;enum
{UsageError 1,SocketError,BindError,ListenError,
};class TcpServer;class ThreadData
{
public:ThreadData(int fd, const std::string ip, const uint16_t p, TcpServer *t): sockfd(fd), clientip(ip), clientport(p), tsvr(t){}
public:int sockfd;std::string clientip;uint16_t clientport;TcpServer *tsvr;
};class TcpServer
{
public:TcpServer(const uint16_t port, const std::string ip defaultip) : listensock_(defaultfd), port_(port), ip_(ip){}void InitServer(){listensock_ socket(AF_INET, SOCK_STREAM, 0);if (listensock_ 0){lg(Fatal, create socket, errno: %d, errstring: %s, errno, strerror(errno));exit(SocketError);}lg(Info, create socket success, listensock_: %d, listensock_);int opt 1;setsockopt(listensock_, SOL_SOCKET, SO_REUSEADDR|SO_REUSEPORT, opt, sizeof(opt)); // 防止偶发性的服务器无法进行立即重启(tcp协议的时候再说)struct sockaddr_in local;memset(local, 0, sizeof(local));local.sin_family AF_INET;local.sin_port htons(port_);inet_aton(ip_.c_str(), (local.sin_addr));// local.sin_addr.s_addr INADDR_ANY;if (bind(listensock_, (struct sockaddr *)local, sizeof(local)) 0){lg(Fatal, bind error, errno: %d, errstring: %s, errno, strerror(errno));exit(BindError);}lg(Info, bind socket success, listensock_: %d, listensock_);// Tcp是面向连接的服务器一般是比较“被动的”服务器一直处于一种一直在等待连接到来的状态if (listen(listensock_, backlog) 0){lg(Fatal, listen error, errno: %d, errstring: %s, errno, strerror(errno));exit(ListenError);}lg(Info, listen socket success, listensock_: %d, listensock_);}void Start(){Daemon();ThreadPoolTask::GetInstance()-Start();// for fork();// signal(SIGCHLD, SIG_IGN);lg(Info, tcpServer is running....);for (;;){// 1. 获取新连接struct sockaddr_in client;socklen_t len sizeof(client);int sockfd accept(listensock_, (struct sockaddr *)client, len);if (sockfd 0){lg(Warning, accept error, errno: %d, errstring: %s, errno, strerror(errno)); //?continue;}uint16_t clientport ntohs(client.sin_port);char clientip[32];inet_ntop(AF_INET, (client.sin_addr), clientip, sizeof(clientip));// version 4 --- 线程池版本Task t(sockfd, clientip, clientport);ThreadPoolTask::GetInstance()-Push(t);}}~TcpServer() {}private:int listensock_;uint16_t port_;std::string ip_;
};表示服务已经启动