linux高性能服务器编程(Linux高性能服务器编程:使用muduo C++网络库)

      最后更新:2022-11-08 10:32:18 手机定位技术交流文章

      关于linux学习路线的问题 请教前辈

      很多同学接触Linux不多,对Linux平台的开发更是一无所知。而现在的趋势越来越表明,作为一 个优秀的软件开发人员,或计算机IT行业从业人员,掌握Linux是一种很重要的谋生资源与手段。下来我将会结合自己的几年的个人开发经验,及对 Linux,更是类UNIX系统,及开源软件文化,谈谈Linux的学习方法与学习中应该注意的一些事。 就如同刚才说的,很多同学以前可能连Linux是什么都不知道,对UNIX更是一无所知。所以我们从最基础的讲起,对于Linux及UNIX的历史我们不做多谈,直接进入入门的学习。Linux入门是很简单的,问题是你是否有耐心,是否爱折腾,是否不排斥重装一类的大修。没折腾可以说是学不好Linux的,鸟哥说过,要真正了解Linux的分区机制,对LVM使用相当熟练,没有20次以上的Linux装机经验是积累不起来的,所以一定不要怕折腾。由于大家之前都使用Windows,所以我也尽可能照顾这些“菜鸟”。我的推荐,如果你第一次接触Linux,那么首先在虚拟机中尝试它。虚拟机我推荐Virtual Box,我并不主张使用VM,原因是VM是闭源的,并且是收费的,我不希望推动盗版。当然如果你的Money足够多,可以尝试VM,但我要说的是即使是VM,不一定就一定好。付费的软件不一定好。首先,Virtual Box很小巧,Windows平台下安装包在80MB左右,而VM动辄600MB,虽然功能强大,但资源消耗也多,何况你的需求Virtual Box完全能够满足。所以,还是自己选。如何使用虚拟机,是你的事,这个我不教你,因为很简单,不会的话Google或Baidu都可以,英文好的可以直接看官方文档。现在介绍Linux发行版的知识。正如你所见,Linux发行版并非Linux,Linux仅是指操作系统的内核,作为科班出生的你不要让我解释,我也没时间。我推荐的发行版如下:UBUNTU适合纯菜鸟,追求稳定的官方支持,对系统稳定性要求较弱,喜欢最新应用,相对来说不太喜欢折腾的开发者。Debian,相对UBUNTU难很多的发行版,突出特点是稳定与容易使用的包管理系统,缺点是企业支持不足,为社区开发驱动。Arch,追逐时尚的开发者的首选,优点是包更新相当快,无缝升级,一次安装基本可以一直运作下去,没有如UBUNTU那样的版本概念,说的专业点叫滚动升级,保持你的系统一定是最新的。缺点显然易见,不稳定。同时安装配置相对Debian再麻烦点。Gentoo,相对Arch再难点,考验使用者的综合水平,从系统安装到微调,内核编译都亲历亲为,是高手及黑客显示自己技术手段,按需配置符合自己要求的系统的首选。Slackware与Gentoo类似。CentOS,社区维护的RedHat的复刻版本,完全使用RedHat的源码重新编译生成,与RedHat的兼容性在理论上来说是最好的。如果你专注于Linux服务器,如网络管理,架站,那么CentOS是你的选择。LFS,终极黑客显摆工具,完全从源代码安装,编译系统。安装前你得到的只有一份文档,你要做的就是照文档你的说明,一步步,一条条命令,一个个软件包的去构建你的Linux,完全由你自己控制,想要什么就是什么。如果你做出了LFS,证明你的Linux功底已经相当不错,如果你能拿LFS文档活学活用,再将Linux从源代码开始移植到嵌入式系统,我敢说中国的企业你可以混的很好。你得挑一个适合你的系统,然后在虚拟机安装它,开始使用它。如果你想快速学会Linux,我有一个建议就是忘记图形界面,不要想图形界面能不能提供你问题的答案,而是满世界的去找,去问,如何用命令行解决你的问题。在这个过程中,你最好能将Linux的命令掌握的不错,起码常用的命令得知道,同时建立了自己的知识库,里面是你积累的各项知识。再下个阶段,你需要学习的是Linux平台的C/C++开发,同时还有Bash脚本编程,如果你对Java兴趣很深还有Java。同样,建议你抛弃掉图形界面的IDE,从VIM开始,为什么是VIM,而不是Emacs,我无意挑起编辑器大战,但我觉得VIM适合初学者,适合手比较笨,脑袋比较慢的开发者。Emacs的键位太多,太复杂,我很畏惧。然后是GCC,Make,Eclipse(Java,C++或者)。虽然将C++列在了Eclipse中,但我并不推荐用IDE开发C++,因为这不是Linux的文化,容易让你忽略一些你应该注意的问题。IDE让你变懒,懒得跟猪一样。如果你对程序调试,测试工作很感兴趣,GDB也得学的很好,如果不是GDB也是必修课。这是开发的第一步,注意我并没有提过一句Linux系统API的内容,这个阶段也不要关心这个。你要做的就是积累经验,在Linux平台的开发经验。我推荐的书如下:C语言程序设计,谭浩强的也可以。C语言,白皮书当然更好。C++推荐C++ Primer Plus,Java我不喜欢,就不推荐了。工具方面推荐VIM的官方手册,GCC中文文档,GDB中文文档,GNU开源软件开发指导(电子书),汇编语言程序设计(让你对库,链接,内嵌汇编,编译器优化选项有初步了解,不必深度)。如果你这个阶段过不了就不必往下做了,这是底线,最基础的基础,否则离开,不要霍霍Linux开发。不专业的Linux开发者作出的程序是与Linux文化或UNIX文化相背的,程序是走不远的,不可能像Bash,VIM这些神品一样。所以做不好干脆离开。接下来进入Linux系统编程,不二选择,APUE,UNIX环境高级编程,一遍一遍的看,看10遍都嫌少,如果你可以在大学将这本书翻烂,里面的内容都实践过,有作品,你口头表达能力够强,你可以在面试时说服所有的考官。(可能有点夸张,但APUE绝对是圣经一般的读物,即使是Windows程序员也从其中汲取养分,Google创始人的案头书籍,扎尔伯克的床头读物。)这本书看完后你会对Linux系统编程有相当的了解,知道Linux与Windows平台间开发的差异在哪?它们的优缺点在哪?我的总结如下:做Windows平台开发,很苦,微软的系统API总在扩容,想使用最新潮,最高效的功能,最适合当前流行系统的功能你必须时刻学习。Linux不是,Linux系统的核心API就100来个,记忆力好完全可以背下来。而且经久不变,为什么不变,因为要同UNIX兼容,符合POSIX标准。所以Linux平台的开发大多是专注于底层的或服务器编程。这是其优点,当然图形是Linux的软肋,但我站在一个开发者的角度,我无所谓,因为命令行我也可以适应,如果有更好的图形界面我就当作恩赐吧。另外,Windows闭源,系统做了什么你更本不知道,永远被微软牵着鼻子跑,想想如果微软说Win8不支持QQ,那腾讯不得哭死。而Linux完全开源,你不喜欢,可以自己改,只要你技术够。另外,Windows虽然使用的人多,但使用场合单一,专注与桌面。而Linux在各个方面都有发展,尤其在云计算,服务器软件,嵌入式领域,企业级应用上有广大前景,而且兼容性一流,由于支持POSIX可以无缝的运行在UNIX系统之上,不管是苹果的Mac还是IBM的AS400系列,都是完全支持的。另外,Linux的开发环境支持也绝对是一流的,不管是C/C++,Java,Bash,Python,PHP,Javascript,。。。。。。就连C#也支持。而微软除Visual Stdio套件以外,都不怎么友好,不是吗?如果你看完APUE的感触有很多,希望验证你的某些想法或经验,推荐UNIX程序设计艺术,世界顶级黑客将同你分享他的看法。现在是时候做分流了。 大体上我分为四个方向:网络,图形,嵌入式,设备驱动。如果选择网络,再细分,我对其他的不是他熟悉,只说服务器软件编写及高性能的并发程序编写吧。相对来说这是网络编程中技术含量最高的,也是底层的。需要很多的经验,看很多的书,做很多的项目。我的看法是以下面的顺序来看书:APUE再深读 – 尤其是进程,线程,IPC,套接字多核程序设计 - Pthread一定得吃透了,你很NBUNIX网络编程 – 卷一,卷二TCP/IP网络详解 – 卷一 再看上面两本书时就该看了5.TCP/IP 网络详解 – 卷二 我觉得看到卷二就差不多了,当然卷三看了更好,努力,争取看了6.Lighttpd源代码 - 这个服务器也很有名了7.Nginx源代码 – 相较于Apache,Nginx的源码较少,如果能看个大致,很NB。看源代码主要是要学习里面的套接字编程及并发控制,想想都激动。如果你有这些本事,可以试着往暴雪投简历,为他们写服务器后台,想一想全球的魔兽都运行在你的服务器软件上。Linux内核 TCP/IP协议栈 – 深入了解TCP/IP的实现如果你还喜欢驱动程序设计,可以看看更底层的协议,如链路层的,写什么路由器,网卡,网络设备的驱动及嵌入式系统软件应该也不成问题了。当然一般的网络公司,就算百度级别的也该毫不犹豫的雇用你。只是看后面这些书需要时间与经验,所以35岁以前办到吧!跳槽到给你未来的地方!图形方向,我觉得图形方向也是很有前途的,以下几个方面。Opengl的工业及游戏开发,国外较成熟。影视动画特效,如皮克斯,也是国外较成熟。GPU计算技术,可以应用在浏览器网页渲染上,GPU计算资源利用上,由于开源的原因,有很多的文档程序可以参考。如果能进火狐开发,或google做浏览器开发,应该会很好 。嵌入式方向:嵌入式方向没说的,Linux很重要。掌握多个架构,不仅X86的,ARM的,单片机什么的也必须得懂。硬件不懂我预见你会死在半路上,我也想走嵌入式方向,但我觉得就学校教授嵌入式的方法,我连学电子的那帮学生都竞争不过。奉劝大家,一定得懂硬件再去做,如果走到嵌入式应用开发,只能祝你好运,不要碰上像Nokia,Hp这样的公司,否则你会很惨的。驱动程序设计:软件开发周期是很长的,硬件不同,很快。每个月诞生那么多的新硬件,如何让他们在Linux上工作起来,这是你的工作。由于Linux的兼容性很好,如果不是太低层的驱动,基本C语言就可以搞定,系统架构的影响不大,因为有系统支持,你可能做些许更改就可以在ARM上使用PC的硬件了,所以做硬件驱动开发不像嵌入式,对硬件知识的要求很高。可以从事的方向也很多,如家电啊,特别是如索尼,日立,希捷,富士康这样的厂子,很稀缺的。LDD – Linux驱动程序设计与内核编程的基础读物深入理解Linux内核 – 进阶的Linux源代码 – 永无止境的 当然你还的看个方面的书,如网络啊什么的。
      Linux学习,主要学以下内容: 第一阶段:linux基础入门1. 开班课程介绍-规章制度介绍-破冰活动;2. Linux硬件基础/Linux发展历史;3. Linux系统安装/xshell连接/xshell优化/SSH远程连接故障问题排查4. 第一关一大波命令及特殊字符知识考试题讲解5. Linux基础优化6. Linux目录结构知识精讲7. 第二关一大波命令及特殊知识考试题讲解(上)8. 第二关一大波命令及特殊知识考试题讲解(下)9. Linux文件属性一大堆知识精讲10. Linux通配符/正则表达式11. 第三关一大波命令及重要知识考试题讲解(上)12. 第三关一大波命令及重要知识考试题讲解(下)13. Linux系统权限(上)14. Linux系统权限(下)15. 第一阶段结束需要导师或讲师对整体课程进行回顾第二阶段:linux系统管理进阶1. Linux定时任务2. Linux用户管理3. Linux磁盘与文件系统(上)4. Linux磁盘与文件系统(中下)5. Linux三剑客之sed命令第三阶段:Linux Shell基础1. Shell编程基础12. Shell编程基础2343. Linux三剑客之awk命令第四阶段:Linux网络基础1. 计算机网络基础上2. 计算机网络基础下3. 第二阶段结束需要导师或讲师对整体课程进行回顾。第五阶段:Linux网络服务1. 集群实战架构开始及环境准备2. rsync数据同步服务3. Linux全网备份项目案例精讲4. nfs网络存储服务精讲5. inotify/sersync实时数据同步/nfs存储实时备份项目案例精讲第六阶段:Linux重要网络服务1. http协议/www服务基础2. nginx web介绍及基础实践3. nginx web精讲结束4. lnmp环境部署/数据库异机迁移/共享数据异机迁移到NFS系统5. nginx负载均衡深入透彻6. keepalived高可用深入透彻第七阶段:Linux中小规模集群构建与优化(50台)1. 期中架构开战说明+期中架构部署回顾2. 全体昼夜兼程部署期中架构并完成上台述职演讲(加上两个周末共9天)3. kickstart cobbler 批量自动安装系统4. pptp vpn与ntp服务5. memcached原理及部署/作为缓存及session会话共享第八阶段:Ansible自动化运维与Zabbix监控1. SSH服务秘钥认证2. ansible批量自动化管理集群(入门及深入)3. zabbix监控第九阶段:大规模集群高可用服务(Lvs、Keepalived)1. Centos7系统自行安装/centos6与7区别2. lvs负载均衡集群/keepalived管理LVS集群第十阶段:Java Tomcat服务及防火墙Iptables1. iptables防火墙精讲上2. iptables防火墙精讲下3. tomcat java应用服务/nginx配合tomcat服务部署及优化第十一阶段:MySQL DBA高级应用实践1. MySQL数据库入门基础命令2. MySQL数据库进阶备份恢复3. MySQL数据库深入事务引擎4. MySQL数据库优化SQL语句优化5. MySQL数据库集群主从复制/读写分离6. MySQL数据库高可用/mha/keepalved第十二阶段:高性能数据库Redis和Memcached课程第十三阶段:Linux大规模集群架构构建(200台)第十四阶段:Linux Shell编程企业案例实战第十五阶段:企业级代码发布上线方案(SVN和Git)1. GIT管理2. 代码上线项目案例第十六阶段企业级Kvm虚拟化与OpenStack云计算1. KVM虚拟化企业级实战2. OpenStack云计算企业级实战第十七阶段公有云阿里云8大组件构建集群实战第十八阶段:Docker技术企业应用实践1. Docker容器与微服务深入实践2. 大数据Hadoop生态体系及实践第十九阶段:Python自动化入门及进阶 第二十阶段:职业规划与高薪就业指导
      第1阶段 零基础入门第2阶段Linux系统管理&shell编程第3阶段百万级访问量集群实战第4阶段千万级访问量核心集群实战第5阶段一切核心技术的底层支持:云计算集群第6阶段大数据运维第7阶段 Python自动化和指导
      先从基础的视频去看吧,现在有免费的linux视频,百度网盘的地址链接:Linux视频基础课程: http://pan.baidu.com/s/1c13ddvE
      同学,你是想学习Linux,成为linux工程师吗?如果你想成为一名linux工程师,linux的学习是需要学很多东西的,学的东西不光是学习linux系统、还有网络、安全、服务、云计算、脚本、数据库等等。因为这些技能目前国内互联网公司,招聘的时候,都需要对这些技能进行要求。内核不用太花时间去学习,因为这块内容目前以你的程度,还很难掌握。可以学习Linux系统用法,以及上面的主要服务,等你达到一定程度,,再回过头来看内核,就会更容易理解。 想成为合格Linux工程师,需要掌握不少技能,Linux运维工程师讲究的是广度,下面是年薪50W的Linux云计算工程师马哥Linux的学习内容:1、Linux 系统基础⼊门-Linux的基础知识内容,和命令使用,以及用户和权限等核⼼知识点2、Linux 系统管理和进阶-Linux从进程、资源、任务、⽂件、软件包、磁盘等管理⽅法3、Linux 企业常用服务-企业级常用服务如DNS、FTP、Http、mail4、Linux 企业级安全原理和防范技巧以及网络和安全-Linux安全架构、安全威胁模型、以及加密、解密等原理,常见攻击和防范⼿段5、Shell 编程⼊门及进阶-Shell脚本基本用法以及进阶,从基础到精通,需要学习一些企业级常见脚本用法6、MySQL 应用原理及管理⼊门-Mysql安装、管理、授权、增删改查7、http 服务代理缓存加速-http ⾼级协议应用、缓存、web服务nginx8、企业级负载集群-企业级4层负载均衡LVS、和7层负载均衡nginx以及haproxy的应用9、企业级⾼可用集群-⾼可用集群原理,实现以keepalived为核⼼的⾼可用集群,以及主从高可用、双主10、运维监控zabbix-企业级监控体系以及zabbix流⾏开源监控系统的功用及架构11、云计算运维自动化-ansible、puppet等运维自动化解决方案12、WEB 服务体系架构-WEB服务体系架构,JSP体系、tomcat、CDN、缓存原理、压测、评估13、⼤型互联⽹集群架构和实战⽅案-LB集群:nginx、Haproxy、LVS HA集群、动静分离14、MySQL DBA 实战技能和优化-数据库参数优化、分库分表、备份方案、数据恢复策略、主从复制、读写分离、连接池及sharding技术、MHA等15、企业级云计算Openstack-Keystone、Glance、Nova核⼼组件、网络模块、块存储服务等16、企业级⼤数据Hadoop 运维实战-列式数据库HBase基础原理、安装配置及其应⽤、Zookeeper集群构建、hadoop实现Namenode⾼可⽤17、企业级虚拟化KVM 实战-KVM环境:KVM的安装、配置及应⽤18、NoSQL 企业级应用-Nosql 应用,如redis、MongoDB 复制、集群等⾼级应用19、企业级日志收集系统ELK 实战-海量数据日志收集系统Elasticsearch+Logstash+kibana 应用20、可持续化集成-Jenkins+github企业级应用21、虚拟化容器Docker-Linux 轻量虚拟化Docker ,Docker 的原理和安装,配置以及应用22、企业级K8S实战-组件功能、安装、配置、企业级应用场景和常见故障分析23、Linux 系统调优实战-从内存、CPU、进程调度、磁盘IO、⽹络参数等全面讲解Linux系统调优 24、Python 编程基础⼊门-python安装、逻辑判断、模块使用等
      关于linux学习路线的问题 请教前辈

      如何看懂《Linux多线程服务端编程

      一:进程和线程 每个进程有自己独立的地址空间。“在同一个进程”还是“不在同一个进程”是系统功能划分的重要决策点。《Erlang程序设计》[ERL]把进程比喻为人:每个人有自己的记忆(内存),人与人通过谈话(消息传递)来交流,谈话既可以是面谈(同一台服务器),也可以在电话里谈(不同的服务器,有网络通信)。面谈和电话谈的区别在于,面谈可以立即知道对方是否死了(crash,SIGCHLD),而电话谈只能通过周期性的心跳来判断对方是否还活着。有了这些比喻,设计分布式系统时可以采取“角色扮演”,团队里的几个人各自扮演一个进程,人的角色由进程的代码决定(管登录的、管消息分发的、管买卖的等等)。每个人有自己的记忆,但不知道别人的记忆,要想知道别人的看法,只能通过交谈(暂不考虑共享内存这种IPC)。然后就可以思考:·容错:万一有人突然死了·扩容:新人中途加进来·负载均衡:把甲的活儿挪给乙做·退休:甲要修复bug,先别派新任务,等他做完手上的事情就把他重启等等各种场景,十分便利。线程的特点是共享地址空间,从而可以高效地共享数据。一台机器上的多个进程能高效地共享代码段(操作系统可以映射为同样的物理内存),但不能共享数据。如果多个进程大量共享内存,等于是把多进程程序当成多线程来写,掩耳盗铃。“多线程”的价值,我认为是为了更好地发挥多核处理器(multi-cores)的效能。在单核时代,多线程没有多大价值(个人想法:如果要完成的任务是CPU密集型的,那多线程没有优势,甚至因为线程切换的开销,多线程反而更慢;如果要完成的任务既有CPU计算,又有磁盘或网络IO,则使用多线程的好处是,当某个线程因为IO而阻塞时,OS可以调度其他线程执行,虽然效率确实要比任务的顺序执行效率要高,然而,这种类型的任务,可以通过单线程的”non-blocking IO+IO multiplexing”的模型(事件驱动)来提高效率,采用多线程的方式,带来的可能仅仅是编程上的简单而已)。Alan Cox说过:”A computer is a state machine.Threads are for people who can’t program state machines.”(计算机是一台状态机。线程是给那些不能编写状态机程序的人准备的)如果只有一块CPU、一个执行单元,那么确实如Alan Cox所说,按状态机的思路去写程序是最高效的。二:单线程服务器的常用编程模型据我了解,在高性能的网络程序中,使用得最为广泛的恐怕要数”non-blocking IO + IO multiplexing”这种模型,即Reactor模式。在”non-blocking IO + IO multiplexing”这种模型中,程序的基本结构是一个事件循环(event loop),以事件驱动(event-driven)和事件回调的方式实现业务逻辑:[cpp] view plain copy//代码仅为示意,没有完整考虑各种情况while(!done){int timeout_ms = max(1000, getNextTimedCallback());int retval = poll(fds, nfds, timeout_ms);if (retval<0){处理错误,回调用户的error handler}else{处理到期的timers,回调用户的timer handlerif(retval>0){处理IO事件,回调用户的IO event handler}}}这里select(2)/poll(2)有伸缩性方面的不足(描述符过多时,效率较低),Linux下可替换为epoll(4),其他操作系统也有对应的高性能替代品。Reactor模型的优点很明显,编程不难,效率也不错。不仅可以用于读写socket,连接的建立(connect(2)/accept(2)),甚至DNS解析都可以用非阻塞方式进行,以提高并发度和吞吐量(throughput),对于IO密集的应用是个不错的选择。lighttpd就是这样,它内部的fdevent结构十分精妙,值得学习。基于事件驱动的编程模型也有其本质的缺点,它要求事件回调函数必须是非阻塞的。对于涉及网络IO的请求响应式协议,它容易割裂业务逻辑,使其散布于多个回调函数之中,相对不容易理解和维护。三:多线程服务器的常用编程模型大概有这么几种:a:每个请求创建一个线程,使用阻塞式IO操作。在Java 1.4引人NIO之前,这是Java网络编程的推荐做法。可惜伸缩性不佳(请求太多时,操作系统创建不了这许多线程)。b:使用线程池,同样使用阻塞式IO操作。与第1种相比,这是提高性能的措施。c:使用non-blocking IO + IO multiplexing。即Java NIO的方式。d:Leader/Follower等高级模式。在默认情况下,我会使用第3种,即non-blocking IO + one loop per thread模式来编写多线程C++网络服务程序。1:one loop per thread此种模型下,程序里的每个IO线程有一个eventloop,用于处理读写和定时事件(无论周期性的还是单次的)。代码框架跟“单线程服务器的常用编程模型”一节中的一样。libev的作者说:One loop per thread is usually a good model. Doing this is almost never wrong, some times a better-performance model exists, but it is always a good start.这种方式的好处是:a:线程数目基本固定,可以在程序启动的时候设置,不会频繁创建与销毁。b:可以很方便地在线程间调配负载。c:IO事件发生的线程是固定的,同一个TCP连接不必考虑事件并发。Event loop代表了线程的主循环,需要让哪个线程干活,就把timer或IO channel(如TCP连接)注册到哪个线程的loop里即可:对实时性有要求的connection可以单独用一个线程;数据量大的connection可以独占一个线程,并把数据处理任务分摊到另几个计算线程中(用线程池);其他次要的辅助性connections可以共享一个线程。比如,在dbproxy中,一个线程用于专门处理客户端发来的管理命令;一个线程用于处理客户端发来的MySQL命令,而与后端数据库通信执行该命令时,是将该任务分配给所有事件线程处理的。对于non-trivial(有一定规模)的服务端程序,一般会采用non-blocking IO + IO multiplexing,每个connection/acceptor都会注册到某个event loop上,程序里有多个event loop,每个线程至多有一个event loop。多线程程序对event loop提出了更高的要求,那就是“线程安全”。要允许一个线程往别的线程的loop里塞东西,这个loop必须得是线程安全的。在dbproxy中,线程向其他线程分发任务,是通过管道和队列实现的。比如主线程accept到连接后,将表示该连接的结构放入队列,并向管道中写入一个字节。计算线程在自己的event loop中注册管道的读事件,一旦有数据可读,就尝试从队列中取任务。2:线程池不过,对于没有IO而光有计算任务的线程,使用event loop有点浪费。可以使用一种补充方案,即用blockingqueue实现的任务队列:[cpp] view plain copytypedef boost::functionFunctor;BlockingQueue taskQueue; //线程安全的全局阻塞队列//计算线程void workerThread(){while (running) //running变量是个全局标志{Functor task = taskQueue.take();//this blockstask(); //在产品代码中需要考虑异常处理}}// 创建容量(并发数)为N的线程池int N = num_of_computing_threads;for (int i = 0; i < N; ++i){create_thread(&workerThread); //启动线程}//向任务队列中追加任务Foo foo;//Foo有calc()成员函数boost::function task = boost::bind(&Foo::calc,&foo);taskQueue.post(task);除了任务队列,还可以用BlockingQueue实现数据的生产者消费者队列,即T是数据类型而非函数对象,queue的消费者从中拿到数据进行处理。其实本质上是一样的。3:总结总结而言,我推荐的C++多线程服务端编程模式为:one (event) loop per thread + thread pool:eventloop用作IO multiplexing,配合non-blockingIO和定时器;threadpool用来做计算,具体可以是任务队列或生产者消费者队列。以这种方式写服务器程序,需要一个优质的基于Reactor模式的网络库来支撑,muduo正是这样的网络库。比如dbproxy使用的是libevent。程序里具体用几个loop、线程池的大小等参数需要根据应用来设定,基本的原则是“阻抗匹配”(解释见下),使得CPU和IO都能高效地运作。所谓阻抗匹配原则:如果池中线程在执行任务时,密集计算所占的时间比重为 P (0 < P <= 1),而系统一共有 C 个 CPU,为了让这 C 个 CPU 跑满而又不过载,线程池大小的经验公式 T = C/P。(T 是个 hint,考虑到 P 值的估计不是很准确,T 的最佳值可以上下浮动 50%)以后我再讲这个经验公式是怎么来的,先验证边界条件的正确性。假设 C = 8,P = 1.0,线程池的任务完全是密集计算,那么T = 8。只要 8 个活动线程就能让 8 个 CPU 饱和,再多也没用,因为 CPU 资源已经耗光了。假设 C = 8,P = 0.5,线程池的任务有一半是计算,有一半等在 IO 上,那么T = 16。考虑操作系统能灵活合理地调度 sleeping/writing/running 线程,那么大概 16 个“50%繁忙的线程”能让 8 个 CPU 忙个不停。启动更多的线程并不能提高吞吐量,反而因为增加上下文切换的开销而降低性能。如果 P < 0.2,这个公式就不适用了,T 可以取一个固定值,比如 5*C。另外,公式里的 C 不一定是 CPU 总数,可以是“分配给这项任务的 CPU 数目”,比如在 8 核机器上分出 4 个核来做一项任务,那么 C=4。四:进程间通信只用TCPLinux下进程间通信的方式有:匿名管道(pipe)、具名管道(FIFO)、POSIX消息队列、共享内存、信号(signals),以及Socket。同步原语有互斥器(mutex)、条件变量(condition variable)、读写锁(reader-writer lock)、文件锁(record locking)、信号量(semaphore)等等。进程间通信我首选Sockets(主要指TCP,我没有用过UDP,也不考虑Unix domain协议)。其好处在于:可以跨主机,具有伸缩性。反正都是多进程了,如果一台机器的处理能力不够,很自然地就能用多台机器来处理。把进程分散到同一局域网的多台机器上,程序改改host:port配置就能继续用;TCP sockets和pipe都是操作文件描述符,用来收发字节流,都可以read/write/fcntl/select/poll等。不同的是,TCP是双向的,Linux的pipe是单向的,进程间双向通信还得开两个文件描述符,不方便;而且进程要有父子关系才能用pipe,这些都限制了pipe的使用;TCP port由一个进程独占,且进程退出时操作系统会自动回收文件描述符。因此即使程序意外退出,也不会给系统留下垃圾,程序重启之后能比较容易地恢复,而不需要重启操作系统(用跨进程的mutex就有这个风险);而且,port是独占的,可以防止程序重复启动,后面那个进程抢不到port,自然就没法初始化了,避免造成意料之外的结果;与其他IPC相比,TCP协议的一个天生的好处是“可记录、可重现”。tcpdump和Wireshark是解决两个进程间协议和状态争端的好帮手,也是性能(吞吐量、延迟)分析的利器。我们可以借此编写分布式程序的自动化回归测试。也可以用tcpcopy之类的工具进行压力测试。TCP还能跨语言,服务端和客户端不必使用同一种语言。分布式系统的软件设计和功能划分一般应该以“进程”为单位。从宏观上看,一个分布式系统是由运行在多台机器上的多个进程组成的,进程之间采用TCP长连接通信。使用TCP长连接的好处有两点:一是容易定位分布式系统中的服务之间的依赖关系。只要在机器上运行netstat-tpna|grep就能立刻列出用到某服务的客户端地址(Foreign Address列),然后在客户端的机器上用netstat或lsof命令找出是哪个进程发起的连接。TCP短连接和UDP则不具备这一特性。二是通过接收和发送队列的长度也较容易定位网络或程序故障。在正常运行的时候,netstat打印的Recv-Q和Send-Q都应该接近0,或者在0附近摆动。如果Recv-Q保持不变或持续增加,则通常意味着服务进程的处理速度变慢,可能发生了死锁或阻塞。如果Send-Q保持不变或持续增加,有可能是对方服务器太忙、来不及处理,也有可能是网络中间某个路由器或交换机故障造成丢包,甚至对方服务器掉线,这些因素都可能表现为数据发送不出去。通过持续监控Recv-Q和Send-Q就能及早预警性能或可用性故障。以下是服务端线程阻塞造成Recv-Q和客户端Send-Q激增的例子:[cpp] view plain copy$netstat -tnProtoRecv-QSend-QLocal AddressForeigntcp 78393 010.0.0.10:2000 10.0.0.10:39748 #服务端连接tcp 013260810.0.0.10:3974810.0.0.10:2000#客户端连接tcp 05210.0.0.10:22 10.0.0.4:55572五:多线程服务器的适用场合如果要在一台多核机器上提供一种服务或执行一个任务,可用的模式有:a:运行一个单线程的进程;b:运行一个多线程的进程;c:运行多个单线程的进程;d:运行多个多线程的进程;考虑这样的场景:如果使用速率为50MB/s的数据压缩库,进程创建销毁的开销是800微秒,线程创建销毁的开销是50微秒。如何执行压缩任务?如果要偶尔压缩1GB的文本文件,预计运行时间是20s,那么起一个进程去做是合理的,因为进程启动和销毁的开销远远小于实际任务的耗时。如果要经常压缩500kB的文本数据,预计运行时间是10ms,那么每次都起进程似乎有点浪费了,可以每次单独起一个线程去做。如果要频繁压缩10kB的文本数据,预计运行时间是200微秒,那么每次起线程似乎也很浪费,不如直接在当前线程搞定。也可以用一个线程池,每次把压缩任务交给线程池,避免阻塞当前线程(特别要避免阻塞IO线程)。由此可见,多线程并不是万灵丹(silver bullet)。1:必须使用单线程的场合据我所知,有两种场合必须使用单线程:a:程序可能会fork(2);实际编程中,应该保证只有单线程程序能进行fork(2)。多线程程序不是不能调用fork(2),而是这么做会遇到很多麻烦:fork一般不能在多线程程序中调用,因为Linux的fork只克隆当前线程的thread of control,不可隆其他线程。fork之后,除了当前线程之外,其他线程都消失了。这就造成一种危险的局面。其他线程可能正好处于临界区之内,持有了某个锁,而它突然死亡,再也没有机会去解锁了。此时如果子进程试图再对同一个mutex加锁,就会立即死锁。因此,fork之后,子进程就相当于处于signal handler之中(因为不知道调用fork时,父进程中的线程此时正在调用什么函数,这和信号发生时的场景一样),你不能调用线程安全的函数(除非它是可重入的),而只能调用异步信号安全的函数。比如,fork之后,子进程不能调用:malloc,因为malloc在访问全局状态时几乎肯定会加锁;任何可能分配或释放内存的函数,比如snprintf;任何Pthreads函数;printf系列函数,因为其他线程可能恰好持有stdout/stderr的锁;除了man 7 signal中明确列出的信号安全函数之外的任何函数。因此,多线程中调用fork,唯一安全的做法是fork之后,立即调用exec执行另一个程序,彻底隔断子进程与父进程的联系。在多线程环境中调用fork,产生子进程后。子进程内部只存在一个线程,也就是父进程中调用fork的线程的副本。使用fork创建子进程时,子进程通过继承整个地址空间的副本,也从父进程那里继承了所有互斥量、读写锁和条件变量的状态。如果父进程中的某个线程占有锁,则子进程同样占有这些锁。问题是子进程并不包含占有锁的线程的副本,所以子进程没有办法知道它占有了哪些锁,并且需要释放哪些锁。尽管Pthread提供了pthread_atfork函数试图绕过这样的问题,但是这回使得代码变得混乱。因此《Programming With Posix Threads》一书的作者说:”Avoid using fork in threaded code except where the child process will immediately exec a new program.”。b:限制程序的CPU占用率;这个很容易理解,比如在一个8核的服务器上,一个单线程程序即便发生busy-wait,占满1个core,其CPU使用率也只有12.5%,在这种最坏的情况下,系统还是有87.5%的计算资源可供其他服务进程使用。 因此对于一些辅助性的程序,如果它必须和主要服务进程运行在同一台机器的话,那么做成单线程的能避免过分抢夺系统的计算资源。
      如何看懂《Linux多线程服务端编程

      如何看懂《Linux多线程服务端编程

      一:进程和线程 每个进程有自己独立的地址空间。“在同一个进程”还是“不在同一个进程”是系统功能划分的重要决策点。《Erlang程序设计》[ERL]把进程比喻为人:每个人有自己的记忆(内存),人与人通过谈话(消息传递)来交流,谈话既可以是面谈(同一台服务器),也可以在电话里谈(不同的服务器,有网络通信)。面谈和电话谈的区别在于,面谈可以立即知道对方是否死了(crash,SIGCHLD),而电话谈只能通过周期性的心跳来判断对方是否还活着。有了这些比喻,设计分布式系统时可以采取“角色扮演”,团队里的几个人各自扮演一个进程,人的角色由进程的代码决定(管登录的、管消息分发的、管买卖的等等)。每个人有自己的记忆,但不知道别人的记忆,要想知道别人的看法,只能通过交谈(暂不考虑共享内存这种IPC)。然后就可以思考:·容错:万一有人突然死了·扩容:新人中途加进来·负载均衡:把甲的活儿挪给乙做·退休:甲要修复bug,先别派新任务,等他做完手上的事情就把他重启等等各种场景,十分便利。线程的特点是共享地址空间,从而可以高效地共享数据。一台机器上的多个进程能高效地共享代码段(操作系统可以映射为同样的物理内存),但不能共享数据。如果多个进程大量共享内存,等于是把多进程程序当成多线程来写,掩耳盗铃。“多线程”的价值,我认为是为了更好地发挥多核处理器(multi-cores)的效能。在单核时代,多线程没有多大价值(个人想法:如果要完成的任务是CPU密集型的,那多线程没有优势,甚至因为线程切换的开销,多线程反而更慢;如果要完成的任务既有CPU计算,又有磁盘或网络IO,则使用多线程的好处是,当某个线程因为IO而阻塞时,OS可以调度其他线程执行,虽然效率确实要比任务的顺序执行效率要高,然而,这种类型的任务,可以通过单线程的”non-blocking IO+IO multiplexing”的模型(事件驱动)来提高效率,采用多线程的方式,带来的可能仅仅是编程上的简单而已)。Alan Cox说过:”A computer is a state machine.Threads are for people who can’t program state machines.”(计算机是一台状态机。线程是给那些不能编写状态机程序的人准备的)如果只有一块CPU、一个执行单元,那么确实如Alan Cox所说,按状态机的思路去写程序是最高效的。二:单线程服务器的常用编程模型据我了解,在高性能的网络程序中,使用得最为广泛的恐怕要数”non-blocking IO + IO multiplexing”这种模型,即Reactor模式。在”non-blocking IO + IO multiplexing”这种模型中,程序的基本结构是一个事件循环(event loop),以事件驱动(event-driven)和事件回调的方式实现业务逻辑:[cpp] view plain copy//代码仅为示意,没有完整考虑各种情况while(!done){int timeout_ms = max(1000, getNextTimedCallback());int retval = poll(fds, nfds, timeout_ms);if (retval<0){处理错误,回调用户的error handler}else{处理到期的timers,回调用户的timer handlerif(retval>0){处理IO事件,回调用户的IO event handler}}}这里select(2)/poll(2)有伸缩性方面的不足(描述符过多时,效率较低),Linux下可替换为epoll(4),其他操作系统也有对应的高性能替代品。Reactor模型的优点很明显,编程不难,效率也不错。不仅可以用于读写socket,连接的建立(connect(2)/accept(2)),甚至DNS解析都可以用非阻塞方式进行,以提高并发度和吞吐量(throughput),对于IO密集的应用是个不错的选择。lighttpd就是这样,它内部的fdevent结构十分精妙,值得学习。基于事件驱动的编程模型也有其本质的缺点,它要求事件回调函数必须是非阻塞的。对于涉及网络IO的请求响应式协议,它容易割裂业务逻辑,使其散布于多个回调函数之中,相对不容易理解和维护。三:多线程服务器的常用编程模型大概有这么几种:a:每个请求创建一个线程,使用阻塞式IO操作。在Java 1.4引人NIO之前,这是Java网络编程的推荐做法。可惜伸缩性不佳(请求太多时,操作系统创建不了这许多线程)。b:使用线程池,同样使用阻塞式IO操作。与第1种相比,这是提高性能的措施。c:使用non-blocking IO + IO multiplexing。即Java NIO的方式。d:Leader/Follower等高级模式。在默认情况下,我会使用第3种,即non-blocking IO + one loop per thread模式来编写多线程C++网络服务程序。1:one loop per thread此种模型下,程序里的每个IO线程有一个eventloop,用于处理读写和定时事件(无论周期性的还是单次的)。代码框架跟“单线程服务器的常用编程模型”一节中的一样。libev的作者说:One loop per thread is usually a good model. Doing this is almost never wrong, some times a better-performance model exists, but it is always a good start.这种方式的好处是:a:线程数目基本固定,可以在程序启动的时候设置,不会频繁创建与销毁。b:可以很方便地在线程间调配负载。c:IO事件发生的线程是固定的,同一个TCP连接不必考虑事件并发。Event loop代表了线程的主循环,需要让哪个线程干活,就把timer或IO channel(如TCP连接)注册到哪个线程的loop里即可:对实时性有要求的connection可以单独用一个线程;数据量大的connection可以独占一个线程,并把数据处理任务分摊到另几个计算线程中(用线程池);其他次要的辅助性connections可以共享一个线程。比如,在dbproxy中,一个线程用于专门处理客户端发来的管理命令;一个线程用于处理客户端发来的MySQL命令,而与后端数据库通信执行该命令时,是将该任务分配给所有事件线程处理的。对于non-trivial(有一定规模)的服务端程序,一般会采用non-blocking IO + IO multiplexing,每个connection/acceptor都会注册到某个event loop上,程序里有多个event loop,每个线程至多有一个event loop。多线程程序对event loop提出了更高的要求,那就是“线程安全”。要允许一个线程往别的线程的loop里塞东西,这个loop必须得是线程安全的。在dbproxy中,线程向其他线程分发任务,是通过管道和队列实现的。比如主线程accept到连接后,将表示该连接的结构放入队列,并向管道中写入一个字节。计算线程在自己的event loop中注册管道的读事件,一旦有数据可读,就尝试从队列中取任务。2:线程池不过,对于没有IO而光有计算任务的线程,使用event loop有点浪费。可以使用一种补充方案,即用blockingqueue实现的任务队列:[cpp] view plain copytypedef boost::functionFunctor;BlockingQueue taskQueue; //线程安全的全局阻塞队列//计算线程void workerThread(){while (running) //running变量是个全局标志{Functor task = taskQueue.take();//this blockstask(); //在产品代码中需要考虑异常处理}}// 创建容量(并发数)为N的线程池int N = num_of_computing_threads;for (int i = 0; i < N; ++i){create_thread(&workerThread); //启动线程}//向任务队列中追加任务Foo foo;//Foo有calc()成员函数boost::function task = boost::bind(&Foo::calc,&foo);taskQueue.post(task);除了任务队列,还可以用BlockingQueue实现数据的生产者消费者队列,即T是数据类型而非函数对象,queue的消费者从中拿到数据进行处理。其实本质上是一样的。3:总结总结而言,我推荐的C++多线程服务端编程模式为:one (event) loop per thread + thread pool:eventloop用作IO multiplexing,配合non-blockingIO和定时器;threadpool用来做计算,具体可以是任务队列或生产者消费者队列。以这种方式写服务器程序,需要一个优质的基于Reactor模式的网络库来支撑,muduo正是这样的网络库。比如dbproxy使用的是libevent。程序里具体用几个loop、线程池的大小等参数需要根据应用来设定,基本的原则是“阻抗匹配”(解释见下),使得CPU和IO都能高效地运作。所谓阻抗匹配原则:如果池中线程在执行任务时,密集计算所占的时间比重为 P (0 < P <= 1),而系统一共有 C 个 CPU,为了让这 C 个 CPU 跑满而又不过载,线程池大小的经验公式 T = C/P。(T 是个 hint,考虑到 P 值的估计不是很准确,T 的最佳值可以上下浮动 50%)以后我再讲这个经验公式是怎么来的,先验证边界条件的正确性。假设 C = 8,P = 1.0,线程池的任务完全是密集计算,那么T = 8。只要 8 个活动线程就能让 8 个 CPU 饱和,再多也没用,因为 CPU 资源已经耗光了。假设 C = 8,P = 0.5,线程池的任务有一半是计算,有一半等在 IO 上,那么T = 16。考虑操作系统能灵活合理地调度 sleeping/writing/running 线程,那么大概 16 个“50%繁忙的线程”能让 8 个 CPU 忙个不停。启动更多的线程并不能提高吞吐量,反而因为增加上下文切换的开销而降低性能。如果 P < 0.2,这个公式就不适用了,T 可以取一个固定值,比如 5*C。另外,公式里的 C 不一定是 CPU 总数,可以是“分配给这项任务的 CPU 数目”,比如在 8 核机器上分出 4 个核来做一项任务,那么 C=4。四:进程间通信只用TCPLinux下进程间通信的方式有:匿名管道(pipe)、具名管道(FIFO)、POSIX消息队列、共享内存、信号(signals),以及Socket。同步原语有互斥器(mutex)、条件变量(condition variable)、读写锁(reader-writer lock)、文件锁(record locking)、信号量(semaphore)等等。进程间通信我首选Sockets(主要指TCP,我没有用过UDP,也不考虑Unix domain协议)。其好处在于:可以跨主机,具有伸缩性。反正都是多进程了,如果一台机器的处理能力不够,很自然地就能用多台机器来处理。把进程分散到同一局域网的多台机器上,程序改改host:port配置就能继续用;TCP sockets和pipe都是操作文件描述符,用来收发字节流,都可以read/write/fcntl/select/poll等。不同的是,TCP是双向的,Linux的pipe是单向的,进程间双向通信还得开两个文件描述符,不方便;而且进程要有父子关系才能用pipe,这些都限制了pipe的使用;TCP port由一个进程独占,且进程退出时操作系统会自动回收文件描述符。因此即使程序意外退出,也不会给系统留下垃圾,程序重启之后能比较容易地恢复,而不需要重启操作系统(用跨进程的mutex就有这个风险);而且,port是独占的,可以防止程序重复启动,后面那个进程抢不到port,自然就没法初始化了,避免造成意料之外的结果;与其他IPC相比,TCP协议的一个天生的好处是“可记录、可重现”。tcpdump和Wireshark是解决两个进程间协议和状态争端的好帮手,也是性能(吞吐量、延迟)分析的利器。我们可以借此编写分布式程序的自动化回归测试。也可以用tcpcopy之类的工具进行压力测试。TCP还能跨语言,服务端和客户端不必使用同一种语言。分布式系统的软件设计和功能划分一般应该以“进程”为单位。从宏观上看,一个分布式系统是由运行在多台机器上的多个进程组成的,进程之间采用TCP长连接通信。使用TCP长连接的好处有两点:一是容易定位分布式系统中的服务之间的依赖关系。只要在机器上运行netstat-tpna|grep就能立刻列出用到某服务的客户端地址(Foreign Address列),然后在客户端的机器上用netstat或lsof命令找出是哪个进程发起的连接。TCP短连接和UDP则不具备这一特性。二是通过接收和发送队列的长度也较容易定位网络或程序故障。在正常运行的时候,netstat打印的Recv-Q和Send-Q都应该接近0,或者在0附近摆动。如果Recv-Q保持不变或持续增加,则通常意味着服务进程的处理速度变慢,可能发生了死锁或阻塞。如果Send-Q保持不变或持续增加,有可能是对方服务器太忙、来不及处理,也有可能是网络中间某个路由器或交换机故障造成丢包,甚至对方服务器掉线,这些因素都可能表现为数据发送不出去。通过持续监控Recv-Q和Send-Q就能及早预警性能或可用性故障。以下是服务端线程阻塞造成Recv-Q和客户端Send-Q激增的例子:[cpp] view plain copy$netstat -tnProtoRecv-QSend-QLocal AddressForeigntcp 78393 010.0.0.10:2000 10.0.0.10:39748 #服务端连接tcp 013260810.0.0.10:3974810.0.0.10:2000#客户端连接tcp 05210.0.0.10:22 10.0.0.4:55572五:多线程服务器的适用场合如果要在一台多核机器上提供一种服务或执行一个任务,可用的模式有:a:运行一个单线程的进程;b:运行一个多线程的进程;c:运行多个单线程的进程;d:运行多个多线程的进程;考虑这样的场景:如果使用速率为50MB/s的数据压缩库,进程创建销毁的开销是800微秒,线程创建销毁的开销是50微秒。如何执行压缩任务?如果要偶尔压缩1GB的文本文件,预计运行时间是20s,那么起一个进程去做是合理的,因为进程启动和销毁的开销远远小于实际任务的耗时。如果要经常压缩500kB的文本数据,预计运行时间是10ms,那么每次都起进程似乎有点浪费了,可以每次单独起一个线程去做。如果要频繁压缩10kB的文本数据,预计运行时间是200微秒,那么每次起线程似乎也很浪费,不如直接在当前线程搞定。也可以用一个线程池,每次把压缩任务交给线程池,避免阻塞当前线程(特别要避免阻塞IO线程)。由此可见,多线程并不是万灵丹(silver bullet)。1:必须使用单线程的场合据我所知,有两种场合必须使用单线程:a:程序可能会fork(2);实际编程中,应该保证只有单线程程序能进行fork(2)。多线程程序不是不能调用fork(2),而是这么做会遇到很多麻烦:fork一般不能在多线程程序中调用,因为Linux的fork只克隆当前线程的thread of control,不可隆其他线程。fork之后,除了当前线程之外,其他线程都消失了。这就造成一种危险的局面。其他线程可能正好处于临界区之内,持有了某个锁,而它突然死亡,再也没有机会去解锁了。此时如果子进程试图再对同一个mutex加锁,就会立即死锁。因此,fork之后,子进程就相当于处于signal handler之中(因为不知道调用fork时,父进程中的线程此时正在调用什么函数,这和信号发生时的场景一样),你不能调用线程安全的函数(除非它是可重入的),而只能调用异步信号安全的函数。比如,fork之后,子进程不能调用:malloc,因为malloc在访问全局状态时几乎肯定会加锁;任何可能分配或释放内存的函数,比如snprintf;任何Pthreads函数;printf系列函数,因为其他线程可能恰好持有stdout/stderr的锁;除了man 7 signal中明确列出的信号安全函数之外的任何函数。因此,多线程中调用fork,唯一安全的做法是fork之后,立即调用exec执行另一个程序,彻底隔断子进程与父进程的联系。在多线程环境中调用fork,产生子进程后。子进程内部只存在一个线程,也就是父进程中调用fork的线程的副本。使用fork创建子进程时,子进程通过继承整个地址空间的副本,也从父进程那里继承了所有互斥量、读写锁和条件变量的状态。如果父进程中的某个线程占有锁,则子进程同样占有这些锁。问题是子进程并不包含占有锁的线程的副本,所以子进程没有办法知道它占有了哪些锁,并且需要释放哪些锁。尽管Pthread提供了pthread_atfork函数试图绕过这样的问题,但是这回使得代码变得混乱。因此《Programming With Posix Threads》一书的作者说:”Avoid using fork in threaded code except where the child process will immediately exec a new program.”。b:限制程序的CPU占用率;这个很容易理解,比如在一个8核的服务器上,一个单线程程序即便发生busy-wait,占满1个core,其CPU使用率也只有12.5%,在这种最坏的情况下,系统还是有87.5%的计算资源可供其他服务进程使用。 因此对于一些辅助性的程序,如果它必须和主要服务进程运行在同一台机器的话,那么做成单线程的能避免过分抢夺系统的计算资源。
      如何看懂《Linux多线程服务端编程

      《Linux高性能服务器编程》pdf下载在线阅读全文,求百度网盘云资源

      《Linux高性能服务器编程》(游双)电子书网盘下载免费在线阅读链接: https://pan.baidu.com/s/1_wuRSEGiIuzq_bLv0TdaqQ提取码: jxb9书名:Linux高性能服务器编程作者:游双豆瓣评分:7.9出版社:机械工业出版社出版年份:2013-5-1页数:360内容简介:本书是Linux服务器编程领域的经典著作,由资深Linux软件开发工程师撰写,从网络协议、服务器编程核心要素、原理机制、工具框架等多角度全面阐释了编写高性能Linux服务器应用的方法、技巧和思想。不仅理论全面、深入,抓住了重点和难点,还包含两个综合性案例,极具实战意义。全书共17章,分为3个部分:第一部分对Linux服务器编程的核心基础——TCP/IP协议进行了深入的解读和阐述,包括TCP/IP协议族、TCP/IP协议,以及一个经典的TCP/IP通信案例;第二部分对高性能服务器编程的核心要素进行了全面深入的剖析,包含Linux网络编程API、高级I/O函数、Linux服务器程序规范、高性能服务器程序框架、I/O复用、信号、定时器、高性能I/O框架库Libevent、多进程编程、多线程编程、进程池和线程池等内容,原理、技术与方法并重;第三部分从侧重实战的角度讲解了高性能服务器的优化与监测,包含服务器的调制、调试和测试,以及各种实用系统监测工具的使用等内容。作者简介:游双,资深Linux软件开发工程师,对Linux网络编程,尤其是服务器端的编程,有非常深入的研究,实战经验也十分丰富。曾就职于摩托罗拉,担任高级Linux软件工程师。此外,他还精通C++、Android、QT等相关的技术。活跃于Chinaunix等专业技术社区,发表了大量关于Linux网络编程的文章,深受社区欢迎。
      《Linux高性能服务器编程》pdf下载在线阅读全文,求百度网盘云资源

      Linux,哪个版本最好,适合做编程的人用

      如果你是一个Linux爱好者,想选择一个桌面系统,并且既不想用盗版,又不想花太多钱购买商业系统软件,那么可以选择Ubuntu桌面系统。 如果你需要服务器端的Linux系统,想用一个比较稳定的服务器系统,或者说目标就是进入企业从事Linux运维工作,那么建议你选择CentOS或Red Hat。在这两者当中又应首选CentOS,因为目前市场的趋势是这样的,CentOS社区非常活跃,CentOS是当前国内互联网企业服务器端实际应用比较多的系统。如果对系统稳定性、安全性有更高的要求,或者是特殊使用偏好的用户,可以考虑Debian或FreeBSD。 如果特别痴迷于新技术体验和追求新的软件版本,可以选择Fedora,但要容忍Fedora潜在的新技术软件的Bug和系统稳定性的问题。
      1、centos7作为服务器,用来搭建tomcat、nginx、mysql等 2、Ubuntu用来作为开发的系统。用来搭建idea等开发工具。
      Linux,哪个版本最好,适合做编程的人用

      本文由 在线网速测试 整理编辑,转载请注明出处,原文链接:https://www.wangsu123.cn/news/43827.html

          热门文章

          文章分类