【slighttpd】基於lighttpd架構的Server專案實戰(3)—Master&Worker模式
阿新 • • 發佈:2018-11-13
轉載地址:https://blog.csdn.net/jiange_zh/article/details/50636180
現在,我們開始一步步構建我們的專案了~
Master-Worker模式
本次一共涉及2個類:Master和Worker;
以下是兩者的標頭檔案:
/************************************************************************* > File Name: server.h > Author: Jiange > Mail: [email protected]
> Created Time: 2016年01月27日 星期三 19時33分00秒 ************************************************************************/ #ifndef _MASTER_H #define _MASTER_H #include "worker.h" #include <string> #include "event2/event.h" #include "event2/util.h" class Master { public: Master(); ~Master(); bool StartMaster(); static void MasterExitSignal(evutil_socket_t signo, short event, void *arg); //SIGINT訊號回撥函式 static void MasterChldSignal(evutil_socket_t signo, short event, void *arg); Worker worker; struct event_base *m_base; struct event *m_exit_event; struct event *m_chld_event; int nums_of_child; //子程序個數 }; #endif
/************************************************************************* > File Name: worker.h > Author: Jiange > Mail: [email protected] > Created Time: 2016年01月27日 星期三 20時10分35秒 ************************************************************************/ #ifndef _WORKER_H #define _WORKER_H #include <string> #include <map> #include "event2/event.h" #include "event2/util.h" #include "util.h" class Master; class Worker { public: Worker(); ~Worker(); void Run(); static void WorkerExitSignal(evutil_socket_t signo, short event, void *arg); Master *master; struct event_base *w_base; struct event *w_exit_event; std::string s_inbuf; std::string s_intmp; std::string s_outbuf; }; #endif
具體實現:
/*************************************************************************
> File Name: master.cpp
> Author: Jiange
> Mail: [email protected]
> Created Time: 2016年01月27日 星期三 19時37分23秒
************************************************************************/
#include "master.h"
#include "worker.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
Master::Master()
{
m_base = NULL;
m_exit_event = NULL;
m_chld_event = NULL;
nums_of_child = 4; //4個子程序
}
Master::~Master()
{
if (m_base) {
event_free(m_exit_event);
event_free(m_chld_event);
event_base_free(m_base);
}
std::cout << "Master Closed" << std::endl;
}
bool Master::StartMaster()
{
std::cout <, "Start Master" << std::endl;
worker.master = this;
//建立一定數量的worker
while (nums_of_child > 0)
{
switch(fork()) {
case -1:
return false;
case 0:
{
worker.Run(); //worker子程序入口
return true;
}
default:
--nums_of_child;
break;
}
}
//Master監聽訊號,一個用於退出,一個用於處理結束的子程序
m_base = event_base_new();
m_exit_event = evsignal_new(m_base, SIGINT, Master::MasterExitSignal, m_base);
m_chld_event = evsignal_new(m_base, SIGCHLD, Master::MasterChldSignal, this);
evsignal_add(m_exit_event, NULL);
evsignal_add(m_chld_event, NULL);
//開始事件迴圈
event_base_dispatch(m_base);
return true;
}
void Master::MasterExitSignal(evutil_socket_t signo, short event, void *arg)
{
//通知所有子程序,暫時不需要,因為程式不是守護程序。
//所有子程序都跟終端關聯,都會收到SIGINT
//kill(0, SIGINT);
//結束事件迴圈
event_base_loopexit((struct event_base *)arg, NULL);
}
//防止子程序僵死,使用waitpid而不是wait->可能多個子程序同時關閉
void Master::MasterChldSignal(evutil_socket_t signo, short event, void *arg)
{
Master *master = (Master *)arg;
pid_t pid;
int stat;
while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) {
++(master->nums_of_child);
std::cout << "Child " << pid << " terminated" << std::endl;
}
}
/*************************************************************************
> File Name: worker.cpp
> Author: Jiange
> Mail: [email protected]
> Created Time: 2016年01月28日 星期四 12時06分22秒
************************************************************************/
#include "worker.h"
#include "master.h"
#include <stdlib.h>
#include <iostream>
Worker::Worker()
{
master = NULL;
w_base = NULL;
w_exit_event = NULL;
}
Worker::~Worker()
{
if (w_exit_event)
event_free(w_exit_event);
if (w_base)
event_base_free(w_base);
std::cout << "Worker closed" << std::endl;
}
void Worker::Run()
{
w_base = event_base_new();
w_exit_event = evsignal_new(w_base, SIGINT, Worker::WorkerExitSignal, w_base);
evsignal_add(w_exit_event, NULL);
event_base_dispatch(w_base);
return;
}
void Worker::WorkerExitSignal(evutil_socket_t signo, short event, void *arg)
{
event_base_loopexit((struct event_base *)arg, NULL);
}
這樣子,一個簡單的“Master-Worker模式”就完成了。
測試入口:
/*************************************************************************
> File Name: main.cpp
> Author: Jiange
> Mail: [email protected]
> Created Time: 2016年01月27日 星期三 19時29分26秒
************************************************************************/
#include "master.h"
#include <iostream>
int main(int argc, char *argv[])
{
Master master;
std::cout << "----Slighttpd ----" << std::endl;
if (!master.StartMaster())
return -1;
std::cout << "-----Goodbye-----" << std::endl;
return 0;
}
需要注意的幾個點:
1.Master和Worker所做的事情是不同的,因此兩者均有自己獨立的event_base;
2.worker的event_base_new()需要在run()函式中使用(在fork之後),而不能在建構函式中初始化分配(fork之前)。否則,好像4個子程序將公用同一個event_base。(Q:按理來說fork應該是完全複製過來的,為什麼會共用同一個呢?可能是跟libevent的實現方式有關?)
接下來,我們需要對它進行拓展,以後將在Master中加入外掛相關的內容,在Worker中加入監聽者Listener和連線者Connection。