《后台开发核心技术与应用实践》(四)

9. 多线程

9.1. 多线程

(1)多进程频繁上下文切换引起的额外开销可能会严重影响系统性能;进程间通信要求复杂的系统级实现
(2)同一个进程内部的多个线程共享该进程的所有资源;通过线程可以支持同一个应用程序内部的并发,免去了进程频繁切换的开销;并发任务间通信也更简单。
(3)多线程在的进程在内存中有多个栈,每个栈对应一个线程,多个栈之间以一定的空白区域隔开,以备栈的增长,任何一个空白区域被填满都会导致栈溢出。

9.2.多线程的创建与结束

(1)线程创建:pthread_create函数
(2)线程退出:执行完成后隐式退出;由线程本身显示调用pthread_exit 函数退出;被其他线程用pthread_cancel函数终止
(3)pthread_join用于等待一个线程的结束,也就是主线程中要是加了这段代码,就会在加代码的位置卡主,直到这个线程执行完毕才往下走。一般都是pthread_exit在线程内退出,然后返回一个值。这个时候就跳到主线程的pthread_join了(因为一直在等你结束),这个返回值会直接送到pthread_join,实现了主与分线程的通信。
(4)向线程传递参数
(5)获得线程id

9.3. 线程的属性

(1)属性值不能直接设置,须使用相关函数进行操作,初始化的函数为pthread_attr_init,这个函数必须在pthread_create函数之前调用,之后必须用pthread_attr_destroy函数来释放资源。
(2)属性对象主要包括:作用域(scope)、栈尺寸(stack size)、栈地址(stack address)、优先级(priority)、分离的状态(detached state)、调度策略和参数(scheduling policy and parameters)。默认的属性为非绑定、非分离、缺省1M的堆栈、与父进程同样级别的优先级。

9.4. 多线程的同步

(1)互斥锁。通过加锁将原先分离的多个指令构成不可分割的一个原子操作
(2)条件变量。条件变量本身不是锁!但它也可以造成阻塞。通常与互斥锁配合使用,给多线程提供一个会合的场所。
(3)读写锁。与互斥量类似,但读写锁允许更高的并行性。其特性为:写独占,读共享。
(4)信号量。进化版的互斥锁(1–>N)。信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。

9.5. 多线程的重入

(1)可重入函数特点:

1.不在函数内部使用静态或者全局数据
2.不返回静态或者全局数据,所有的数据都由函数调用者提供
3.使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据
4. 如果必须访问全局数据,使用互斥锁来保护
5.不调用不可重入函数

(2)不可重入函数特点:

1.函数中使用了静态变量,无论是全局静态变量还是局部静态变量
2.函数返回静态变量
3.函数中调用了不可重入函数
4.函数中使用了静态的数据结构
5.调用了malloc/free函数,因为malloc函数是用全局链表来管理堆的
6.调用了标准I/O库函数,标准I/O库的很多实现都以不可重入的方式使用全局数据结构。

(3)_REENTRANT宏
在一个多线程程序里,默认情况下,只有一个errno变量供所有的线程共享。在一个线程准备获取刚才的错误代码时,该变量很容易被另一个线程中的函数调用所改变。类似的问题还存在于fputs之类的函数中,这些函数通常用一个单独的全局性区域来缓存输出数据。
为解决这个问题,需要使用可重入的例程。可重入代码可以被多次调用而仍然工作正常。编写的多线程程序,通过定义宏_REENTRANT来告诉编译器我们需要可重入功能,这个宏的定义必须出现于程序中的任何#include语句之前。
_REENTRANT为我们做三件事情,并且做的非常优雅:

1.它会对部分函数重新定义它们的可安全重入的版本,这些函数名字一般不会发生改变,只是会在函数名后面添加_r字符串,如函数名gethostbyname变成gethostbyname_r。
2.stdio.h中原来以宏的形式实现的一些函数将变成可安全重入函数。
3.在error.h中定义的变量error现在将成为一个函数调用,它能够以一种安全的多线程方式来获取真正的errno的值。

10.进程

10.1.程序与进程

(1)进程结构:代码段、数据段、堆栈段。堆栈段包括进程控制块PCB
(2)程序转换成进程步骤:

1.内核将程序读入内存,为程序分配内存空间
2.内核为该进程分配进程标识符(PID)和其他所需资源
3.内核为进程保存PID及相应的状态信息,把进程放到运行队列中等待执行。程序转化为进程后就可以被操作系统的调度程序调度执行了。

10.2.进程的创建与结束

(1)fork()函数创建进程。仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:

1.在父进程中,fork返回新创建子进程的进程ID;
2.在子进程中,fork返回0;
3.如果创建出错,fork返回-1

(2)exit()函数结束进程。

1.exit是函数,带参数,执行完后把控制权交给系统;return是函数执行完后的返回,执行完后把控制权交给调用函数
2.exit是正常终止进程;abort是异常终止
3.exit()会将缓冲区的数据写完后再退出;_exit()函数直接退出

10.3.僵尸进程

(1)孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
(2)僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。

10.4.守护进程

(1)linux或UNIX在系统引导时会开启很多服务,这些服务就叫作守护进程。守护进程是脱离终端并且在后台运行的进程
(2)创建守护进程步骤:

