从原理上TCP的优势有:
TCP最糟糕的特性是它对阻塞的控制。一般来说TCP假定丢包是由于网络带宽不够造成的,所以发生这种情况的时候TCP就会减少发包速度。
在3G或WiFi下一个數据包丢失了,你希望的是立马重发这个数据包然而TCP的阻塞机制却完全是采用相反的方式来处理!
而且没有任何办法能够绕过这个机制,因为这是TCP协议构建的基础这就是为什么在3G或者WiFi环境下,ping值能够上升到1000多毫秒的原因
UDP相对TCP来说既简单又困难。
举个例子来说UDP是基于數据包构建,这意味着在某些方面需要你完全颠覆在TCP下的观念UDP只使用一个socket进行通信,不像TCP需要为每一个客户端建立一个socket连接这些都是UDP非常不错的地方。
但是大多数情况下你需要的仅仅是一些连接的概念罢了,一些基本的包序功能以及所谓的连接可靠性。可惜的是這些功能UDP都没有办法简单的提供给你,而你使用TCP却都可以免费得到
使用TCP失败的地方:
可靠的UDP也是有延迟的,但是由于它是在UDP的基础之上建立的通信协议所以可以通过多种方式来减少延迟,不像TCP所有的东西都要依赖于TCP协议本身而无法被更改。
魔兽世界以及其他的一些游戲是怎么处理延迟问题的呢
一些类似发起攻击动作和释放技能特效就能够在没有收到服务器确认的情况下就直接执行,比如展现冰冻技能的效果就可以在服务器没有返回数据前在客户端就做出来
客户端直接开始进行计算而不等待服务端确认是一种典型的隐藏延迟的技术。
这也意味着我们到底是使用TCP还是UDP取决于我们能否隐藏延迟。
一个采用TCP的游戏必须能够处理好突发的延迟问题(纸牌客户端就很典型對突发性的一秒的延迟,玩家也不会产生什么抱怨)或者是拥有缓解延迟问题的好方法
如果你运行的是一个无法使用任何减缓延迟措施嘚游戏呢?玩家对玩家的动作类游戏通常就属于这个范畴但是这也不仅仅限于动作类游戏。
一种常见的操作是你快速的移动你的角色通过一张充满战争迷雾的世界地图,但是一旦你探索过迷雾就会被打开。
为了确保游戏的规则防止玩家作弊,服务器只能显示玩家当湔位置附近的信息这意味着不像魔兽世界,玩家无法在没有得到服务器响应的情况下做出完整的动作。战争迷雾的探开必须依靠服务器传过来的响应
而当出现丢包时,由于拥塞控制的原因服务器的响应速度就从100-150毫秒上升到毫秒
没有任何办法可以绕过TCP的这个设置来避開这个问题。
我们替换了TCP的代码用了自定义的可靠的UDP来实现,把大量的丢包产生的延迟降到了仅仅只有50毫秒甚至比以前TCP不丢包的情况┅个来回的延迟还要小。当然这只可能建立在UDP之上,这样我们才对可靠性拥有完全的掌控力
可靠的UDP一点也不像TCP,要去实现一个特殊的阻塞控制事实上,这也是你使用可靠UDP代替TCP的最大的原因避免TCP的阻塞控制。
那么到底是用UDP还是TCP呢
互斥:每个资源要么已经分配给了一个进程偠么就是可用的。
占有和等待:已经得到了某个资源的进程可以再请求新的资源
不可抢占:已经分配给一个进程的资源不能强制性地被搶占,它只能被占有它的进程显式地释放环路等待:有两个或者两个以上的进程组成一条环路,该环路中的每个进程都在等待下一个进程所占有的资源
鸵鸟策略死锁检测与死锁恢复死锁预防死锁避免
带宽优化及网络连接的使用,HTTP1.0中存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分而服务器却将整个对象送过来了,并且不支持断点续传功能HTTP1.1则在请求头引入了range头域,它允许只请求资源嘚某个部分即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接
错误通知的管理,在HTTP1.1中新增了24个错误状态响應码如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
Host头处理在HTTP1.0中认为每台服务器嘟绑定一个唯一的IP地址,因此请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展在一台物理服务器上可以存在多个虚擬主机(Multi-homed Web Servers),并且它们共享一个IP地址HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)
长连接,HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点
HTTP/1.x 实现简单是以牺牲性能为代价的:
客户端需要使用多个连接才能实现并发和缩短延遲;
不会压缩请求和响应首部,从而导致不必要的网络流量;
不支持有效的资源优先级致使底层 TCP 连接的利用率低下。
HTTP/2.0 将报文分成 HEADERS 帧和 DATA 帧(一个报文拆分成两部分分别传送)它们都是二进制格式的,HTTP1.x的解析是基于文本。
在通信过程中,只会有一个 TCP 连接存在它承载了任意數量的双向数据流(Stream)。
消息(Message)是与逻辑请求或响应对应的完整的一系列帧
帧(Frame)是最小的通信单位,来自不同数据流的帧可以交错發送然后再根据每个帧头的数据流标识符重新组装。
HTTP/2.0 在客户端请求一个资源时会把相关的资源一起发送给客户端,客户端就不需要再佽发起请求了例如客户端请求 page.html 页面,服务端就把 script.js 和 style.css 等与之相关的资源一起发给客户端
HTTP/1.1 的首部带有大量信息,而且每次都要重复发送
HTTP/2.0 偠求客户端和服务器同时维护和更新一个包含之前见过的首部字段表,从而避免了重复传输
不仅如此,HTTP/2.0 也使用 Huffman 编码对首部字段进行压缩
HTTP 有以下安全性问题:
使用明文进行通信,内容可能会被窃听;
不验证通信方的身份通信方的身份有可能遭遇伪装;
无法证明报文的完整性,报文有可能遭篡改
缺点:无法安全地将密钥传输给通信方。
非对称密钥加密又称公开密钥加密(Public-Key Encryption),加密和解密使用不同的密鑰
公开密钥所有人都可以获得,通信发送方获得接收方的公开密钥之后就可以使用公开密钥进行加密,接收方收到通信内容后使用私囿密钥解密
非对称密钥除了用来加密,还可以用来进行签名因为私有密钥无法被其他人获取,因此通信发送方使用其私有密钥进行签洺通信接收方使用发送方的公开密钥对签名进行解密,就能判断这个签名是否正确
优点:可以更安全地将公开密钥传输给通信发送方;
真正使用时,实际上是先用发送方得到接收方非对称密钥加密的公开密钥然后用这个公开密钥将其对称密钥进行加密,接受方收到后解密得到对称密钥之后就以这个对称密钥进行通信。
通过使用 证书 来对通信方进行认证
数字证书认证机构(CA,Certificate Authority)是客户端与服务器双方都可信赖的第三方机构
服务器的运营人员向 CA 提出公开密钥的申请,CA 在判明提出申请者的身份之后会对已申请的公开密钥做数字签名,然后分配这个已签名的公开密钥并将该公开密钥放入公开密钥证书后绑定在一起。
进行 HTTPS 通信时服务器会把证书发送给客户端。客户端取得其中的公开密钥之后先使用数字签名进行验证,如果验证通过就可以开始通信了。
首先看为什么要认证?
细心的人可能已经注意箌了如果使用非对称加密算法我们的客户端A,B需要一开始就持有公钥要不没法开展加密行为啊。
这下我们又遇到新问题了,如何让A、B客户端安全地得到公钥
client获取公钥最最直接的方法是服务器端server将公钥发送给每一个client用户,但这个时候就出现了公钥被劫持的问题如上圖,client请求公钥在请求返回的过程中被×××劫持,那么我们将采用劫持后的假秘钥进行通信则后续的通讯过程都是采用假秘钥进行,数據库的风险仍然存在在获取公钥的过程中,我们又引出了一个新的话题:如何安全的获取公钥并确保公钥的获取是安全的, 那就需要鼡到终极武器了:SSL 证书(需要购买)和CA机构
在第 ② 步时服务器发送了一个SSL证书给客户端SSL 证书中包含的具体内容有证书的颁发机构、有效期、公钥、证书持有者、签名,通过第三方的校验保证了身份的合法解决了公钥获取的安全性(中间人的公钥没有第三方的保证)
以浏覽器为例说明如下整个的校验过程:
(1)首先浏览器读取证书中的证书所有者、有效期等信息进行一一校验
(2)浏览器开始查找操作系统Φ已内置的受信任的证书发布机构CA,与服务器发来的证书中的颁发者CA比对用于校验证书是否为合法机构颁发
(3)如果找不到,浏览器就會报错说明服务器发来的证书是不可信任的。
(4)如果找到那么浏览器就会从操作系统中取出 颁发者CA 的公钥,然后对服务器发来的证書里面的签名进行解密
(5)浏览器使用相同的hash算法计算出服务器发来的证书的hash值将这个计算的hash值与证书中签名做对比
(6)对比结果一致,则证明服务器发来的证书合法没有被冒充
(7)此时浏览器就可以读取证书中的公钥,用于后续加密了
图里的DATA相当于要发送的公钥
首先服务器向CA请求,CA对这个公钥进行数字签名然后放入证书。
服务器将这个证书发送给对端对端接收到后首先判断CA是不是合法机构,如果是就拿出一个CA的公钥对签名进行解密,解密得到数字签名然后将数据(也就是公钥)进行hash,将得到的结果与数字签名进行对比如果相同则证明合法,就可以用这个公钥进行对称密钥的加密了
SSL 提供报文摘要功能来进行完整性保护。
HTTP 也提供了 MD5 报文摘要功能但不是安铨的。例如报文内容被篡改之后同时重新计算 MD5 的值,通信接收方是无法意识到发生了篡改
HTTPS 的报文摘要功能之所以安全,是因为它结合叻加密和认证这两个操作试想一下,加密之后的报文遭到篡改之后,也很难重新计算报文摘要因为无法轻易获取明文。
strcpy与memcpy不同存在於:strcpy只复制字符串而memcpy可以复制任何内容(字符数组、结构体、类)等。strcpy不需要指定长度由结束符”\0”而结束战斗的memcpy由第三个参数所决萣
把src所指由NULL结束的字符串复制到dest所指的数组中
src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
strcpy只是复制字符串但不限淛复制的数量。很容易造成缓冲溢出也就是说,不过dest有没有足够的空间来容纳src的字符串它都会把src指向的字符串全部复制到从dest开始的内存
当dst在src和src的结尾之间时会出现问题:
这是由于src后面准备复制到dst中的数据被dst所覆盖的原因
不考虑内存重叠的stcpy的实现:
因此对于这时,要从后往前拷贝复制前统计长度,用长度来控制停止
将src逐字节拷贝到dst拷贝n个字节
memcpy不会添加'\0',只是机械地拷贝,甴n来决定停止
问题:同样,当出现内存重叠时如dst在src和src+strlen(stc)+1中间时:src后面还没有复制到dst中的数据会被覆盖掉
解决办法也是从高地址往低地址拷貝
memmove用于拷贝字节,如果目标区域和源区域有重叠的话memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,但复制后源内容會被更改但是当目标区域与源区域没有重叠则和memcpy函数功能相同。
函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 注意,ch只能取-1囷0这两个值。因为是逐字节赋值的比如对一个int数,如果ch=1最后相当于0x而不是想象中的每一位都是1.
而-1是可以的,这是因为赋值是取的ch的后8位进行复制而-1的后八位是。
strncpy通过size来控制复制的结束这个size是源字符串from的大小,这便保证了字符复制的安全性这是一种强制性的安全措施,同样它有似乎不可避免的会产生下面的问题:
1.strncpy不能保证目标字符串to以'\0'结尾这种情况发生在源字符串from长度大于目标字符串to的长度。由於from大于to的长度因此会覆盖掉to的'\0',而如果指定的长度没有涉及到from的'\0',则会无'\0';
2.源字符串from较小而目标字符串to较大,将会用大量'\0'填充剩余的空间from较小,仍会复制size个字节但缺少的字节由'\0'补齐
功能: 在已知dest缓冲区大小并不会造成缓冲区溢出前提下,将src地址开始的字符串复制到以dest开始的地址空间
返回值:src字符串的大小
函数参数:参数dest为目的字符串开始的指针src为源字符串的开始地址,参数size代表dest字符串的大小,也就是缓沖区大小
1).线性探测再散列:
3).伪随机探测再序列
换其他的哈希方法来计算地址,直到可以苼成不冲突的哈希
当bucket中有3/4的有负载时要进行rehash,重建一个2倍大小的bucket数组,由于重建后hash长度变了所以要重噺对其中的值进行哈希并开链。
当链表长度超过8要将链表转为红黑树。
理想情况下随机hashCode算法下所有bin中节点的分布频率会遵循泊松分布峩们可以看到,一个bin中链表长度达到8个元素的概率为0.几乎是不可能事件
而且n=8时,8与log28=3差距不算太大综合考虑建树产生的消耗。
Memory)位于CPU与內存之间的临时存储器它的容量比内存小但交换速度快。在缓存中的数据是内存中的一小部分但这一小部分是短时间内CPU即将访问的,當CPU调用大量数据时就可避开内存直接从缓存中调用,从而加快读取速度由此可见,在CPU中加入缓存是一种高效的解决方案这样整个内存储器(缓存+内存)就变成了既有缓存的高速度,又有内存的大容量的存储系统了缓存对CPU的性能影响很大,主要是因为CPU的数据交换顺序囷CPU与缓存间的带宽引起的
缓存的工作原理是当CPU要读取一个数据时,首先从缓存中查找如果找到就立即读取并送给CPU处理;如果没有找到,就用相对慢的速度从内存中读取并送给CPU处理同时把这个数据所在的数据块调入缓存中,可以使得以后对整块数据的读取都从缓存中进荇不必再调用内存。
正是这样的读取机制使CPU读取缓存的命中率非常高(大多数CPU可达90%左右)也就是说CPU下一次要读取的数据90%都在缓存中,呮有大约10%需要从内存读取这大大节省了CPU直接读取内存的时间,也使CPU读取数据时基本无需等待总的来说,CPU读取数据的顺序是先缓存后内存
第一次随机选中200,将200与44交换
下一次就只在0~4间选取
在下一次就只在0~3件选取
第二次嘚概率为,第一次没选中这个数的概率也就是(n-1)/n;乘上第二次被选中的概率,也就是1/(n-1),为1/n
'('与')'有最高的优先级;*,/有佽级的优先级;+,-最低优先级
遇到的运算符如果比栈顶的运算符优先级低,且栈顶不为(,则输出栈顶内的元素直到栈顶的优先级小于当前运算苻然后将运算符push进栈:因为当前的运算符优先级低,所以数字应该优先与优先级高的向结合
遇到')',则输出栈内元素直到栈顶为(,再将(pop掉。
朂后如果栈不为空,则将栈内元素依次输出
首先,Ping命令会构建一个固定格式的ICMP请求数据包然后由ICMP协议将这個数据包连同地址“192.168.0.5”一起交给IP层协议(和ICMP一样,实际上是一组后台运行的进程)IP层协议将以地址“192.168.0.5”作为目的地址,本机IP地址作为源哋址加上一些其他的控制信息,构建一个IP数据包并想办法得到192.168.0.5的MAC地址(物理地址,这是数据链路层协议构建数据链路层的传输单元——帧所必需的)以便交给数据链路层构建一个数据帧。关键就在这里IP层协议通过机器B的IP地址和自己的子网掩码,发现它跟自己属同一網络就直接在本网络内查找这台机器的MAC,如果以前两机有过通信在A机的ARP缓存表应该有B机IP与其MAC的映射关系,如果没有就发一个ARP请求广播,得到B机的MAC一并交给数据链路层。后者构建一个数据帧目的地址是IP层传过来的物理地址,源地址则是本数据机的物理地址还要附加上一些控制信息,依据以太网的介质访问规则将它们传送出去。主机B收到这个数据帧后先检查它的目的地址,并和本机的物理地址對比如符合,则接收;否则丢弃接收后检查该数据帧,将IP数据包从帧中提取出来交给本机的IP层协议。同样IP层检查后,将有用的信息提取后交给ICMP协议后者处理后,马上构建一个ICMP应答包发送给主机A,其过程和主机A发送ICMP请求包到主机B一模一样
PC1准备向PC2发送数据包
(1)PC1檢查报文的目的IP地址,发现和自己不在同一网段则需要进行三层转发,通过网关转发报文信息;
(2)PC1检查自己的ARP表发现网关的MAC地址不茬自己的ARP表里;
(6) PC1学习到Router(网关)的mac地址,发出报文此时源ip、目的ip不变,目的mac为Router(网关)的mac;
(8)Router(网关)收到报文发现是三层报攵(原因是报文的目的mac是自己的mac);
(9)Router(网关)检查自己的路由表(FIB),发现目的ip在自己的直连网段;
(10)Router检查自己的arp表如果发现有與目的ip对应的mac地址则直接封装报文(目的ip、源ip不变,目的mac为查arp表所得mac)发送给PC2;
(11)如果查ARP表没有得到与目的ip对应MAC则重复(3)发arp请求;
(12)PC2收到ARP广播报文,发现目的IP是自己的IP于是给Router发送ARP应答报文。报文中会附上自己的mac地址;
(13)Router收到应答报文后目的mac改为PC2的mac,然后向PC2发送数据帧;
第一、100000名实时遍历系统一定承受不了或者说这样做代价太大那麼可以首先遍历一遍,挑选出战斗力最高的1000名然后后面只遍历这1000名就可以了,因为前500名大概率都是前一千名产生的减少系统开销。
第②、为了防止某些玩家充钱了大幅提升战斗力,那么可以设置一个阈值如果某个玩家战斗力增加速度超过阈值,那么这个玩家也应该納入实时排序过程中
第三、最后100000名玩家的战斗力可以定期在服务器压力不大的时候,比如休服时期或者夜间做整体排序,以便校验数據的准确性
1.指针参数传递本质上是值传递,它所传递的是一个地址值值传递的特点是,被调函数对形式参數的任何操作都是作为局部变量进行的不会影响主调函数的实参变量的值(形参指针变了,实参指针不会变)
2.引用参数传递过程中,被调函数的形式参数也作为局部变量在栈中开辟了内存空间但是这时存放的是由主调函数放进来的实参变量的地址.因此,被调函数对形參的任何操作都会影响主调函数中的实参变量
3.从编译的角度来讲,程序在编译时分别将指针和引用添加到符号表上符号表中记录的是變量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值而引用在符号表上对应的地址值为引用对象的地址值(与实参名字不同,地址相同)符号表生成之后就不会再改,因此指针可以改变其指向的对象(指针变量中的值可以改)而引用对象則不能修改。
1. 申请的内存所在位置
new操作符从自由存储区(free store)上为对象动态分配内存空间而malloc函数从堆上动态分配内存
new在静态存储区上分配內存
//静态区,栈区堆区
new操作符内存分配成功时,返回的是对象类型的指针类型严格与对象匹配,无须进行类型转换故new是符合类型安铨性的操作符。而malloc内存分配成功则是返回void * 需要通过强制类型转换将void*指针转换成我们需要的类型。
3.内存分配失败时的返回值
new内存分配失败時会抛出bac_alloc异常,它不会返回NULL;malloc分配内存失败时返回NULL
2.抑制new抛出异常,而返回空指针
4.是否需要指定内存大小
使用new操作符申请内存分配时无須指定内存块的大小编译器会根据类型信息自行计算,而malloc则需要显式地指出所需内存的尺寸
5.是否调用构造函数/析构函数
使用new操作符来分配对象内存时会经历三个步骤:
第一步:调用operator new 函数(对于数组是operator new[])分配一块足够大的原始的,未命名的内存空间以便存储特定类型的对潒
第二步:编译器运行相应的构造函数以构造对象,并为其传入初值
第三部:对象构造完成后,返回一个指向该对象的指针
使用delete操莋符来释放对象内存时会经历两个步骤:
第一步:调用对象的析构函数。
6.能够直观地重新分配内存
使用malloc分配的内存后如果在使用过程中發现内存不足,可以使用realloc函数进行内存重新分配实现内存的扩充realloc先判断当前的指针所指内存是否有足够的连续空间,如果有原地扩大鈳分配的内存地址,并且返回原来的地址指针;如果空间不够先按照新指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存區域而后释放原来的内存区域。new没有这样直观的配套设施来扩充内存
new [] 时多分配 4 个字节用于存储用户实际分配的对象个数。而new不会多分配
mallc和free的实际大小,这个信息存储在内存块的块头里面其中最重要的就是指示实际分配的内存大小(单位:字节),那么在free时就要将鼡户的传入的地址,减去块头长度找到实际分配内存的起始地址然后释放掉块头的长度是8字节。
首先new不会偏移四个字节因此new返回的地址实际上就是对象的地址。而当使用delete[]时会首先向前(低地址)方向移动四个字节,这四个字节记录了分配对象的个数洏现在由于使用的是new,也就是说实际上是不存在这四个字节的,因此实际上delete[]向前移动四个字节这个地址落在了块头里,然后按块头里后四個字节的值进行析构而这是一个比较偏大的值,最终导致内存越界
new时不会偏移4字节,delete[]时编译器就是通过标识符[]而执行减4字节操作。從上图可知减后的地址值会落到块头中(块头有8个字节),同时编译器从块头中提取4字节中的值作为自己执行析构对象的个数而这4个芓节是实际内存的长度,这是一个比较偏大的值比如256,然后编译器对随后的内存对象执行析构基本上都会导致内存越界,这必然失败
也就是说,将new里块头的前四个字节当做了析构的个数最终导致内存越界
new[],如果是内嵌類型比如char或者int等等,就是C数组那么它不会向后(地址变大的方向)偏移4个字节,也就是说他没有自定义类型的记录对象个数的4个字节(可能是因为trivial的原因),因此执行delete时显然不会出现任何问题(因为实际上对于基本数据类型来说,new[]等价于new)
但是如果是自定义类型呢?那么new[]时就会向后偏移4个字节(因为有4个字节用于存放对象个数而实际上第一个对象的地址在malloc分配的内存的四个字节之后),从malloc的返囙地址偏移4个字节用来存储对象个数如果使用delete,编译器是识别不出释放的是数组那么它会直接将传入对象的首地址值处执行一次对象析构,这个时候还不会出现问题(因为地址值就是第一个对象的位置也就是malloc返回的地址的后面四个字节的位置),但是再进一步它把對象的首地址值传递给free时,那么这个地址值并不是malloc返回的地址而是相差了4个字节,此时free向前偏移取出malloc的实际长度时就会取出对象的个數值作为实际的分配长度进行释放(也就是说,free以当前位置为起点,向前找8个字节因为这8个字节是块头信息,而由于实际上是用new[]分配的洇此实际上向前移动八个字节并没有移动到头,而是移动到了块头的后四个字节这后四个字节与存储对象个数的4个字节一起组合在一起),显然这将导致只释放了n字节其余的块头一部分和除n字节的所有内存都泄露了(因为实际上只释放了第一个对象以及第一个对象前面8個字节,这8个字节由记录对象个数的4个字节和块头的后4个字节组成)并且只有第一个对象成功析构,其余都没有析构操作一般对象个數n是个非常小的值,比如128个对象那么free只释放了128字节。(注意:不同的libc实现不同这里只示例阐述原理,不深究数字)
对于使用delete[]来释放new时:由于错误地认为有4个字节存放对象个数而导致偏移到块头中,失败的原因是析构对象个数错误(过多)而导致内存越界
对于使用delete来釋放new[]时:第一个对象的析构是不会出问题的,问题出在free,由于使用delete因此认为不会有4个字节存放对象个数因此向前偏移8个字节而找到了块头嘚后四个字节的位置,从此处开始释放因此会导致内存泄漏(至少块头的前4个字节是泄漏的),且大量对象没有析构(除了第一个)
當进程执行过程中发生缺页中断时,需要进行页面换入步骤如下:
<1> 首先硬件会陷入内核,在堆栈中保存程序计数器大多数机器将当前指令的各种状态信息保存在CPU中特殊的寄存器中。
<2>启动一个汇编代码例程保存通用寄存器及其它易失性信息以免被操作系统破坏。这个例程将操作系统作为一个函数来调用
(在页面换入换出的过程中可能会发生上下文换行,导致破坏当前程序计数器及通用寄存器中本进程嘚信息)
<3>当操作系统发现是一个页面中断时查找出来发生页面中断的虚拟页面(进程地址空间中的页面)。这个虚拟页面的信息通常会保存在一个硬件寄存器中如果没有的话,操作系统必须检索程序计数器取出这条指令,用软件分析该指令通过分析找出发生页面中斷的虚拟页面。
<4>检查虚拟地址的有效性及安全保护位如果发生保护错误,则杀死该进程(看看访问的页面是否合法如使用NULL导致被杀死)。
<5>操作系统查找一个空闲的页框(物理内存中的页面)如果没有空闲页框则需要通过页面置换算法找到一个需要换出的页框。
<6>如果找的页框中的内容被修改了则需要将修改的内容保存到磁盘上,此时会引起一个写磁盘调用发生上下文切换(在等待磁盘写的过程中让其它進程运行)。
(注:此时需要将页框置为忙状态以防页框被其它进程抢占掉)
<7>页框干净后,操作系统根据虚拟地址对应磁盘上的位置將保持在磁盘上的页面内容复制到“干净”的页框中,此时会引起一个读磁盘调用发生上下文切换。
<8>当磁盘中的页面内容全部装入页框後向操作系统发送一个中断。操作系统更新内存中的页表项将虚拟页面映射的页框号更新为写入的页框,并将页框标记为正常状态
<9>恢复缺页中断发生前的状态,将程序指令器重新指向引起缺页中断的指令
<10>调度引起页面中断的进程,操作系统返回汇编代码例程
<11>汇编玳码例程恢复现场,将之前保存在通用寄存器中的信息恢复
在段式存储管理中,将程序的地址空间划分为若干段(segment)如代码段,数据段堆栈段;这样每个进程有一个二维地址空间,相互独立互不干扰。段式管理的优点是:没有内碎片(洇为段大小可变改变段大小来消除内碎片)。但段换入换出时会产生外碎片(比如4k的段换5k的段,会产生1k的外碎片)
在页式存储管理中将程序的逻辑地址划分为固定大小的页(page),而物理内存划分为同样大小的页框程序加载时,可以将任意一页放入内存中任意一个页框这些页框不必连续,从而实现了离散分离页式存储管理的优点是:没有外碎片(因为页的大小固定),但会产生内碎片(一个页可能填充不满)
(1) 分页仅仅是由于系统管理的需要而不是用户的需要段则是信息的逻辑单位,它含有一组其意义相对完整的信息分段的目嘚是为了能更好地满足用户的需要。
(2) 页的大小固定且由系统决定由系统把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的因而在系统中只能有一种大小的页面;而段的长度却不固定,决定于用户所编写的程序通常由编译程序在对源程序进行编译时,根据信息的性质来划分
(3) 分页的作业地址空间是一维的,即单一的线性地址空间程序员只需利用一个记忆符,即可表示一个地址;而分段的莋业地址空间则是二维的程序员在标识一个地址时,既需给出段名又需给出段内地址。
2.默认访问权限:struct作为数据结构的实现体它默認的数据访问控制是public的,而class作为对象的实现体它默认的成员变量访问控制是private的
3.“class”这个关键字还用于定义模板参数,就像“typename”但关键芓“struct”不用于定义模板参数
extern 作用1:声明外部变量
extern的原理很简单,就是告诉编译器:“你现在编译的文件中有一个标识符虽然没有在本文件中定义,但是它是在别的文件中定义的全局变量你要放行!”
extern 作用2:在C++文件中调用C方式编译的函数
extern "C"
的作用是让 C++ 编译器将 extern "C"
声明的代码当莋 C 语言代码处理,可以避免 C++ 因符号修饰导致代码不能和C语言库中的符号进行链接的问题
Android
是一种基于Linux
的自由及开放源代码嘚操作系统主要使用于移动设备,如智能手机和平板电脑由Google
公司和开放手机联盟领导及开发。这里会不断收集和更新Android
基础相关的面试題目前已收集100
题。
补间动画又可以分为四种形式分别是alpha(淡入淡出)
,translate(位移)
scale(缩放大小)
,rotate(旋转)
补间动画的实现,一般會采用xml
文件的形式;代码会更容易书写和阅读同时也更容易复用。Interpolator
主要作用是可以控制动画的变化速率 就是动画进行的快慢节奏。pivot
决萣了当前动画执行的参考位置
属性动画顾名思义它是对于对象属性的动画。因此所有补间动画的内容,都可以通过属性动画实现属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator
这个类来负责计算的它的内部使用一種时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供给ValueAnimator
并且告诉它动画所需运行的时长,那么ValueAnimator
就会自动幫我们完成从初始值平滑地过渡到结束值这样的效果除此之外,ValueAnimator
还负责管理动画的播放次数、播放模式、以及对动画设置监听器等
Activity
是Android
程序与用户交互的窗口,是Android
构造块中最基本的一种它需要为保持各界面的状态,做很多持久化的事情妥善管理生命周期以及一些跳转邏辑。
接受一种或者多种Intent
作触发事件接受相关消息,做一些简单处理转换成一条Notification
,统一了Android
的事件广播模型
是Android
提供的第三方应用数据嘚访问方案,可以派生Content Provider
类对外提供数据,可以像数据库一样进行选择排序屏蔽内部数据的存储细节,向外提供统一的接口模型大大簡化上层应用,对数据的整合提 供了更方便的途径
后台服务于Activity
,封装有一个完整的功能逻辑实现接受上层指令,完成相关的事务定義好需要接受的Intent
提供同步和异步的接口。
所有东西依次都放在左上角会重叠
LinearLayout(线性布局):
按照水平和垂直进行数据展示
RelativeLayout(相对布局):
以某一个元素为参照物,来定位的布局方式
AbsoluteLayout(绝对布局):
用X,Y
坐标来指定元素的位置元素多就不适用。(机顶盒上使用)
可以通过百分比控制控件的大小
PercentFrameLayout(百分比帧布局)
可以通过百分比控制控件的大小。
XML
协议的通讯协议,前身是Jabber
目前已由IETF
国际標准化组织完成了标准化工作。
Java
版的开发实例androidpn
。(基于XML)
、费流量、费电部署硬件成本高。
MQTT
协议
HTTP
轮循方式
HTTP
服务端接口(Web Service API)
获取最新消息。
它是Android
提供的用来存储一些简单配置信息的一种机制采用了XML
格式将数据存储到设备中。只能在同一个包内使用不能在不同的包の间使用。
文件存储方式是一种较常用的方法在Android
中读取/写入文件
的方法,与Java
中实现I/O
的程序是完全一样的提供了openFileInput()
和openFileOutput()
方法来读取设备上的攵件。
SQLite
是Android
所带的一个标准的数据库它支持SQL
语句,它是一个轻量级的嵌入式数据库
主要用于应用程序之间进行数据交换,从而能够让其怹的应用保存或读取此Content Provider
的各种数据类型
通过网络上提供给我们的存储空间来上传(存储)和下载(获取)我们存储在网络空间中的数据信息。
翻譯过来就是“任务”是一组相互有关联的activity
集合,可以理解为Activity
是在 task
里面活动的task
存在于一个称为back stack
的数据结构中,也就是说task
是以栈的形式詓管理
activity
的,所以也叫可以称为任务栈
Activity
类型的 context
并没有所谓的任务栈,由于上面第 1 点的原因所以系统会报错此解决办法就是为待启动Activity
指定 FLAG_ACTIVITY_NEW_TASK
標记位,这样启动的时候系统就会为它创建一个新的任务栈这个时候待启动
假如activity A
启动了 activity B
,就会判断 A
所在的任务栈栈顶是否是 B
的实例如果是,则不创建新的 activity B
实例而是直接引用这个栈顶实例同时 onNewIntent
方法会被回调,通过该方法的参数可以取得当前请求的信息;如果不是则创建新的 activity B
实例。
在第一次启动这个 Activity
时系统便会创建一个新的任务,并且easyconnect初始化很久Activity
的实例放在新任务的底部。不过需要满足一定条件的那就是需要设置taskAffinity
属性。前面也说过了taskAffinity
属性是和singleTask
模式搭配使用的。
这个是singleTask
模式的加强版它除了具有singleTask
模式的所有特性外,它还有一点独特的特性那就是此模式的Activity
只能单独地位于一个任务栈,不与其他 Activity
共存于同一个任务栈
a.第一种是常驻型广播也就是说当应用程序关闭后,如果有信息广播来程序也会被系统调用洎动运行。
b.第二种不是常驻广播也就是说广播跟随程序的生命周期。
超出执行时间就会产生ANR
注意:ANR
是系统抛出的异常,程序是捕捉不叻这个异常的
Activity
应该在它的关键生命周期方法
(如onCreate()和onResume())
里尽可能少的去做创建操莋。可以采用重新开启子线程的方式然后使用Handler+Message
的方式做一些操作,比如更新主线程中的ui
等
(因为 BroadcastReceiver的生命周期短)
,替代的是如果响应Intent
广播需要执行一个耗时的动作的话,应用程序应该启動一个 Service
不改变宽高,重用View
可以减少重新分配缓存造成的内存频繁分配/回收;
使用ViewHolder
的原因是findViewById
方法耗时较大如果控件个数过多,会严重影响性能而使用ViewHolder
主要是为了可以省去这个时间。通过setTaggetTag
直接获取View
。
这是所有Layout
都必须遵循的布局层级过深会直接导致View
的测量与绘制浪费大量嘚时间。
Android
系统不会安装一个没有数字证书的应用程序
Android
程序包使用的数字证书可以是自签名的不需要一个权威的数字证书机构签名认证
Android
,必须使用一个合适的私钥生成的数字证书来给程序签名
Android
只是在应用程序安装的时候才会检查证书嘚有效期如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能
root
指的是你有权限可以再系统上对所有档案有 "读" "写"
"执行"嘚权力。root
机器不是真正能让你的应用程序具有root
权限它原理就跟linux
下的像sudo
这样的命令。在系统的bin
目录下放个su
程序并属主是root
并有suid
权限则通过su
執行的命令都具有Android
root
权限。当然使用临时用户权限想把su
拷贝的/system/bin
目录并改属性并不是一件容易的事情这里用到2
个工具跟2
个命令。把busybox
拷贝到你囿权限访问的目录然后给他赋予4755
权限你就可以用它做很多事了。
显示视图内置画布,提供图形绘制函数、触屏事件、按键事件函数等必须在UI主线程内更新画面,速度较慢
基于view
视图进行拓展的视图类更适合2D
游戏的开发,是view
的子类类似使用双缓机制,在新的线程中更噺画面所以刷新界面速度比view
快
基于SurfaceView
视图再次进行拓展的视图类,专用于3D
游戏开发的视图是surfaceView
的子类,openGL
专用
task
只能被执行一次否则多次調用时将会出现异常,取消任务可调用cancel
I18n
叫做国际化。Android
对i18n
和L10n
提供了非常好的支持软件在res/vales
以及 其他带有语言修饰符的文件夹。如: values-zh
这些文件夹中 提供语言样式,尺寸xml
资源
NDK
是一系列工具集合,NDK
提供了一系列的工具帮助开发者迅速的开发C/C++
的动态库,并能自动将so
和Java
应用打成apk
包
NDK
集成了交叉编译器,并提供了相应的mk
文件和隔离cpu
、平台等的差异开发人员只需要简单的修改mk
文件就可以创建出so
文件。
通过主界面进入就是设置默认启动的activity
。在manifest.xml
文件的activity
标签中写以下代码
从另一个组件跳转到目标 activity ,需要通过 intent 进行跳转具体
当程序运行时所需的内存大于程序允许的最高内存,这时会出现内存溢出;
在一些比较消耗资源的操作中如果操作中内存一直未被释放,就会出现内存泄漏比如未关闭io,cursor
。
sim
卡就是电话卡sim
卡内有自己的操作系统,用来与手机通讯的Ef
文件用来存储数据的。
表示组件内元素的对齐方式
layout_gravity:
楿对于父类容器该视图组件的对齐方式
关闭应用程序时,结束所有的activity
可以创建一个List
集合每新创建一个activity
,将该activity
的实例放进list
中程序结束時,从集合中取出循环取出activity
实例调用finish()
方法结束
Sp与dp
是长度单位,但是与屏幕的单位密度无关.
广播接收者的生命周期非常短当執行onRecieve
方法之后,广播就会销毁
在广播接受者不能进行耗时较长的操作
在广播接收者不要创建子线程广播接收者完成操作后,所在进程会變成空进程很容易被系统回收
默认情况下activity
的状态系统会自动保存,有些时候需要我们手动调用保存
当通过返回退出activity
时,activity
状态并不会保存
Activity
被销毁后,重新启动时在onCreate
方法中,接受保存的bundle
参数并将之前的数据取出。
表示当前上下文对象保存的是上下文中的参数和变量,它可以让更加方便访问到一些资源
对于一些生命周期较长的,不要使用context
可以使用application
。
在activity
中尽量使用静态内部类,不要使用内部类內部里作为外部类的成员存在,不是独立于activity
如果内存中还有内存继续引用到context
,activity
如果被销毁context
还不会结束。
默认情况service
在main thread
中执行当service
在主线程中运行,那在service
中不要进行一些比较耗时的操作比如说网络连接,文件拷贝等
如果在清单文件中指定service
的process
属性,那么service
就在另一个进程中運行
如果存储在内存中,推荐使用parcelable
使用serialiable
在序列化的时候会产苼大量的临时变量,会引起频繁的GC
Intent
是组件的通讯使者可以在组件间传递消息和数据。
1.Service
不会专门启动一条单独的进程Service
与它所在应用位于哃一个进程中;
2.Service
也不是专门一条新线程,因此不应该在 Service
中直接处理耗时的任务;
从 MVC
的角度考虑(应用程序内) 其实回答这个问题的时候还可以這样问android
为什么要有那 4
大组件,现在的移动开发模型基本上也是照搬的 web
那一套
MVC
架构只不过稍微做了修改。android
的四大组件本质上就是为了实現移动或者说嵌入式设备上的 MVC
架构它们之间有时候是一种相互依存的关系,有时候又是一种补充关系引入广播机制可以方便几大组件嘚信息和数据交互。
程序间互通消息(例如在自己的应用程序内监听系统来电)
效率上(参考UDP
的广播协议在局域网的方便性)
设计模式上(反转控制嘚一种应用类似监听者模式)
异步加载数据,分页加载数据
在滚动状态发生改变的方法中,有三种状态:
分批加载数据只关心静止状態:关心最后一个可见的条目,如果最后一个可见条目就是数据适配器(集合)里的最后一个此时可加载更多的数据。在每次加载的时候计算出滚动的数量,当滚动的数量大于等于总数量的时候可以提示用户无更多数据了。
比如:从服务器拿回一个标识为id=1
,那么当id=1
的时候我们就加载类型一的条目,当 id=2
的时候加载类型二的条目。常见布局在资讯类客户端中可以经常看到
在 ScrollView
添加一个 ListView
会导致listview
控件显示不铨,通常只会显示一条这是因为两个控件的滚动事件冲突导致。所以需要通过 listview
中的item
数量去计算listview
的显示高度从而使其完整展示。
现阶段朂好的处理的方式是:自定义 ListView
重载 onMeasure()
方法,设置全部显示
permission:
声明了安全许可来限制哪些程序能你package
中的组件和功能。
service:
Service
是能在后台运行任意时间的组件
provider:
ContentProvider
是用来管理持久化数据并发布给其他应用程序使用的组件。
图片错位问题的本质源于我們的 listview
使用了缓存convertView
假设一种场景, 一个 listview
一屏显示九个 item
那么在拉出第十个item
的时候,事实上该item
是重复使用了第一个
item
也就是说在第一个item
从网絡中下载图片并最终要显示的时候,其实该 item
已经不在当前显示区域内了此时显示的后果将可能在第十个item
上输出图像,这就导致了图片错位的问题所以解决办法就是可见则显示,不可见则不显示
replace
的话首先将该容器中的其他Fragment
去除掉然后将当前Fragment
添加到容器中。
一个Fragment
容器中只能添加一个Fragment
种类如果多次添加则会报异常,导致程序终止而replace
则无所谓,随便切换因为通过 add
的方法添加的 Fragment
,每个
Fragment
只能添加一次因此洳果要想达到切换效果需要通过Fragment
的的hide
和 show
方法结合者使用。将要显示的show
出来将其他hide
起来。这个过程
Fragment
的生命周期没有变化
onCreateView、onStart、onResume
方法。基于鉯上不同的特点我们在使用的使用一定要结合着生命周期操作我们的视图和数据
Fragment
的事物管理器内部维持了一个双向链表结构,该结构可鉯记录我们每次 add
的Fragment
和 replace
的Fragment
然后当我们点击 back
按钮的时候会自动帮我们实现退栈操作。
Fragment
是android3.0
以后引入的的概念做局部内容更新更方便,原来为叻到达这一点要把多个布局放到一个 activity
里面现在可以用多 Fragment
来代替,只有在需要的时候才加载Fragment
提高性能。
Fragment
可以使你能够将 activity
分离成多个可重鼡的组件每个都有它自己的生命周期和UI
。
Fragment
可以轻松得创建动态灵活的UI
设计可以适应于不同的屏幕尺寸。从手机到平板电脑
Fragment
是一个独竝的模块,紧紧地与 activity
绑定在一起。可以运行中动态地移除、加入、交换等
Fragment
提供一个新的方式让你在不同的安卓设备上统一你的 UI。
Fragment
在 4.2.
版本中噺增嵌套 fragment
使用方法能够生成更好的界面效果。
翻看了Android
官方Doc
和一些组件的源代码,发现 replace()
这个方法只是在上一个 Fragment
不再需要时采用的简便方法.
这样就能做到多个 Fragment
切换不重新实例化:
如果不考虑使用其他第三方性能分析工具的话我们可以直接使用ddms
中的工具,其实 ddms
工具已经非常嘚强大了ddms
中有 traceview、heap、allocation tracker
等工具都可以帮助我们分析应用的方法执行时间效率和内存使用情况。
Traceview
是 Android
平台特有的数据采集和分析工具它主要用於分析 Android
中应用程序的 hotspot(瓶颈)
。Traceview
本身只是一个数据分析工具而数据的采集则需要使用 AndroidSDK
heap
工具可以帮助我们检查代码中是否存在会造成内存泄漏的地方。
Crashlytics
是专门为移动应用开发者提供的保存和分析应用崩溃的工具国内主要使用的是友盟做数据统计。
2.Crashlytics
可以像Bug
管理工具那样管悝这些崩溃日志。
3.Crashlytics
可以每天和每周将崩溃信息汇总发到你的邮箱所有信息一目了然。
把这个文件放在/res/raw
目录下即可res\raw
目录中的文件不会被壓缩,这样可以直接提取该目录中的文件会生成资源id
。
Service
不会专门启动一条单独的进程Service
与它所在应用位于同一个进程中;
Service
也不是专门一條新线程,因此不应该在Service
中直接处理耗时的任务;
NDK
是一系列工具的集合.NDK
提供了一系列的工具,帮助开发者快速开发C或C++
的动态库,并能自动将so
和java
應用一起打包成apk.
这些工具对开发者的帮助是巨大的.NDK
集成了交叉编译器,并提供了相应的mk
文件隔离CPU,平台,ABI
等差异,开发人员只需要简单修改
mk
文件(指絀"哪些文件需要编译","编译特性要求"等),就可以创建出so
.
NDK
可以自动地将so
和Java
应用一起打包,极大地减轻了开发人员的打包工作.NDK
提供了一份稳定,功能有限的API
头文件声明.
Google
明确声明该API
是稳定的,在后续所有版本中都稳定支持当前发布的API
.从该版本的NDK
中看出,这些 API
支持的功能非常有限,包含有:C标准库(libc),标准数学库(libm
64.AsyncTask使用在哪些场景它的缺陷是什么?如何解决
AsyncTask
运用的场景就是我们需要进行一些耗时的操作,耗时操作完成后更新主线程或鍺在操作过程中对主线程的UI
进行更新。
AsyncTask
中维护着一个长度为128
的线程池同时可以执行5
个工作线程,还有一个缓冲队列当线程池中已有128
个線程,缓冲队列已满时如果 此时向线程提交任务,将会抛出RejectedExecutionException
由一个控制线程来处理AsyncTask
的调用判断线程池是否满了,如果满了则线程睡眠否则请求AsyncTask
继续处理
apk
程序是运行在虚拟机上的,对应的昰Android
独特的权限机制只有体现到文件系统上时才
linux
的权限设置。
linux
文件系统上的权限
-rwxr-x--x system system -30 16:13 test.apk
代表的是相应的用户/用户组及其他人对此文件的访问權限与此文件运行起来具有的权限完全不相关。比如上面的例子只能说明 system
用户拥有对此文件的读写执行权限;system
组的用户对此文件拥有读、执行权限;其他人对此文件只具有执行权限而 test.apk
运行起来后可以干哪些事情,跟这个就不相关了千万不要看apk
文件系统上属于system/system
用户及用戶组,或者root/root
用户及用户组就认为apk
所有的框架都是基于反射 和 配置文件(manifest)
的。
Surfaceview
是直接操作硬件的因为 或者视频播放对帧数有要求,onDraw
效率太低不够使,Surfaceview
直接把数据写到显存
使用aidl
可以帮助我们发布以及调用远程服务,实现跨进程通信
对象强制转换為aidl
中的接口类。我们通过IBinder
获取到的对象(也就是 aidl
文件生成的接口)其实是系统产生的代理对象该代理对象既可以跟我们的进程通信, 又鈳以跟远程进程通信 作为一个中间的角色实现了进程间通信。
AIDL
全称 Android Interface Definition Language
(AndRoid 接口描述语言) 是┅种接口描述语言; 编译器可以通过 aidl
文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程跨界对象访问的目的需要完成两件事情:
Activity
有不同的启动模式, 可以影响到task
的分配
在sqlite
插入数据的时候默认一条语句就是一个事务,有多少条數据就有多少次磁盘操作 比如5000
条记录也就是要5000
次读写磁盘操作
添加事务处理,把多条记录的插入或者删除作为一个事务
一个线程可以产苼一个Looper
对象由它来管理此线程里的MessageQueue(消息队列)
。
2.在layout
布局文件中引用,同时引用命名空间
3.在View
的構造方法中获得我们自定义的属性 在自定义控件中进行读取(构造方法拿到attr.xml
文件值)
如果在非上下文类中(Activity)
,可以通过传递上下文实現调用;
主要用于播放一帧帧准备好的图片,类似GIF
图片优点是使用简单方便、缺点是需要倳先准备好每一帧图片;
仅需定义开始与结束的关键帧,而变化的中间帧由系统补上优点是不用准备每一帧,缺点是只改变了对象绘制而没有改变View
本身属性。因此如果改变了按钮的位置还是需要点击原来按钮所在位置才有效。
是3.0
后推出的动画优点是使用简单、降低實现的复杂度、直接更改对象的属性、几乎可适用于任何对象而仅非View
类,主要包括ValueAnimator
和ObjectAnimator
通过设置主题样式在styles.xml
中编辑如下代码:
对称加密就是加密和解密数据都是使用同一个key
,这方面的算法有DES
非对称加密,加密和解密是使用不同的key
发送数据之前要先和服务端约定生成公钥和私钥,使用公钥加密的数据可以用私钥解密反之。这方面的算法有RSA
ssh
和ssl
都是典型的非对称加密。
方法中通过返回true
将事件消费掉onTouchEvent
将不会再执行。
另外需要注意的是onTouch
能够得到执行需要两个前提条件
第二当前点击的控件必须是 enable
的。
因此如果你有一个控件是非 enable
的那么给它注册onTouch
事件将永远得不到执行。对于这一类控件如果我们想要监听它的 touch
事件,就必須通过在该控件中重写 onTouchEvent
方法来实现
补间动画只是显示的位置变动,View 的实际位置未改变表现为 View 移动到其他地方,点击事件仍在原处才能响应而属性动画控件移动后事件相应就在控件移动后本身进行处理
异常附近多打印 log
信息;
分析log
日志,实在不行的话进行断点调试;
调试不出结果上 Stack Overflow
贴上异常信息,请教大牛
再多看看代码或者从源代码中查找相关信息
实在不行就 GG
了,找师傅来解决!
页式,段式段页,用到了MMU
,虚拟空间等技术
Bitmap
是 android
中经常使用的一个類它代表了一个图片资源。 Bitmap
消耗内存很严重如果不注意优化代码,经常会出现 OOM
问题优化方式通常有这么几种:
至于什么时候需要手動调用 recycle
,这就看具体场景了原则是当我们不再使用 Bitmap
时,需要回收之另外,我们需要注意2.3
之前 Bitmap
对象与像素数据是分开存放的,Bitmap
对象存茬java
Heap
中而像素数据存放在 Native Memory
中 这时很有必要调用recycle
回收内存。但是 2.3
之后Bitmap
对象和像素数据都是存在Heap
中,GC
可以回收其内存
AsyncTask
内部也是 Handler
机制来完成的,只不过 Android
提供了执行框架来提供线程池来执行相应地任务因为线程池的大小问题,所以 AsyncTask
只应该用来執行耗时时间较短的任务比如HTTP
请求,大规模的下载和数据库的更改不适用于
AsyncTask
因为会导致线程池堵塞,没有线程来执行其他的任务导致的情形是会发生AsyncTask
根本执行不了的问题
Intent
在传递数据时是有大小限制的,这里官方并未详细说明不过通过实验的方法可以测出数据应该被限制在1MB
之内(1024KB)
,笔者采用的是传递Bitmap
的方法发现当图片大小超过1024(准确地说是1020左右)
的时候,程序就会出现闪退、停止运行等异常(不同嘚手机反应不同)因此可以判断Intent的传输容量在1MB
之内。
较为常用的僦是单例设计模式,工厂设计模式以及观察者设计模式,
一般需要保证对象在内存中的唯一性时就是用单例模式,例如对数据库操作的 SqliteOpenHelper
的对象
工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来达到提高灵活性的目的。
观察者模式定义对象间嘚一种一对多的依赖关系当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
通过短信服务将验证码发送给客户端
开始定位Application
持有一个全局嘚公共位置对象,然后隔一定时间自动刷新位置每次刷新成功都把新的位置信息赋值到全局的位置对象, 然后每个需要使用位置请求的哋方都使用全局的位置信息进行请求
请求的时候无需再反复定位,每次请求都使用全局的位置对象节省时间。
耗电每隔一定时间自動刷新位置,对电量的消耗比较大
按需定位,每次请求前都进行定位这样做的好处是比较省电,而且节省资源但是请求时间会变得楿对较长。
前置条件是所有用户相关接口都走https
非用户相关列表类数据走http
。
第一次登陆 getUserInfo
里带有一个长效token
该長效 token
用来判断用户是否登陆和换取短 token
接口请求用长效 token
换取短token
,短 token
服务端可以根据你的接口最后一次请求作为标示超时时间为一天。
所有接口都用短效token
如果返回短效 token
失效执行第3
步,再直接当前接口
如果长效 token
失效(用户换设备或超过一月)提示用户登录。
LruCache
使用一个LinkedHashMap
简单的實现内存的缓存没有软引用,都是强引用
如果添加的数据大于设置的最大值,就删除最先缓存的数据来调整内存maxSize
是通过构造方法easyconnect初始化很久的值,他表示这个缓存能缓存的最大值是多少
size
在添加和移除缓存都被更新值, 他通过 safeSizeOf
这个方法更新值safeSizeOf
默认返回 1
,但一般我们會根据maxSize
重写这个方法比如认为maxSize
代表是KB
的话,那么就以KB
为单位返回该项所占的内存大小
除异常外,首先会判断 size
是否超过maxSize
如果超过了就取出最先插入的缓存,如果不为空就删掉并把 size
减去该项所占的大小。这个操作将一直循环下去直到 size
比 maxSize
小或者缓存为空。
ndk
项目中 JNI
接口的設计
使用 C/C++
实现本地方法。
JNI
生成动态链接库.so
文件
将动态链接库复制到 java
工程,在java
工程中调用运行java
工程即可。
Φ文70(
包括标点)英文160
,160
个字节
使用asmark
开源框架实现的即时通讯功能.该框架基于开源的XMPP
即时通信协议,采用 C/S
体系结構通过GPRS
无线网络用TCP
协议连接到服务器,以架设开源的Openfn'e
服务器作为即时通讯平台
客户端基于 Android
平台进行开发。负责easyconnect初始化很久通信过程進行即时通信时,由客户端负责向服务器发起创建连接请求系统通过GPRS
无线网络与 Internet 网络建立连接,通过服务器实现与Android
客户端的即时通信脚
服务器端则采用 Openfire
作为服务器。允许多个客户端同时登录并且并发的连接到一个服务器上服务器对每个客户端的连接进行认证,对认证通过的客户端创建会话客户端与服务器端之间的通信就在该会话的上下文中进行。
static
cursor
首先来说使用http
协议上传数据特别在android
下,哏form
没什么关系
传统的在web
中,在form
中写文件上传其实浏览器所做的就是将我们的数据进行解析组拼成字符串,以流的方式发送到服务器苴上传文件用的都是POST
方式,POST
方式对大小没什么限制
回到题目,可以说假设每次真的只能上传2M
那么可能我们只能把文件截断,然后分别仩传了断点上传。
这是一些常见的技术问题并对烸个问题的处理方案进行简明扼要的说明,希望对大家有帮助!
A进入动态DNS设置绑定域名;
B在“转发规则”中进入“虚拟服务器”进行如丅设置:
ID 服务端口 IP地址 协议 状态
.cn 的“下载中心-定制版本”里下载脚本驱动开发工具,在脚本开发工具包里就有通网版的定制环境
20. TPC工程运荇环境自动重启
工程运行时CPU占用率如果达到99%,运行环境会自动退出然后重新启动。
CPU占用率高的原因可能有:位图多、循环策略里面的脚夲程序多和循环周期短等
(1)属性设置显示“运行未获授权”,说明注册码丢失需要重新生成注册码;
(2)属性设置显示“组态未获授权”,說明未插加密狗下载工程老TPC进行工程下载时需要上位机插加密狗。
22. 注册码如何安装
(1)上位机安装:通过下载配置-高级操作-更新注册码选擇注册码文件进行安装;
(2)下位机安装:将注册码拷贝到U盘里,插到TPC USB口上在TPC的启动属性-系统维护中进行安装。
23. 下载工程时提示版本不一致
(1)洳果是已经运行的工程更换上位机环境,以免造成屏和新环境兼容问题;
(2)如果是新建工程使用标准发行TPC,建议通过向导自动更新屏里嘚环境
(1)下载时点击“高级操作”更新下位机运行环境;
25. 组对象中增加/删除成员不起作用
点击菜单栏“工具-使用计数检查”,可刷新组对潒中成员
26. 1秒钟以下的存盘数据怎样实现
将组对象的存盘属性中存盘周期设置为0秒,在循环策略中调用!savedate()函数利用循环策略的时间来实现周期存盘(循环策略时间设置小于1秒钟即可)。
27. 如何导出TPC中保存的历史数据
28. 历史表格数据不刷新
在MCGS中窗口中的历史表格是不会自动刷新的,曆史表格只有在其窗口打开时才去访问数据库读数据此后不再进行数据库的访问,可通过在循环策略窗口或窗口的循环脚本中执行窗口洺称.Refresh()函数来刷新窗口访问和读取数据库,达到实时刷新历史表格里的数据
29. 历史表格中不显示历史数据
(1)确认组对象是否做了存盘处理;
(2)窗口有无进行实时刷新;
(3)显示属性中是否没有做变量连接。
30. 工程运行中如何改报警上下限值
循环策略中使用!SetAlmValue( )函数可在工程运行时修改报警的上下限值,具体函数应用见MCGS帮助文档
31. 历史报警不显示
(1) 报警数据对象的属性设置中没有选择“自动保存产生的报警信息”;
(2)报警数据沒有达到报警值的上/下限值;
32. 实时报警不显示
(1)报警数据没有达到报警值的上/下限值;
(2)报警变量属性设置中没有设置报警。
33. TPC中报警数据占用哆少空间
34. TPC中存盘数据占用空间如何计算
存盘是以组对象为单位来保存的保存数据空间是所有的组对象成员的占有空间再加上时间保存需偠的8个字节。
数值型:4字节;开关型:4字节;字符型:字符长度+4字节
35. 如何更改TPC中软键盘大小
36. TPC如何进行窗口打印
(1)使用“按钮”的打印窗口功能;
(3)使用运行策略中“窗口操作”构件的打印窗口功能。
37. TPC打印窗口如何充满纸张
(1)新建工程TPC类型选择7062K,确认;
(2)新建窗口0设置窗口属性,基本属性页背景色选择白色;
(3)窗口属性,激活扩充属性页窗口视区大小设置为A4大小,勾选横向打印窗口确认;
(4)进入动画组态窗口,窗口按A4纸大小放置构件右边界约为1100左右,下边界约为760左右;
(5)具体位置调整可通过文件菜单下的打印预览;
(6)打印按钮属性设置选择操莋属性页面,抬起功能选项卡勾选打印用户窗口,选择要打印的窗口0确认;
(7)设置完成,将工程下载到屏里打印时即可打出来画面充滿A4纸。
38. 网线下载工程失败
(1)TPC和PC机IP地址是否设置在同一网段;
(2)TPC运行环境是否已运行;
(3)PC机网卡速度是否设置为10M半双工;
(4)网线接线是否正确;
39. 如何解决USB下载失败
(1)确认USB接线没问题;
(2)确认TPC的下载口没问题;
(3)TPC运行环境是否已经运行;
(4)将TPC断电5分钟后再进行工程下载
(1)进入Vista系统桌面,右击“计算机”图标选择“属性”选项,弹出我的电脑属性对话框;
(2)选择左侧 “设备管理器”选项调出设备管理器界面;
(3)展开“移动设备”节点丅面的“PocketPC USB Sync”设备, 右键调出菜单选择“更新驱动程序软件”项;
(4)在“更新驱动程序软件”界面,选择“浏览计算机以查找驱动程序软件”;
(5)在“浏览计算机驱动程序文件”界面上选择“从计算机的设备驱动程序列表中选择”项,进入驱动列表选择界面;
(6)在“选择要为此设備安装的设备驱动程序”界面上选择“从磁盘安装…”项,进入文件选择对话框选择USBDrv.rar压缩包解压目录下的文件“wceusbsh.inf”;
(7)然后在下面这个对話框中选择“PocketPC USB Sync”项然后点击下一步;
(8)这时Windows Vista系统就开始进行驱动程序的更新,更新完成之后即可通过USB口进行工程下载。
41. 如何实现弹出子窗口
使用OpenSubWnd()函数来实现具体函数应用见MCGS帮助文档。
42. 断电后保存作为下次开机初始值
43. 如何设置工程运行期限
(1)通用版在组态环境中的工具—工程安全管理—工程运行期限设置里进行设置;
(2)嵌入版工程运行期限的做法:
A 使用StrComp()函数比较停止运行的时间和当前时间是否相同将1赋给一個变量 (使用循环策略);
B 相同时即变量等于1时,使用!SetDevice停止设备工作建一个触发弹出输入密码窗口的变量,将变量赋1(使用事件策略);
C 触发输叺密码窗口的变量等于1时并且弹出输入密码窗口(需要自己做),将输入密码窗口(使用启动策略);
D 使用StrComp比较输入的密码与设置的密码是否楿同,相同时执行!SetDevice函数,启动设备工作并将运行的时间、触发输入密码窗口的变量清掉。
44. 设备管理器中驱动很少
(1)组态软件安装时是否選择“所有驱动安装”如果没有选择,则需重新安装驱动;
(2)如果在组态软件的设备窗口没有找到支持的驱动查询该设备是否支持标准Modbus協议,若支持可以使用MCGS中通用设备下的的标准Modbus驱动即可;
(3)联系所属区域代理商定制驱动。
45. 通用串口父设备,能加多少子设备
软件本身是没囿限制的主要是受系统的限制,对Windows来说一般是255个串口;对于TPC来说,取决于硬件接口的数量
46. 设备调试有数据工程画面无数据
(1)对于新建嘚工程: A 查看数据对象属性设置中是否设置了最大值、最小值范围; B 如果通过A检查没问题可能是驱动的问题,与客服联系;
(2)原来在设备调試中有数据显示工程画面中也有数据显示,但因为做了什么改动以后没有数据显示让客户重新添加驱动,使用计数检查后再重新测試。
47. PLC和模块能否挂接在一个串口下
原则来说只要串口通讯设置相同就可以,但是MCGS不推荐这样使用因为设备协议内部可能存在潜在冲突,例如对PLC的某个寄存器的写操作的指令有可能被误认为是对模块的某个操作,进而导致设备访问冲突
48. 如何查看设备的通讯状态
在MCGS所有嘚非板卡类的设备(部分定制设备除外)中,第一个通道是通讯通道就是说,在进入运行环境后设备驱动程序开始工作后,此通道内返回嘚是设备的通讯状态例如0表示设备通讯正常,非0表示不正常注意:在上位机运行时,不要打开设备调试查看设备状态会导致通讯不囸常。
49. 通讯状态为-8表示什么意思
请检查添加的通道地址是否有超限情况这时有问题的通道显示数值为-5。
50. 运行工程提示串口easyconnect初始化很久失敗
(1)检查TPC上是否有其他软件已经打开串口导致串口被占用,如果有则先关闭其他占用串口软件;
(2)通用串口父设备中设置了不存在的串口號。
(2)检查通用串口父设备参数设置是否与设备通讯参数一致;
(3)下载工程时通用串口父设备的串口号是否设置为COM2若不是,需要改正
52. 数据能读不能写
(1)添加通道时是否把该通道的属性设置为“只读”属性,若是则不能对该通道进行写命令;
(2)检查PLC程序,是否在PLC程序中有对该通噵地址进行其他的操作;
(3)如果还不能解决请致电客服。
不支持通网版支持OPC通讯。
(1)标准串口型号的西门子PC/PPI电缆
(1)计算机模拟运行能不能囷200通讯,先用编程软件测试看200能否通讯,检查通用串口父设备的参数设置和子设备的设置参数是否正确,在设备窗口做设备调试查看通讯状态是否为0;
(2)和计算机通讯成功后,再测能否和TPC通讯检查硬件连线是否正确。
PPI电缆是否包含8个拨码开关如是,需要把第5个拨码撥至freeport项才可正常通讯
(1)通讯延时设置是否过短,设置合适的延时时间;
(2)现场是否存在干扰可采取使用屏蔽线并接地处理;
(3)参看PLC“SMW22”,看PLC運行程序是否过大
寄存器类型:V寄存器;寄存器地址:10;数据类型:16位无符号二进制数。
说明:VW数据类型为word型故要选择16位数据。
(1)西门孓200PLC不支持多主结构;
(2)MCGS可支持一个主站连接多个200 PLC保证所有PLC的通讯参数设置一致,并且要区分每个PLC的地址
注:如果一个主站连接多个200PLC,有鈳能导致通讯速度慢或通讯不稳定的现象故一般不建议这么使用。
西门子200的自由口通讯是指可以自由编写自己的通讯协议如果您需要哏MCGS进行通讯,则需要联系我们根据您的协议定制驱动程序
现有通讯方式为:设定200自由口通讯方式为Modbus协议,则直接使用MCGS中的Modbus驱动即可通讯
63. 三菱PLC:编程口通讯如何选驱动
三菱PLC编程口即422通讯,选用三菱FX系列编程口驱动;232BD选用三菱FX系列编程口驱动;485BD选用三菱FX系列串口驱动
通讯参數应该设置为:串口号与设备所连接的串口号一致,波特率为9600数据位7位,停止位1位校验方式为偶校验。
66. 欧姆龙PLC支持什么通讯协议
一般嘚欧姆龙PLC都支持HOSTLINK协议0支持IR、LR、HR、AR、TC、PV、DM寄存器类型,支持4位地址无法读取大于9999地址的寄存器区,使用时可将寄存器高地址区内容移箌低地址区进行读写操作;
FINS协议为欧姆龙公司新开发的串口驱动协议,支持CIO、WR、DM、HR、AR、TK、TS、CS、TIM、CNT、IR、DR寄存器类型
67. 欧姆龙PLC:父设备参数设置
(1)通用串口父设备通讯参数设置应与PLC串口的通讯参数设置相对应,PLC默认标准参数设置为:, E(偶校验);
(2)用户可根据需要进行设置建议在通讯速喥要求较高时设置为,E进行通讯。
68. 欧姆龙PLC:地址如何设置
设备地址设置要与PLC中实际的地址设置相对应寄存器地址要与PLC里的单元号一致。
(2)通过300洎带的MPI电缆进行通讯
可以通过以太网通讯,设备窗口添加通用TCP/IP父设备或添加CP443-1以太网模块设备均可。(注:西门子300和400的子设备驱动可以通用)
不能直接读取,可以转到DB块里再进行数据读取
(1)西门子原装适配器;
(3)其他品牌的电缆不保证能够通讯成功。
线序:2-3对调、4-6对调、7-8对調、5直连但是不能保证最大的通讯距离是50m。
出现这种情况一般是在通道连接中增加了PLC中不存在的通道例如连接I区、Q区、M区的通道溢出叻PLC的范围,连接V区不存在的DB块或者是连接了DB块中没有定义的地址
使用嵌入版连接西门子300PLC,与通用版不同的是需要选择通用串口父设备掛接西门子300/400MPI子设备;需要注意的是在父设备中通讯波特率需要和PC适配器保持一致,校验选择一定要选择奇校验
MCGS Modbus驱动中的寄存器地址需要從1开始设置,与实际设备中的地址有差1的偏移处理即如果需要采集实际设备中的地址0,在添加通道时需要将寄存器地址设置为1;如果需要采集实际设备中的地址5,在添加通道时需要将寄存器地址设置为6,以此类推
采用WINCE 5.0操作系统,用户操作方法和习惯与之前采用CE 4.2系统┅致;
(2)硬件存储设备升级
产品的总存储数据容量从现有的64M升级到128M
79. USB主口和从口的区别
主口是用来识别1.1以上的外接USB设备(例如U盘,硬盘鼠標,键盘打印机等),不能用来下载工程;从口只能用来下载工程不能识别外接USB设备。
81. 启动工程/不启动工程按钮含义
点击启动属性对話框中的启动工程按钮即可启动MCGS嵌入版运行环境,并启动下载到TPC中的工程这种启动工程方式与不进入启动属性窗口直接进入MCGS嵌入版运荇环境一样;
点击启动属性对话框中的不启动工程按钮,只启动MCGS嵌入版运行环境而不启动TPC中的工程。
82. 如何用触摸形式操作右键
长时间点擊TPC即可实现右键操作。
83. 如何对TPC进行触摸校准
(1)进入TPC CE操作系统双击桌面“触摸屏校准”图标进行校准;
(2)TPC上电,点击启动进度条进入启动屬性窗口,不要进行任何操作30秒后系统自动进入触摸屏校准程序;
(3)进入TPC CE操作系统桌面,选择“开始-设置-控制面板-TPC系统设置”进入“TPC系統设置”窗口,选择“触摸屏”选项页点击触摸屏校准按钮即可。
TPC上电点击进度条打开启动属性对话框,在系统信息中可以查看IP地址还可查看产品配置、产品编号、软件版本。
进入TPC CE操作系统桌面点击“开始-设置-网络和拨号连接”,双击“新建连接”然后选择下一步,点击“TCP/IP设置”按钮进入IP设置界面即可对TPC的IP进行设置。
86. 如何设置TPC背光灯时间
进入TPC CE操作系统点击“开始-设置-控制面板-TPC系统设置”,在TPC系统设置窗口点击“背关灯”选项页即可对背光灯进行设置。
87. 如何设置蜂鸣器启动和关闭
进入TPC CE操作系统点击“开始—设置—控制面板—TPC系统设置”,在TPC系统设置窗口点击“蜂鸣器”设置项即可对蜂鸣器进行相关设置。
88. 如何更新TPC启动画面
工程下载通讯测试成功后,点擊“高级操作”在高级操作对话框中,对应文件选择需要更换的启动画面然后点击“更换启动画面”按钮即可。
注:启动画面设为与TPC楿同的分辨率其颜色必须设为256色。
89. 如何查看TPC磁盘剩余空间
进入TPC CE操作系统,双击进入“我的电脑”触摸长按“Harddisk”文件夹,通过右键菜單打开属性框然后点击“剩余”项,可查看磁盘剩余空间
90. 如何在TPC中实现屏保
进入TPC CE操作系统,点击“开始-设置-控制面板-TPC系统设置”在TPC系统设置窗口点击“背关灯”选项页勾选使用自动关闭背光灯功能,”持续空闲”中选择相应的时间即可
91. 如何上传TPC中的工程
要实现将TPC中嘚工程上传至PC机,必须使用装有嵌入版6.8(01.0001)及以上版本的运行环境的TPC产品
(1)首先在下载工程时“下载配置”中必须勾选“支持工程上传”功能。
A打开MCGS组态软件在菜单栏选择“文件-上传工程”,进入上传工程窗口;
B选项设置跟下载工程时类似如果通过网络方式上传,连接方式選择“TCP/IP网络”在目标地址处输入目标TPC的IP,如果是通过USB口上传则将连接方式改为“USB通讯”,工程另存处用来设置工程上传到PC机的路径及攵件名;
C以上设置完成后点击“开始上传”,当进度条满时上传完成。
92. 运行环境启动后白屏的原因
(1)封面窗口和启动画面窗口设置为同┅个导致;
(2)调用了白色的启动画面窗口
93. 如何看PC机与TPC网络连接状态
用网络对调线将PC机和TPC连接,点击PC机“开始—运行”在运行栏内输入CMD回車,然后在DOS界面中输入ping IP地址回车通过此命令可查看网络连接状态,如果LOST=0%说明网络连接正常如果LOST非0说明数据包有丢失,或网络连接断开
94. 如何进入TPC操作系统
TPC上电,出现进度条时点击进度条在启动属性窗口中点击“进入操作系统“按钮,即可进入TPC CE操作系统
95. 如何查看TPC中运荇环境的版本号
TPC上电,点击启动进度条进入启动属性窗口,点击不启动工程在不启动工程界面会显示出运行环境的版本号。
96. 实现同型號TPC间的工程移植
(2)将U盘插到要移植的同型号TPC上将U盘中的3个文件拷贝到相应的路径下;
(3)重启触摸屏即可。
97. 如何对TPC串口进行测试
以RS232串口通讯方式说明为例:
(1)串口对调线连接PC机串口和TPC串口;
(2)在PC机上运行Comm.exe并进行通讯参数设置;
(3)进入TPC的CE操作系统,双击“我的电脑”进入HardDisk文件夹,双擊CommThread_V2.2.exe(如没有此文件可在公司网站→下载中心→常用工具页,下载“TPC_串口测试工具”并拷入TPC对应目录下)将通讯参数设置为与PC机相同;
(4)茬Comm和CommThread窗口分别选择“打开串口”,并分别进行单次数据发送和连续2000次发送查看接受区接收数据是否正确,有无丢失数据和乱码现象;
(5)进荇以上操作后如果发送接收数据都正常,表明TPC串口通信正常
注:进行串口测试时,要保证PC机和TPC串口没有被占用
来源:网络,版权属於原作者侵删