21xrx.com
2025-01-12 14:45:59 Sunday
文章检索 我的文章 写文章
C++进程池实现详解
2023-06-29 15:05:22 深夜i     6     0
C++ 进程池 实现 详解 多进程编程

进程池是一种常见的网络编程技术,它可以通过提前创建一定数量的子进程来减少进程的创建和销毁,从而有效地提高程序的性能和稳定性。在 C++ 中,通过使用多进程模型和进程池技术,可以实现高效的网络服务器程序。

下面是一个简单的 C++ 进程池实现,它使用系统调用函数 fork() 来创建子进程,通过信号量实现进程的同步和互斥,从而实现对客户端请求的处理:

1. 定义进程池类

class ProcessPool {
public:
  ProcessPool(int listenfd, int processNumber);
  ~ProcessPool();
  void run();
private:
  static const int MAX_PROCESS_NUMBER = 16;
  static const int USER_PER_PROCESS = 65536;
  static const int MAX_EVENT_NUMBER = 10000;
  int m_listenfd;
  int m_processNumber;
  int m_idx;
  int m_epollfd;
  int m_stop;
  std::vector<childProcess> m_processes;
  static int* m_pipe;
  static int m_epollfd;
};

2. 创建子进程类

struct childProcess {
  pid_t pid;
  int m_pipefd[2];
};
int* ProcessPool::m_pipe = 0;
int ProcessPool::m_epollfd = 0;
void setnonblocking(int fd);
void addfd(int epollfd, int fd, bool one_shot);
void removefd(int epollfd, int fd);
void sig_handler(int sig);
void addsig(int sig, void(handler)(int), bool restart = true);
void childMain(int idx, int listenfd, int pipefd);

3. 进程池构造函数实现

ProcessPool::ProcessPool(int listenfd, int processNumber): m_listenfd(listenfd), m_processNumber(processNumber), m_idx(-1), m_stop(false) {
  assert((processNumber > 0) && (processNumber <= MAX_PROCESS_NUMBER));
  m_processes.resize(processNumber);
  for (int i = 0; i < processNumber; ++i) {
    int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, m_processes[i].m_pipefd);
    assert (ret == 0);
    m_processes[i].pid = fork();
    assert (m_processes[i].pid >= 0);
    if (m_processes[i].pid > 0) { // 父进程
      close(m_processes[i].m_pipefd[1]);
      continue;
    }
    else { // 子进程
      close(m_processes[i].m_pipefd[0]);
      m_idx = i;
      break;
    }
  }
}

4. 进程池主函数 run() 实现

void ProcessPool::run() {
  if (m_idx >= 0) {
    childMain(m_idx, m_listenfd, m_processes[m_idx].m_pipefd[1]);
    exit(0);
  }
  for (int i = 0; i < m_processNumber; ++i) {
    addfd(m_epollfd, m_processes[i].m_pipefd[0], false);
  }
  struct epoll_event events[MAX_EVENT_NUMBER];
  while (!m_stop) {
    int number = epoll_wait(m_epollfd, events, MAX_EVENT_NUMBER, -1);
    if ((number < 0) && (errno != EINTR))
      break;
    
    for (int i = 0; i < number; ++i) {
      int sockfd = events[i].data.fd;
      if (sockfd == m_processes[m_idx].m_pipefd[0] && (events[i].events & EPOLLIN)) {
        int client = 0;
        int ret = recv(sockfd, (void*)&client, sizeof(client), 0);
        if (((ret < 0) && (errno != EAGAIN)) || ret == 0)
          continue;
        
        else {
          struct sockaddr_in client_address;
          socklen_t client_addrlength = sizeof(client_address);
          int connfd = accept(m_listenfd, (struct sockaddr*)&client_address, &client_addrlength);
          if (connfd < 0)
            continue;
          
          addfd(m_epollfd, connfd, true);
        }
      }
      else if (events[i].events & EPOLLIN) {
        char msg[1024];
        memset(msg, 0, sizeof(msg));
        int ret = recv(sockfd, msg, sizeof(msg), 0);
        if (ret < 0)
          continue;
        
        else if (ret == 0) {
          removefd(m_epollfd, sockfd);
          continue;
        }
        else {
          send(sockfd, msg, strlen(msg), 0);
        }
      }
    }
  }
}

以上就是 C++ 进程池实现的详细介绍。进程池虽然可以提高并发性和稳定性,但同时,它的复杂性也更高一些。因此,在使用时需要特别注意代码的实现和代码可靠性。

  
  

评论区