21xrx.com
2024-09-20 00:43:33 Friday
登录
文章检索 我的文章 写文章
C++进程池实现详解
2023-06-29 15:05:22 深夜i     --     --
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++ 进程池实现的详细介绍。进程池虽然可以提高并发性和稳定性,但同时,它的复杂性也更高一些。因此,在使用时需要特别注意代码的实现和代码可靠性。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复