1.创建子进程,父进程退出(使子进程成为孤儿进程)
2.在子进程中创建新的会话(脱离控制终端)
3.改变当前目录为根目录
4.重设文件权限掩码
5.关闭文件描述符
6.守护进程的退出

11.进程间通信

11.1.管道

(1)管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程或兄弟进程。
(2)无名管道和有名管道(FIFO)。前者用于父进程和子进程间的通信,后者用于运行于同一台机器上的任意两个进程间的通信。

11.2.消息队列

消息队列用于运行于同一台机器上的进程间通信,它和管道很相似,是一个在系统内核中用来保存消息的队列,它在系统内核中是以消息链表的形式出现。消息链表中节点的结构用msg声明。

11.3.共享内存

(1)共享内存是运行在同一台机器上的进程间通信最快的方式,因为数据不需要在不同的进程间复制。通常由一个进程创建一块共享内存区,其余进程对这块内存区进行读写。
(2)得到共享内存有两种方式:映射/dev/mem设备和内存映像文件。前一种方式不给系统带来额外的开销,但在现实中并不常用,因为它控制存取的将是实际的物理内存,在Linux系统下,这只有通过限制Linux系统存取的内存才可以做到,这当然不太实际。常用的方式是通过shmXXX函数族来实现利用共享内存进行存储的。
(3)使用共享内存优点:方便,函数接口简单,数据的共享使得进程间的数据不用传送,而是直接访问,也加快了效率。不像无名管道一样要求亲缘关系。
(4)使用共享内存缺点:没有提供同步机制,使得在使用共享内存进行进程间通信时,往往要借助其他的手段来进行进程间的同步工作。

11.4.信号量

信号量又称为信号灯,它是用来协调不同进程间的数据对象的,而最主要的应用是前一节的共享内存方式的进程间通信。本质上,信号量是一个计数器,它用来记录对某个资源(如共享内存)的存取状况。

11.5.ipcs命令

(1)ipcs -a列出本用户所有相关的ipcs参数
(2)ipcs -q列出进程中的消息队列
(3)ipcs -s列出所有信号量
(4)ipcs -m列出所有共享内存信息
(5)ipcs -l列出系统的限额
(6)ipcs -t列出最后的访问时间
(7)ipcs -u列出当前的使用情况

《后台开发核心技术与应用实践》(一)
《后台开发核心技术与应用实践》(二)
《后台开发核心技术与应用实践》(三)
《后台开发核心技术与应用实践》(四)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
后台开发核心技术应用实践 作者:徐晓鑫 著 出版日期:2016年08月06日 封面宣传语:腾讯云平台技术总监黄世飞、Facebook对外支付项目主程张子兴、微软软件工程师彭可竞、阿里巴巴资深算法工程师周乐、百度大数据高级测试工程师畅晋联袂推荐;围绕后台开发需要掌握的核心技术,从多个方面、多个角度进行了阐述,覆盖了该领域的几乎所有内容;充分抓住本质并结合实践,文字通俗易懂,可操作性强 出版书名:后台开发核心技术应用实践 作者:徐晓鑫 著 封底文字 专家评价 后台开发是一个“历史悠久”的领域,同时也是一个沉淀深厚,高技术价值的领域。本书清晰、严谨、务实的风格显示出晓鑫对该领域知识的深刻理解。 ——张子兴 Facebook对外支付项目主程,美国加州MenloPark 每一位从事后台开发的专业人士都需要一本后台开发指南。对每一位想要认真从事该领域工作的人来说,本书是一本绝对必读的书籍。 ——彭可竞 微软软件工程师,美国华盛顿州Redmond 本书是作者多年后台开发、架构和研究的精华。书中用通俗的文字、详尽的示例代码,结合实际工作中的案例,讲述了后台开发方方面面的知识,内容丰富。对于从事后台开发的人员,这是一本很好的由浅入深的学习书籍。 ——周乐 阿里巴巴资深算法工程师,北京望京 使用C++语言进行后台开发有一定的门槛,本书可以很好地帮助你跨过这个“门槛”。 ——畅晋 百度大数据高级测试工程师,北京上地 前勒口 互联网网民日益剧增,各种应用层出不穷,各项技术更新不断。单是游戏行业,近几年就经历了从端游、页游到手游的巨大变迁,客户端更新迭代之快,始料未及。而后台开发中使用到的技术,却变化不是很大。让服务性能更高、处理能力更强、安全性更好,是后台开发工程师永恒的主题。 后台开发中用到的技术,深而广,需要读的“大部头”很多,光是Richard Stevens的APUE,UNP,TCP/IP详解就够读个半年以上。读者通过阅读本书,可以从实践出发,快速由浅入深地进入后台开发领域。在读完本书,有了实践的经验之后,再去阅读大师们的著作,会更有体会,更懂得如何欣赏。 读书的最高境界莫过于“把书读薄,把书读厚”。本书文字通俗易懂,让你更快地“读薄”,同时又涉及较多的核心知识点,顺着这些知识点,读着读着也发觉“读厚”了。 后勒口 徐晓鑫,腾讯资深软件研发工程师,先后在腾讯游戏之洛克王国、QQ会员、QQ秀等项目工作,精通后台开发各种技术,实战经验丰富。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值