zoukankan      html  css  js  c++  java
  • 第十五章 进程池与线程池

    第十五章 进程池与线程池


    15.1 进程池和线程池概述

    进程池是由服务器预先创建的一组子进程,线程池中的线程数量应该和CPU数量差不多.

    • 进程池中的所有子进程都运行着相同的代码,并具有相同的属性,比如优先级,PGID等等。因为进程池在服务器启动之初就创建好了,所以每个子进程都相对“干净”,即他们没有打开不必要的文件描述符(从父进程继承而来),也不会错误地使用大块的堆内存(从父进程复制得到)

    15.2 进程池内的进程如何被唤醒

    当有新的任务到来时,主进程将通过某种方式选择进程池中的某一个子进程来为之服务.

    1. 主进程使用某种算法主动选择子进程。最简单、最常用的算法是随机算法和Round-Robin(轮流选取)算法,但更优秀、更智能的算法将使任务在各个工作进程中更均匀地分配、从而减轻服务器的整体压力。

    2. 主进程和所有子进程通过一个共享的工作队列来同步,子进程都睡眠在该工作队列上。当有心的任务到来时,主进程将任务添加到工作队列中。这将唤醒正在等待任务的子进程,不过只有一个子进程获得新任务的“接管权”,它可以从工作队列中取出并执行之,而其他子进程将继续睡眠在工作队列上。

    觉得这个过程有点类似于CPU的调度.


    15.3 进程池的实现

    这一章之前有一个问题困扰着我,就是究竟如何创建一个进程池,如何回收.

    //创建process_number个子进程,并建立它们和父进程之间的管道
    for(int i = 0; i < process_number; i++) 
    {
        int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, m_sub_process[i].m_pipefd);
        assert(ret == 0);
    
        m_sub_process[i].m_pid = fork();
        assert(m_sub_process[i].m_pid >= 0);
    	// 主进程关闭写
        if (m_sub_process[i].m_pid > 0) 
        {
            close(m_sub_process[i].m_pipefd[1]);
            continue;
        }
    	// 子进程关闭读
        else
        {
            close(m_sub_process[i].m_pipefd[0]);
            m_idx = i;
            break;
        }
    	//这就意味着子进程要发送给主进程信号
    }
    
    ...
    for(int i = 0; i < number; i ++)
    {
        int sockfd = events[i].data.fd;
        if (sockfd == m_listenfd) 
        {
            //如果有新连接到来,就采用Round
            //Robin方式将其分配给一个子进程处理
            int i = sub_process_counter;
            do
            {
                if (m_sub_process[i].m_pid != -1) 
                {
                    break;
                }
                i = (i + 1)%m_process_number;
            }
            while(i != sub_process_counter);
    
            if (m_sub_process[i].m_pid == -1) 
            {
                m_stop = true;
                break;
            }
    
            sub_process_counter = (i + 1)%m_process_number;
            send(m_sub_process[i].m_pipefd[0],
                    (char *)&new_conn, sizeof(new_conn), 0);
            printf("send request to child %d
    ", i);
        }
    	// 处理父进程收到的信号,对子进程的行为做出判断和抉择.
    	// 如若关闭了就回收它.若全部退出了,则主进程也退出.
    	// ...
    }
    

    关于第十五章的总结

    • 不深入的了解了进程/线程池的具体实现.

    From

    Linux 高性能服务器编程 游双著 机械工业出版社

    MarkdownPad2

    Aaron-z/linux-server-high-performance

    2017/2/13 15:09:45

  • 相关阅读:
    方差、协方差、相关系数的理解
    yii2原生sql
    Oracle中日期作为条件的查询
    IDEA 中tomcat图片储存和访问虚拟路径(图片和程序分家)
    nginx配置静态资源:配置绝对路径
    一般spring配置上下文
    spring boot 集成 redis lettuce(jedis)
    windows下面同时部署多个tomcat的方法
    oracel: 通过特殊表序列来实现oracle自增id (mybatis实现自增id)
    使用fastjson 进行jsonObject转实体类对象
  • 原文地址:https://www.cnblogs.com/leihui/p/6394465.html
Copyright © 2011-2022 走看看