netty tcp 参数

netty tcp 参数 TCP_NODELAY 这个选项的作用就是禁用 Nagle’s Algorithm NAGLE算法通过将缓冲区内的小封包自动相连,组成较大的封包,阻止大量小封包的发送阻塞网络,从而提高网络应用效率。但是对于时延敏感的应用场景需要关闭该优化算法; SO_RCVBUF 接收缓冲区 SO_SNDBUF 发送缓冲区 SO_KEEPALIVE 保持连接检测对方主机是否崩溃,避免 (服务器) 永远阻塞于TCP连接的输入。 设置该选项后, 如果2小时内在此 socket 的任一方向都没有数据交换, TCP就自动给对方发一个保持存活探测分节 (keepalive probe)。 SO_REUSEADDR SO_BACKLOG The backlog argument is the requested maximum number of pending connections on the socket. SO_RCVBUF ,SO_SNDBUF 每个TCP socket在内核中都有一个发送缓冲区和一个接收缓冲区,TCP的全双工的工作模式以及TCP的滑动窗口便是依赖于这两个独立的buffer以及此buffer的填充状态。接收缓冲区把数据缓存入内核,应用进程一直没有调用read进行读取的话,此数据会一直缓存在相应socket的接收缓冲区内。再啰嗦一点,不管进程是否读取socket,对端发来的数据都会经由内核接收并且缓存到socket的内核接收缓冲区之中。read所做的工作,就是把内核缓冲区中的数据拷贝到应用层用户的buffer里面,仅此而已。进程调用send发送的数据的时候,最简单情况 (也是一般情况) ,将数据拷贝进入socket的内核发送缓冲区之中,然后send便会在上层返回。换句话说,send返回之时,数据不一定会发送到对端去 (和write写文件有点类似) ,send仅仅是把应用层buffer的数据拷贝进socket的内核发送buffer中。后续我会专门用一篇文章介绍read和send所关联的内核动作。每个UDP socket都有一个接收缓冲区,没有发送缓冲区,从概念上来说就是只要有数据就发,不管对方是否可以正确接收,所以不缓冲,不需要发送缓冲区。 接收缓冲区被TCP和UDP用来缓存网络上来的数据,一直保存到应用进程读走为止。对于TCP,如果应用进程一直没有读取,buffer满了之后,发生的动作是: 通知对端TCP协议中的窗口关闭。这个便是滑动窗口的实现。保证TCP socket 接收缓冲区不会溢出,从而保证了TCP是可靠传输。因为对方不允许发出超过所通告窗口大小的数据。 这就是TCP的流量控制,如果对方无视窗口大小而发出了超过窗口大小的数据,则接收方TCP将丢弃它。 UDP: 当 socket 接收缓冲区满时,新来的数据报无法进入接收缓冲区,此数据报就被丢弃。UDP是没有流量控制的;快的发送者可以很容易地就淹没慢的接收者,导致接收方的UDP丢弃数据报。 以上便是TCP可靠,UDP不可靠的实现。 这两个选项就是来设置TCP连接的两个buffer尺寸的。 /** * 100 Continue * 是这样的一种情况: HTTP客户端程序有一个实体的主体部分要发送给服务器,但希望在发送之前查看下服务器是否会 * 接受这个实体,所以在发送实体之前先发送了一个携带100 * Continue的Expect请求首部的请求。服务器在收到这样的请求后,应该用 100 Continue或一条错误码来进行响应。 */ http://www.cnblogs.com/qq78292959/archive/2013/01/18/2865926.html ...

2015-12-19 · 1 min · 77 words · -

netty http client

netty http client http://www.cnblogs.com/luxiaoxun/p/3959450.html 基于Netty4的HttpServer和HttpClient的简单实现 Netty的主页: http://netty.io/index.html 使用的Netty的版本: netty-4.0.23.Final.tar.bz2 ‐ 15-Aug-2014 (Stable, Recommended) Http 消息格式: Http request: Method path-to-resource HTTPVersion-number Header-name-1: value1 Header-name-2: value2 Optional request body Http response: HTTP/Version-number response-code response-phrase Header-name-1: value1 Header-name-2: value2 Optional response body 实现一个简单的Http请求及响应过程: Client向Server发送http请求。 Server端对http请求进行解析。 Server端向client发送http响应。 Client对http响应进行解析。 Netty中Http request消息格式: Netty中Http response消息格式: 代码实例: Http Server: package com.netty.test; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; ...

2015-12-17 · 2 min · 380 words · -

AKKA

AKKA http://sunxiang0918.cn/2016/01/10/Akka-in-JAVA-1/ Akka是一个由Scala编写的,能兼容Sacala和JAVA的,用于编写高可用和高伸缩性的Actor模型框架.它基于了事件驱动的并发处理模式,性能非常的高,并且有很高的可用性.大大的简化了我们在应用系统中开发并发处理的过程.它在各个领域都有很好的表现. 使用AKKA的好处 就如上面简介中所说的,AKKA把并发操作的各种复杂的东西都统一的做了封装.我们主要关心的是业务逻辑的实现,只需要少量的关心Actor模型的串联即可构建出高可用,高性能,高扩展的应用. Akka for JAVA 由于AKKA是使用Scala编写的,而Scala是一种基于JVM的语言.因此JAVA对AKKA的支持也是很不错的.Akka自身又是采用微内核的方式来实现的,这就意味着能很容易的在自己的项目中应用AKKA,只需要引入几个akka的Lib包即可.而官方直接就提供了Maven库供我们在JAVA中使用AKKA. 这些AKKA的依赖包主要有: akka-actor:最核心的依赖包,里面实现了Actor模型的大部分东西 akka-agent:代理/整合了Scala中的一些STM特性 akka-camel:整合了Apache的Camel akka-cluster:akka集群依赖,封装了集群成员的管理和路由 akka-kernel:akka的一个极简化的应用服务器,可以脱离项目单独运行. akka-osgi:对OSGI容器的支持,有akka的最基本的Bundle akka-remote:akka远程调用 akka-slf4j:Akka的日志事件监听 akka-testkit:Akka的各种测试工具 akka-zeromq:整合ZeroMQ 其中最总要的就是akka-actor,最简单的AKKA使用的话,只需要引入这个包就可以了. Actor 模型 什么是Actor 既然说AKKA是一个Actor模型框架,那么就需要搞清楚什么是Actor模型.Actor模型是由Carl Hewitt于上世纪70年代提出的,目的是为了解决分布式编程中的一系列问题而产生. 在Actor模型中,一切都可以抽象为Actor. 而Actor是封装了状态和行为的对象,他们的唯一通讯方式就是交换消息,交换的消息放在接收方的邮箱(Inbox)里.也就是说Actor之间并不直接通信,而是通过了消息来相互沟通,每一个Actor都把它要做的事情都封装在了它的内部. 每一个Actor是可以有状态也可以是无状态的,理论上来讲,每一个Actor都拥有属于自己的轻量级进程,保护它不会被系统中的其他部分影响.因此,我们在编写Actor时,就不用担心并发的问题. 通过Actor能够简化锁以及线程管理,Actor具有以下的特性: 提供了一种高级的抽象,能够封装状态和操作.简化并发应用的开发. 提供了异步的非阻塞的/高性能的事件驱动模型 超级轻量级的线程事件处理能力. 要在JAVA中实现一个Actor也非常的简单,直接继承akka.actor.UntypedActor类,然后实现public void onReceive(Object message) throws Exception方法即可. https://guobinhit.github.io/akka-guide/ https://www.zhihu.com/question/279512440/answer/407373037

2015-12-15 · 1 min · 41 words · -

MySQL Innodb 锁

MySQL Innodb 锁 InnoDB 发音为"in-no-db" 行锁 行锁的分类 行锁从mode上分为X、S,type上进一步细分为以下类型: LOCK_GAP: GAP 锁, 锁两个记录之间的GAP, 防止记录插入; LOCK_ORDINARY: 官方文档中称为 “Next-Key Lock” ,锁一条记录及其之前的间隙,这是RR级别用的最多的锁,从名字也能看出来; LOCK_REC_NOT_GAP: 只锁记录; LOCK_INSERT_INTENSION: 插入意向GAP锁,插入记录时使用,是LOCK_GAP的一种特例。 RC级别只有记录锁,没有 Next-Key Lock 和 GAP锁,因此存在幻读现象。 行锁是加在记录上的锁,InnoDB中的记录是以B+树索引的方式组织在一起的,InnoDB的行锁实际是 index record lock,即对B+索引叶子节点的锁。索引可能有多个,因此操作一行数据时,有可能会加多个行锁在不同的B+树上。 在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足。 在数据库的锁机制中介绍过,在DBMS中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎)、表级锁(MYISAM引擎)和页级锁(BDB引擎 )。 行级锁 行级锁 是 MySQL 中锁定粒度最细的一种锁, 表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小, 但加锁的开销也最大。行级锁分为共享锁和排他锁 行级锁特点 开销大, 加锁慢;会出现死锁;锁定粒度最小, 发生锁冲突的概率最低, 并发度也最高。 表级锁 表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。表级锁定分为**表共享读锁 (共享锁)与表独占写锁 (排他锁)**。 表级锁特点 开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。 页级锁 页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。BDB支持页级锁 页级锁特点 开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般 MySQL常用存储引擎的锁机制 MyISAM和MEMORY采用表级锁(table-level locking) BDB采用页面锁(page-level locking)或表级锁,默认为页面锁 InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁 Innodb中的行锁与表锁 前面提到过,在Innodb引擎中既支持行锁也支持表锁,那么什么时候会锁住整张表,什么时候或只锁住一行呢? InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着: 只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁! 在实际应用中,要特别注意InnoDB行锁的这一特性,不然的话,可能导致大量的锁冲突,从而影响并发性能。 在不通过索引条件查询的时候,InnoDB 确实使用的是表锁,而不是行锁。 由于 MySQL 的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行 的记录,但是如果是使用相同的索引键,是会出现锁冲突的。应用设计的时候要注意这一点。 当表有多个索引的时候,不同的事务可以使用不同的索引锁定不同的行,另外,不论 是使用主键索引、唯一索引或普通索引,InnoDB 都会使用行锁来对数据加锁。 即便在条件中使用了索引字段,但是否使用索引来检索数据是由 MySQL 通过判断不同 执行计划的代价来决定的,如果 MySQL 认为全表扫 效率更高,比如对一些很小的表,它 就不会使用索引,这种情况下 InnoDB 将使用表锁,而不是行锁。因此,在分析锁冲突时, 别忘了检查 SQL 的执行计划,以确认是否真正使用了索引。 行级锁与死锁 MyISAM中是不会产生死锁的,因为MyISAM总是一次性获得所需的全部锁,要么全部满足,要么全部等待。而在InnoDB中,锁是逐步获得的,就造成了死锁的可能。 ...

2015-12-15 · 3 min · 637 words · -

jcl-over-slf4j

http://www.cnblogs.com/zcy_soft/p/3566208.html jcl-over-slf4j log桥接工具简介 java 界里有许多实现日志功能的工具,最早得到广泛使用的是 log4j,许多应用程序的日志部分都交给了 log4j,不过作为组件开发者,他们希望自己的组件不要紧紧依赖某一个工具,毕竟在同一个时候还有很多其他很多日志工具,假如一个应用程序用到了两个组件,恰好两个组件使用不同的日志工具,那么应用程序就会有两份日志输出了。 为了解决这个问题,Apache Commons Logging (之前叫 Jakarta Commons Logging,JCL) 粉墨登场,JCL 只提供 log 接口,具体的实现则在运行时动态寻找。这样一来组件开发者只需要针对 JCL 接口开发,而调用组件的应用程序则可以在运行时搭配自己喜好的日志实践工具。 所以即使到现在你仍会看到很多程序应用 JCL + log4j 这种搭配,不过当程序规模越来越庞大时,JCL的动态绑定并不是总能成功,具体原因大家可以 Google 一下,这里就不再赘述了。解决方法之一就是在程序部署时静态绑定指定的日志工具,这就是 SLF4J 产生的原因。 跟 JCL 一样,SLF4J 也是只提供 log 接口,具体的实现是在打包应用程序时所放入的绑定器 (名字为 slf4j-XXX-version.jar) 来决定,XXX 可以是 log4j12, jdk14, jcl, nop 等,他们实现了跟具体日志工具 (比如 log4j) 的绑定及代理工作。举个例子: 如果一个程序希望用 log4j 日志工具,那么程序只需针对 slf4j-api 接口编程,然后在打包时再放入 slf4j-log4j12-version.jar 和 log4j.jar 就可以了。 现在还有一个问题,假如你正在开发应用程序所调用的组件当中已经使用了 JCL 的,还有一些组建可能直接调用了 java.util.logging,这时你需要一个桥接器 (名字为 XXX-over-slf4j.jar) 把他们的日志输出重定向到 SLF4J,所谓的桥接器就是一个假的日志实现工具,比如当你把 jcl-over-slf4j.jar 放到 CLASS_PATH 时,即使某个组件原本是通过 JCL 输出日志的,现在却会被 jcl-over-slf4j “骗到"SLF4J 里,然后 SLF4J 又会根据绑定器把日志交给具体的日志实现工具。过程如下 ...

2015-12-09 · 1 min · 129 words · -

脑裂问题

脑裂问题 http://my.oschina.net/moooofly/blog/92288?fromerr=sduNT5ao 在心跳失效的时候,就发生了脑裂 (split-brain) 。 ( 一种常见的脑裂情况可以描述如下) 比如正常情况下, (集群中的) NodeA 和 NodeB 会通过心跳检测以确认对方存在,在通过心跳检测确认不到对方存在时,就接管对应的 (共享) resource 。如果突然间,NodeA 和 NodeB 之间的心跳不存在了 (如网络断开) ,而 NodeA 和 NodeB 事实上却都处于 Active 状态,此时 NodeA 要接管 NodeB 的 resource ,同时 NodeB 要接管 NodeA 的 resource ,这时就是脑裂 (split-brain) 。 脑裂 (split-brain) 会 引起数据的不完整性 ,并且可能会 对服务造成严重影响 。 引起数据的不完整性主要是指,集群中节点 (在脑裂期间) 同时访问同一共享资源,而此时并没有锁机制来控制针对该数据访问 (都脑裂了,咋控制哩) ,那么就存在数据的不完整性的可能。 对服务造成严重影响,举例来说,可能你早上上班的时候会发现 NodeA 和 NodeB 同时接管了一个虚拟 IP 。 所以,裂脑这个词是一个很形象的术语,用于描述 HA 系统危机的情景。 曾经看央视 10 套教育频道,获知"裂脑"是治疗"癫痫"病的一种手术。医生们认为癫痫病发作是由于大脑"异常放电"所至。为了阻止"异常放电"波及整个大脑 (左、右半脑) ,就用手术来割断病人左右脑的连接神经。使今后病人在发病时至少还有半个大脑正常、能控制行为。但施行过手术的所谓"裂脑人"在术后有一段不适应期,表现得行为分裂,仿佛体内存在着2个人,时常要发生冲突。例如,右脑想让一只手去脸上挠痒痒,左脑却不认同、以为是谁的手要"登鼻子上脸"就让另一只手去阻止,于是明明是自己的 2 只手,却互不相让、扭在一起扳起了手腕…… 在"双机热备"高可用 (HA) 系统中,当联系 2 个节点的"心跳线"断开时,本来构成同一个整体、动作协调的 HA 系统,就分裂成为 2 个独立的个体。由于相互失去了联系,都以为是对方出了故障,2 个节点上的 HA 软件像"裂脑人"一样,“本能"地争抢"共享资源”、争着起动"应用服务",那么必然会发生严重的后果: 或者共享资源被瓜分、两边的"服务"都起不来了;或者两边"服务"都起来了,但同时读写"共享存储",导致数据损坏 (常见如数据库轮询着的联机日志出错) 。 ...

2015-12-09 · 2 min · 261 words · -

archlinux kvm qemu gentoo

archlinux kvm qemu gentoo pacman -Syu pacman -S qemu pacman -S qemu-launcher qemu-img create -f raw gentoo.img 20G qemu-img create -f qcow2 gentoo 20G exec qemu-system-x86_64 -enable-kvm -cpu host -cdrom install-amd64-minimal-20150924.iso -boot order=d -drive file=gentooVM.img,if=virtio -netdev user,id=vmnic,hostname=gentoovm -device virtio-net,netdev=vmnic -m 2048M -monitor stdio -name "Gentoo VM" pacman -S linux-atm pacman -S bridge-utils 在主机上创建桥 创建桥的原因是虚拟机间,虚拟机与主机间的互联 $ sudo brctl addbr br0 ip tuntap # start gentoo with sshd gentoo dosshd # or /etc/init.d/sshd start #prepare partition #mounting mount /dev/sda4 /mnt/gentoo mkdir /mnt/gentoo/boot mount /dev/sda2 /mnt/gentoo/boot chmod 1777 /mnt/gentoo/tmp #Downloading the stage tarball https://bbs.archlinux.org/viewtopic.php?id=164461 ...

2015-12-07 · 1 min · 93 words · -

float double NaN

float double NaN http://zranye.iteye.com/blog/1344880 http://blog.csdn.net/naruto_ahu/article/details/8805808 (注意,double中的NaN类似) 在帮助文档中,NaN是这样解释的 (double的,和float差不多) : <!- Generated by javadoc (build 1.6.0-beta2) on Mon Mar 19 18:22:44 CST 2007 -> public static final double NaN 保存 double 类型的 NaN 值的常量。它等于 Double.longBitsToDouble(0x7ff8000000000000L) 返回的值。 我是这样解释的 (理解不深,有错请不吝赐教) : NaN-Not-a-Number,其实是指一个不合理的实数,在合法却不合理的情况下避免你的程序出现Exception。 NaN什么也不是,如果理解成一个超越了float范围的常量 (或者double) ,那也是不对的,为什么?试试判断 (NaN==NaN) 吧,你会发现这返回了一个false。这在java底层是怎么做到的呢?最直接的方式是看java源代码咯。 /** A constant holding a Not-a-Number (NaN) value of type float. It is equivalent to the value returned by Float.intBitsToFloat(0x7fc00000). ...

2015-12-04 · 1 min · 79 words · -

connection=keep alive 和close

connection=keep alive 和close 浏览器和服务器在建立 http 连接的时候需要3次握手, 在高并发的环境下每一次建立连接都3次握手会消耗太多的服务资源, 这个本质上是由于http是无状态造成的.http1.0默认开启了 connection=close 模式意味着服务器和客户端都需要关闭TCP连接, 而客户端是通过判断连接关闭来判断响应是否都收到了。http1.1 默认开启connection=keep-alive模式 (长连接) ,主要为了解决浏览器内高并发的访问服务器资源,而且每次的访问都可以复用连接,从而提高响应速度。但是也需要注意,因为浏览器无法判断当前发送的二进制码流是否结束, 也就是所谓的粘包问题, 所以在 keep-alive 模式下, 服务器需要显示的返回Content-Length 用来根据码流的长度来判断一个完整的 response 是否结束。

2015-12-02 · 1 min · 22 words · -

redis set

redis set # 删除集合 del set_name_0 redis set 是string类型对象的无序集合,set不管存储多少对象,对存储对象的add,remove和test操作的时间复杂度是O(1)。set最多能包含 232 – 1 个member。 增加, sadd 语法: sadd key member[member…] 解释: 对特定key的set增加一个或多个值,返回是增加元素的个数。注意: 对同一个member多次add,set中只会保留一份。 查询 smembers, sismember, scard, srandmember smembers 语法: smembers key 解释: 获取set中的所有member sismember 语法: sismember key member 解释: 判断值是否是set的member。如果值是set的member返回1,否则,返回0 scard 语法: scard key 解释: 返回set的member个数,如果set不存在,返回0 srandmember 语法: srandmember key 解释: 从set中返回一个随机member 删除 spop 语法: spop key 解释: 移除并返回一个随机member srem 语法: srem key member [member …] 解释: 移除一个或多个member smove 语法: smove source destination member ...

2015-12-01 · 1 min · 156 words · -

redis windows

redis windows 启动redis 服务 redis-server.exe redis-server.exe redis.windows.conf https://github.com/MSOpenTech/redis/releases 修改配置文件 redis.windows.conf ,搜索 maxheap , 然后直接指定好内容即可. maxheap <bytes> maxheap 1024000000

2015-12-01 · 1 min · 18 words · -

CAS, Compare and Swap, 比较并交换

CAS, Compare and Swap, 比较并交换 JDK 5 的并发包中提供了很多类,这些类提供了比原有的并发机制更好的性能和伸缩性。要想理解这些类的工作机理,那就不得不提到 CAS。 CAS 全称是 Compare and Swap (比较并交换),是指现代主流 CPU 都支持的一种指令,这个指令能为多线程编程带来更好的性能 (稍后会详细介绍) 。 另外一个可能会被当做 CAS 的是 Compare and Set,是指 JDK 5 并发包中广泛使用的一种基于 Compare and Swap 的并发算法。严格说 CAS 仅指代前者。 java.util.concurrent 包完全建立在CAS之上的,没有CAS就不会有此包。可见CAS的重要性。 java.util.concurrent 包中借助CAS实现了区别于 synchronouse 同步锁的一种乐观锁。 CAS应用 CAS: 全称Compare and swap,字面意思:”比较并交换“,一个 CAS 涉及到以下操作: 我们假设内存中的原数据V,旧的预期值A,需要修改的新值B。 比较 A 与 V 是否相等。 (比较) 如果比较相等,将 B 写入 V。 (交换) 返回操作是否成功。 CAS 有3个操作数,内存值 V, 旧的预期值 A, 要修改的新值 B. 当且仅当预期值 A 和内存值 V 相同时,将内存值 V 修改为 B, 否则什么都不做。 ...

2015-12-01 · 3 min · 454 words · -

ODX(Open Diagnostic Data Exchange)

ODX(Open Diagnostic Data Exchange) http://auto.vogel.com.cn/news_view.html?id=358026 随着汽车电子技术的不断发展,电子控制单元 (ECU) 在现代汽车中得到了广泛的应用。电子控制单元在提高汽车动力性、经济性、舒适性和安全性的同时,也使得车辆中的电子电气系统越来越复杂,这也促使汽车诊断技术有了更大的发展。在整车生命周期中,为了便于交换诊断数据,提高研发、测试、生产及售后的效率,降低诊断数据管理成本,一种开源的标准化诊断数据格式——ODX得到了越来越多的应用。本文介绍了ODX的基本体系结构,其与车辆通信模型接口 (MVCI) 的关系,并分析了现在ODX的主要应用及未来发展方向。 一、 ODX概述 ODX(Open Diagnostic Data Exchange)是一种开放式的诊断数据格式,用于车辆全生命周期中诊断数据的交互。ODX最初由ASAM (自动化及测量系统标准协会)提出并形成标准MCD-2D,在2008年以ODX 2.2.0为基础形成了ISO标准——ISO 22901-1。 在ODX提出之前,由于应用场景、开发工具的不同,诊断开发不同阶段使用的数据格式均不相同。例如,在研发阶段,诊断需求通常采用.doc或.rtf格式描述;在测试验证阶段,以业界常用的Vector CANoe.DiVa工具为例,诊断需求采用.cdd的格式描述;同样,生产、ECU代码实现及售后阶段,诊断需求的描述格式也不相同。然而,诊断开发流程中的各个阶段又相互依存,密不可分。如果诊断需求描述格式不断转换,将难以保证数据的一致性,既增大了需求管理的复杂度,又使各阶段工作衔接困难,增加综合成本。如果在整个诊断开发流程中均使用ODX作为诊断数据格式,由于其开源及标准化属性,上述问题都得以解决。使用ODX作为诊断数据格式的整个数据交互过程如图1所示: 图1 ODX数据交互过程 目前最新版本的ODX为2.2.0,整个ODX数据模型分为七层: ODX-D、ODX-C、ODX-V、ODX-E、ODX-FD、ODX-F、ODX-M,如图2所示: 图2 ODX数据模型 ODX-D部分主要描述了诊断仪与ECU之间的通信过程,包括诊断服务的请求、响应格式及所用到的参数类型等。除此之外,ODX-D部分还使用Single-ECU-job (java)的形式描述了一些特殊的诊断应用,例如安全访问算法的实现。ODX-C部分描述了诊断仪与ECU之间的通信参数,例如网络层定时参数、应用层定时参数、波特率等。ODX-V描述了车辆的信息,例如OEM(原始设备制造商)信息、车型信息、车辆拓扑等。ODX-F部分主要对上传下载的数据进行描述,应用于在线刷新程序。ODX-E部分描述了车辆的配置信息,包括根据特定的车辆环境,地点,使能/关闭可选功能,设定特征曲线等,主要应用于ECU生产、售后阶段。ODX-FD部分描述了面向功能的诊断信息。ODX-M部分描述了多个ECU共同实现的某些诊断功能信息。ODX-D与ODX-C是ODX数据模型的基础,是诊断数据的描述必不可少的两个部分。对于OEM来讲,ODX-V也是不可或缺的。 ODX为开发人员、供应商、售后生产人员之间的诊断数据交互提供了便利,简化了彼此之间的工作流程,降低了OEM对诊断数据维护、管理的成本。除此之外,ODX-D中各诊断层的值继承的应用,使诊断数据得以复用。在多个ECU项目中,通过比较或添加来减少数据量,避免不同ECU的数据拷贝时出错。同时,也可以通过值的本地覆盖来更新数据,有很强的灵活性。ODX中权限属性及强制继承属性的应用保证了诊断数据的安全性和完整性。 二、 ODX与MVCI MVCI(Multiple Vehicle Connect Interface)为车辆通信接口模型,描述了车辆外接设备(例如售后诊断仪、下线设备、测试设备)与ECU之间的通信接口,如图3所示。 图3 车辆通信接口模型 其中应用层实现诊断的上层功能,例如售后诊断仪中读取故障功能、下线设备中钥匙匹配功能、测试设备中的测试用例等。接口实时系统负责与ODX进行交互,将应用层的功能转换成诊断请求,或者将收到的诊断响应解析为应用数据传给应用层。VCI是ECU与车辆外接设备之前的硬件接口,实现不同信号载体之间数据的传递。应用层与实时系统之间的接口称为D-Server API,实时系统与VCI之间的接口称为D-PDU API,这两个接口均由ISO标准化定义,分别为ISO 22900-1、ISO 22900-2。 由图3可知,对于OEM来说,如果使用ODX作为诊断数据格式,无论车辆外接设备应用于售后诊断、下线检测还是测试验证,只需要开发一套通用的接口实时系统,并提供标准的接口,即可根据不同的应用需求开发出不同的工具。节约了工具开发的成本,也避免了各个环节中诊断工具的管理成本。另外,这也将便于以后应用的扩展及通信硬件设备的更新。 接下来以读取发动机转速值为例介绍MVCI处理ODX数据的过程。 图4 MVCI处理ODX数据 应用层将读取发动机转速值的应用命令通过D-Server API传递给接口实时系统; 接口实时系统将读取数据这一应用命令通过ODX映射到诊断服务中(例如通过标识符读数据($22)); 接口实时系统将发动机转速这一命令通过ODX映射到诊断服务的参数中(例如 $0101); 接口实时系统将应用指令组成完整的诊断请求 $22 $01 $01; 接口实时系统通过D-PDU API接口将请求传递给VCI,VCI将这一诊断请求转换成通信信号(例如CAN信号)发给ECU; VCI将接收到的通信信号通过D-PDU API传递给接口实时系统,例如$62 $01 $01 $5D $C0; 接口实时系统将响应中数据通过ODX进行解析,例如发动机转速为$5D $C0; 接口实时系统通过ODX中的参数数据类型将响应中的总线值转换成物理值,例如 ($5DC0*0.125=3000) 接口实时系统通过ODX创建响应对象,包括参数物理值、单位等,例如3000 rpm; ...

2015-11-25 · 1 min · 109 words · -

阻塞,非阻塞,同步,异步

阻塞,非阻塞,同步,异步 作者: 萧萧 链接: https://www.zhihu.com/question/19732473/answer/241673170 来源: 知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 IO 概念区分四个相关概念: 同步 (Synchronous) 异步( Asynchronous) 阻塞( Blocking ) 非阻塞( Nonblocking) 这四个概念的含义以及相互之间的区别与联系,并不如很多网络博客所写的那么简单, 通过举一些什么商店购物, 买书买报的例子就能讲清楚。 进程间通信的同步/异步, 阻塞/非阻塞首先强调一点, 网络上很多博文关于同步/异步, 阻塞非阻塞区别的解释其实都经不起推敲。 例如在 严肃 的这一高赞回答中 , 有如下解释 (不准确) : 同步/异步关注的是消息通信机制 (synchronous communication/ asynchronous communication) 。 所谓同步,就是在发出一个调用时,在没有得到结果之前, 该调用就不返回。异步则是相反,调用在发出之后,这个调用就直接返回了, 所以没有返回结果阻塞/非阻塞关注的是程序在等待调用结果 (消息,返回值) 时的状态.阻塞调用是指调用结果返回之前,当前线程会被挂起。 调用线程只有在得到结果之后才会返回。非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。粗一看, 好像同步/ 非同步, 阻塞/非阻塞 是两种维度的概念, 可以分别对待, 但是稍微推敲一下就会发现上述的解释存在不妥之处。如果“同步”是发起了一个调用后, 没有得到结果之前不返回, 那它毫无疑问就是被“阻塞”了 (即调用进程处于 “waiting” 状态) 。如果“异步”调用发出了以后就直接返回了, 毫无疑问, 这个进程没有被“阻塞”。 所以, 上述的解释是不准确的。 让我们看一下《操作系统概念 (第九版) 》中有关进程间通信的部分是如何解释的: 翻译一下就是: 进程间的通信是通过 send() 和 receive() 两种基本操作完成的。具体如何实现这两种基础操作,存在着不同的设计。 消息的传递有可能是阻塞的或非阻塞的 – 也被称为同步或异步的: 阻塞式发送 (blocking send) . 发送方进程会被一直阻塞, 直到消息被接受方进程收到。非阻塞式发送 (nonblocking send) 。 发送方进程调用 send() 后, 立即就可以其他操作。阻塞式接收 (blocking receive) 接收方调用 receive() 后一直阻塞, 直到消息到达可用。非阻塞式接受 (nonblocking receive) 接收方调用 receive() 函数后, 要么得到一个有效的结果, 要么得到一个空值, 即不会被阻塞。上述不同类型的发送方式和不同类型的接收方式,可以自由组合。也就是说, 从进程级通信的维度讨论时, 阻塞和同步 (非阻塞和异步) 就是一对同义词, 且需要针对发送方和接收方作区分对待。———- 下面对理解同步异步,阻塞非阻塞所需的知识点进行详细叙述———————先修知识用户空间和内核空间进程切换 系统调用 (system call) 中断 (interrupt) 进程的阻塞用户空间和内核空间操作系统为了支持多个应用同时运行,需要保证不同进程之间相对独立 (一个进程的崩溃不会影响其他的进程 , 恶意进程不能直接读取和修改其他进程运行时的代码和数据) 。 因此操作系统内核需要拥有高于普通进程的权限, 以此来调度和管理用户的应用程序。于是内存空间被划分为两部分,一部分为内核空间,一部分为用户空间,内核空间存储的代码和数据具有更高级别的权限。内存访问的相关硬件在程序执行期间会进行访问控制 ( Access Control) ,使得用户空间的程序不能直接读写内核空间的内存。有《微机原理》 课程基础同学可以 Google 搜索 DPL, CPL 这两个关键字了解硬件层面的内存访问权限控制细节进程切换上图展示了进程切换中几个最重要的步骤: 当一个程序正在执行的过程中, 中断 (interrupt) 或 系统调用 (system call) 发生可以使得 CPU 的控制权会从当前进程转移到操作系统内核。操作系统内核负责保存进程 i 在 CPU 中的上下文 (程序计数器, 寄存器) 到 PCBi (操作系统分配给进程的一个内存块) 中。从 PCBj 取出进程 j 的CPU 上下文, 将 CPU 控制权转移给进程 j , 开始执行进程 j 的指令。几个底层概念的通俗 (不严谨) 解释: 中断 (interrupt) CPU 微处理器有一个中断信号位, 在每个CPU时钟周期的末尾, CPU会去检测那个中断信号位是否有中断信号到达, 如果有, 则会根据中断优先级决定是否要暂停当前执行的指令, 转而去执行处理中断的指令。 (其实就是 CPU 层级的 while 轮询) 时钟中断( Clock Interrupt )一个硬件时钟会每隔一段 (很短) 的时间就产生一个中断信号发送给 CPU,CPU 在响应这个中断时, 就会去执行操作系统内核的指令, 继而将 CPU 的控制权转移给了操作系统内核, 可以由操作系统内核决定下一个要被执行的指令。系统调用 (system call) system call 是操作系统提供给应用程序的接口。 用户通过调用 systemcall 来完成那些需要操作系统内核进行的操作, 例如硬盘, 网络接口设备的读写等。从上述描述中, 可以看出来, 操作系统在进行进切换时,需要进行一系列的内存读写操作, 这带来了一定的开销: 对于一个运行着 UNIX 系统的现代 PC 来说, 进程切换通常至少需要花费 300 us 的时间进程阻塞上图展示了一个进程的不同状态: New. 进程正在被创建.Running. 进程的指令正在被执行Waiting. 进程正在等待一些事件的发生 (例如 I/O 的完成或者收到某个信号) Ready. 进程在等待被操作系统调度Terminated. 进程执行完毕 (可能是被强行终止的) 我们所说的 “阻塞”是指进程在发起了一个系统调用 (System Call) 后, 由于该系统调用的操作不能立即完成,需要等待一段时间,于是内核将进程挂起为等待 (waiting) 状态, 以确保它不会被调度执行, 占用 CPU 资源。友情提示: 在任意时刻, 一个 CPU 核心上 (processor) 只可能运行一个进程 。I/O System Call 的阻塞/非阻塞, 同步/异步这里再重新审视 阻塞/非阻塞 IO 这个概念, 其实阻塞和非阻塞描述的是进程的一个操作是否会使得进程转变为“等待”的状态, 但是为什么我们总是把它和 IO 连在一起讨论呢?原因是, 阻塞这个词是与系统调用 System Call 紧紧联系在一起的, 因为要让一个进程进入 等待 (waiting) 的状态, 要么是它主动调用 wait() 或 sleep() 等挂起自己的操作, 另一种就是它调用 System Call, 而 System Call 因为涉及到了 I/O 操作, 不能立即完成, 于是内核就会先将该进程置为等待状态, 调度其他进程的运行, 等到 它所请求的 I/O 操作完成了以后, 再将其状态更改回 ready 。操作系统内核在执行 System Call 时, CPU 需要与 IO 设备完成一系列物理通信上的交互, 其实再一次会涉及到阻塞和非阻塞的问题, 例如, 操作系统发起了一个读硬盘的请求后, 其实是向硬盘设备通过总线发出了一个请求,它即可以阻塞式地等待IO 设备的返回结果,也可以非阻塞式的继续其他的操作。 在现代计算机中,这些物理通信操作基本都是异步完成的, 即发出请求后, 等待 I/O 设备的中断信号后, 再来读取相应的设备缓冲区。 但是,大部分操作系统默认为用户级应用程序提供的都是阻塞式的系统调用 (blocking systemcall) 接口, 因为阻塞式的调用,使得应用级代码的编写更容易 (代码的执行顺序和编写顺序是一致的) 。但同样, 现在的大部分操作系统也会提供非阻塞I/O 系统调用接口 (Nonblocking I/O system call) 。 一个非阻塞调用不会挂起调用程序, 而是会立即返回一个值, 表示有多少bytes 的数据被成功读取 (或写入) 。非阻塞I/O 系统调用( nonblocking system call )的另一个替代品是 异步I/O系统调用 (asychronous system call) 。 与非阻塞 I/O 系统调用类似,asychronous system call 也是会立即返回, 不会等待 I/O 操作的完成, 应用程序可以继续执行其他的操作, 等到 I/O 操作完成了以后,操作系统会通知调用进程 (设置一个用户空间特殊的变量值 或者 触发一个 signal 或者 产生一个软中断 或者 调用应用程序的回调函数) 。此处, 非阻塞I/O 系统调用( nonblocking system call ) 和 异步I/O系统调用 (asychronous system call) 的区别是: 一个非阻塞I/O 系统调用 read() 操作立即返回的是任何可以立即拿到的数据, 可以是完整的结果, 也可以是不完整的结果, 还可以是一个空值。而异步I/O系统调用 read () 结果必须是完整的, 但是这个操作完成的通知可以延迟到将来的一个时间点。下图展示了同步I/O 与 异步 I/O 的区别 (非阻塞 IO 在下图中没有绘出) . 注意, 上面提到的 非阻塞I/O 系统调用( nonblocking system call ) 和 异步I/O系统调用 都是非阻塞式的行为 (non-blocking behavior) 。 他们的差异仅仅是返回结果的方式和内容不同。非阻塞 I/O 如何帮助服务器提高吞吐量考虑一个单进程服务器程序, 收到一个 Socket 连接请求后, 读取请求中的文件名,然后读请求的文件名内容,将文件内容返回给客户端。 那么一个请求的处理流程会如下图所示。R 表示读操作W 表示写操作C 表示关闭操作在这个过程中, 我们可以看到, CPU 和 硬盘IO 的资源大部分时间都是闲置的。 此时, 我们会希望在等待 I/O 的过程中继续处理新的请求。方案一: 多进程每到达一个请求, 我们为这个请求新创建一个进程来处理。 这样, 一个进程在等待 IO 时, 其他的进程可以被调度执行, 更加充分地利用 CPU 等资源。问题: 每新创建一个进程都会消耗一定的内存空间, 且进程切换也会有时间消耗, 高并发时, 大量进程来回切换的时间开销会变得明显起来。方案二: 多线程和多进程方案类似,为每一个请求新建一个线程进行处理,这样做的重要区别是, 所有的线程都共享同一个进程空间问题: 需要考虑是否需要为特定的逻辑使用锁。引申问题: 一个进程中的某一个线程发起了 system call 后, 是否造成整个进程的阻塞? 如果会, 那么多线程方案与单进程方案相比就没有明显的改善。解决办法1: 内核支持的线程 (kenerl supported threads) 操作系统内核能够感知到线程, 每一个线程都会有一个内核调用栈 (kenerl stack) 和 保存CPU 寄存器下文的 table 。在这种方案中, 如果 CPU 是多核的, 不同的线程还可以运行在不同的 CPU processor 上。 既实现了IO 并发, 也实现了 CPU 并发。问题: 内核支持线程可移植性差, 其实现对于不同的操作系统而言有所差别。解决办法2: 用户支持的线程 (user supported threads) 内核感知不到用户线程, 每一个用户的进程拥有一个调度器, 该调度器可以感知到线程发起的系统调用, 当一个线程产生系统调用时, 不阻塞整个进程, 切换到其他线程继续运行。 当 I/O 调用完成以后, 能够重新唤醒被阻塞的线程。实现细节: 应用程序基于线程库 thread libray 编写线程库中包含 “虚假的” read(), write(), accept()等系统调用。线程库中的 read(), write(), accept() 的底层实现为非阻塞系统调用 (Non-blocking system call) , 调用后,由于可以立即返回, 则将特定的线程状态标记为 waiting, 调度其他的可执行线程。 内核完成了 IO 操作后, 调用线程库的回调函数, 将原来处于 waiting 状态的线程标记为 runnable.从上面的过程可以看出,用户级支持线程 (User-Supported Threads) 的解决方案基于非阻塞IO系统调用( non-blocking system call) , 且是一种基于操作系统内核事件通知 (event-driven) 的解决方案, 该方案可以降低系统处理并发请求时的进程切换开销。 基于这个方案, 可以引申到更为宽泛的 event-driven progreamming 话题上。 但是这里就不作赘述了。总结: 阻塞/非阻塞, 同步/异步的概念要注意讨论的上下文: 在进程通信层面, 阻塞/非阻塞, 同步/异步基本是同义词, 但是需要注意区分讨论的对象是发送方还是接收方。发送方阻塞/非阻塞 (同步/异步) 和接收方的阻塞/非阻塞 (同步/异步) 是互不影响的。在 IO 系统调用层面 ( IO system call ) 层面, 非阻塞 IO 系统调用 和 异步 IO 系统调用存在着一定的差别, 它们都不会阻塞进程, 但是返回结果的方式和内容有所差别, 但是都属于非阻塞系统调用 ( non-blocing system call ) 2. 非阻塞系统调用 (non-blocking I/O system call 与 asynchronous I/O system call) 的存在可以用来实现线程级别的 I/O 并发, 与通过多进程实现的 I/O 并发相比可以减少内存消耗以及进程切换的开销。编辑于 03-02 ...

2015-11-13 · 3 min · 584 words · -

jstack

jstack jstack主要用来查看某个Java进程内的线程堆栈信息。语法格式如下: jstack [option] PID jstack [option] executable core jstack [option] [server-id@]remote-hostname-or-ip 可以显示所有的线程 H 打印线程信息,p指定pid,这两个参数的作用是显示进行pid下的所有线程的资源占用情况。 top -Hp PID 找到cpu占用最高的线程 10进制转16进制 printf "%x\n" PID #-l long listings,会打印出额外的锁信息,在发生死锁时可以用jstack -l pid来观察锁持有情况 #http://www.wiloon.com/?p=10225 #-m mixed mode,不仅会输出Java堆栈信息,还会输出C/C++堆栈信息 (比如Native方法) #-m prints mixed mode (both Java and native C/C++ frames) stack trace. #-F Force a stack dump when 'jstack [-l] pid' does not respond. jstack可以定位到线程堆栈,根据堆栈信息我们可以定位到具体代码,所以它在JVM性能调优中使用得非常多。下面我们来一个实例找出某个Java进程中最耗费CPU的Java线程并定位堆栈信息,用到的命令有ps、top、printf、jstack、grep。 第一步先找出Java进程ID,我部署在服务器上的Java应用名称为mrf-center: ps -ef | grep mrf-center | grep -v grep ...

2015-11-11 · 4 min · 715 words · -

SVN中Branch/tag

SVN中Branch/tag http://blog.csdn.net/adupt/article/details/4203133 SVN中Branch/tag的比较 分类: SVN2009-05-20 10:23 8700人阅读 评论(0) 收藏 举报 svnbranchmergetortoisesvnurl测试 在SVN中Branch/tag在一个功能选项中,在使用中也往往产生混淆。 在实现上,branch和tag,对于svn都是使用copy实现的,所以他们在默认的权限上和一般的目录没有区别。至于何时用tag,何时用branch,完全由人主观的根据规范和需要来选择,而不是强制的 (比如cvs) 。 一般情况下, tag,是用来做一个milestone的,不管是不是release,都是一个可用的版本。这里,应该是只读的。更多的是一个显示用的,给人一个可读 (readable) 的标记。 branch,是用来做并行开发的,这里的并行是指和trunk进行比较。 比如,3.0开发完成,这个时候要做一个tag,tag_release_3_0,然后基于这个tag做release,比如安装程序等。trunk进入 3.1的开发,但是3.0发现了bug,那么就需要基于tag_release_3_0做一个branch,branch_bugfix_3_0,基于这 个branch进行bugfix,等到bugfix结束,做一个tag,tag_release_3_0_1,然后,根据需要决定 branch_bugfix_3_0是否并入trunk。 对于svn还要注意的一点,就是它是全局版本号,其实这个就是一个tag的标记,所以我们经常可以看到,什么什么release,基于xxx项目的 2xxxx版本。就是这个意思了。但是,它还明确的给出一个tag的概念,就是因为这个更加的可读,毕竟记住tag_release_1_0要比记住一个 很大的版本号容易的多。 svn中建立branch或者tag的方法比较简单,totoiseSVN中的操作是: 1.选择Branch/tag.. 2.在出来的界面中的To URL中填上URL,一般是svn://IP/Project/branches/branch-1, 这样就建立了一个branch-1的branch. 建立tag是一样的操作,只不过URL一般是svn://IP/Project/tags/tag-1 3.后面的Create copy from是用于选择从你当前的working base中的哪个版本中建立branch/tag,可以根据自己的选择来订制,一般选择Head Revision subclipse中几乎是一样的操作。 Merge分为很多种: 1.多个branch之间merge 2.branch merge到trunk 3.trunk merge到branch 第2种用的比较多,比如在otfs接口中netamount的需求提出后就得建立一个netamount的branch,trunk继续在非 netamount的情况下继续开发,netamount单独开发,当netamount功能测试通过后,将netamount branch merge到trunk下,然后将trunk release。 第3种情况用的也不少,如上的例子,当用户进行netamount测试时,如果用户不想只测试netamount的功能,则需要将trunk中的修改merge到netamount branch,然后从netamount branch中发布一个版本供用户测试。 branch merge to trunk在tortoiseSVN操作如下: 1.选择TortoiseSVN->Merge 2.选择Reintegrate a branch 3.选择From URL,URL填好之后可以点击Show Log,可以看看这个branch是否是你要merge的内容,下面的Working copy中也可以Show Log,可以确认一下你的工作目录是否是trunk。确认后点击Next 4.Merge Options里面有些选项,根据需要来选择,Test Merge按钮会告诉你这次Merge会做哪些操作,最好先Test Merge一下!如果是预期的Merge操作,点击Merge则可以将branch Merge到本地工作目录下 ...

2015-11-11 · 1 min · 131 words · -

jvisualvm, JVM 监控分析工具(VisualVM)

jvisualvm, JVM 监控分析工具(VisualVM) Visual GC GC time Time taken to perform garbage collection Compile time Time spent in just-in-time (JIT) compilation if visualvm can not find java start visualvm with -jdkhome visualvm.exe -jdkhome D:\java\jdk7 插件安装目录 C:\Users\user0\AppData\Roaming\VisualVM\8u131 在Java多线程程序运行时,多数情况下我们不知道到底发生了什么,只有出了错误的日志的时候,我们才知道原来代码中有死锁。撇开代码检查工具,我们先讨论一下利用VisualVM监控,分析我们的多线程的运行情况。 (注: 实践本文内容的JDK的版本需要1.6.07以上) 什么是VisualVM VisualVM是JDK的一个集成的分析工具,自从JDK 6 Update 7以后已经作为Sun的JDK的一部分。 VisualVM可以做的: 监控应用程序的性能和内存占用情况、监控应用程序的线程、进行线程转储(Thread Dump)或堆转储(Heap Dump)、跟踪内存泄漏、监控垃圾回收器、执行内存和CPU分析,保存快照以便脱机分析应用程序;同时它还支持在MBeans上进行浏览和操作。尽管 VisualVM自身要在JDK6以上的运行,但是JDK1.4以上版本的程序它都能被它监控。 在JDK1.6.07以上的版本中: 到$JAVA_HOME/bin,点击jvisualvm.exe图标就可以启动VisualVM;当然也可以点击这里获取官方的最新版本,支持: 英文,中文,日文。 VisualVM功能集成较多,我们这里只讨论它对象线程的监控分析。 VisualVM监控线程 当我们运行VisualVM的时候,可以在应用程序》本地中看到VisualVM和eclipse的运行程序,然后我们启动eclipse中的一个 线程: com.longtask.thread.TestVisualVm,可以看到在菜单中多了一个该线程的显示。点击右边的 线程 菜单,可以看到线程运行的跟踪情况。 点击 thread dump,可以生成该线程的运行情况的tdump文件,通过thread dump提供的相关信息,我们可以看到线程在什么地方被阻塞了以及线程的其他状态。 把日志另存为文件,到Thread Dump Analyzer的主页点击图标下载TDA,然后用TDA打开刚才VisualVM保存的 thread dump文件,查看相关的分析结果。 远程监控 我们也可以用VisualVM来监控远程java线程的运行情况。 ...

2015-11-04 · 1 min · 208 words · -

pacstrap,command not found

‘pacstrap,command not found’ http://archlinuxarm.org/forum/viewtopic.php?f=60&t=8529 pacman -S pkgfile pkgfile --update pkgfile pacstrap pacman -S extra/arch-install-scripts command-not-found.com 提供 command not found 的搜索 command-not-found.com

2015-11-01 · 1 min · 21 words · -

linux 文本 统计

linux 文本, 字符 统计 # 统计一个目录下所有 .md 文件的字符数 find content/post -name '*.md' -exec wc -w '{}' \; > /tmp/foo.txt awk '{sum+=$1} END {print sum}' /tmp/foo.txt # 另外一种统计, 数字好像不太对, 有时间再研究一下. ls -lR content/post |grep '\.md'|wc -w 用 grep -c 来统计匹配的行数 grep -c 的作用类似grep | wc -l,不同的是,如果是查找多个文件,grep -c会统计每个文件匹配的行数,每行一个文件的列出来,而 wc -l 则列出总的统计数字。 另外grep -c 要比 grep | wc -l快一点。 grep -c night restart.07014 返回2 没有 返回0 http://blog.csdn.net/xuejiayue1105/article/details/1483940

2015-10-28 · 1 min · 64 words · -

java.lang.OutOfMemoryError,unable to create new native thread

‘java.lang.OutOfMemoryError,unable to create new native thread’ http://www.blogjava.net/ldd600/archive/2009/09/25/296397.html 星期一早上到了公司,据称产品环境抛出了最可爱的异常—OutOfMemory, 它是这样来描述他自己的: java.lang.OutOfMemoryError: unable to create new native thread 而且这位仁兄竟然还堂而皇之地同时出现在了3个application里面,所有应用全部遭殃。 那可爱的OOM是如何产生的呢?直接原因是创建的线程太多了,根本原因是某个地方的内存限制了。 搜罗了一下在网上找到了一个计算公式: (MaxProcessMemory - JVMMemory – ReservedOsMemory) / (ThreadStackSize) = Number of threads MaxProcessMemory: 进程最大的寻址空间,但我想这个值应该也不会超过虚拟内存和物理内存的总和吧。关于不同系统的进程可寻址的最大空间,可参考下面表格: Maximum Address Space Per Process Operating System Maximum Address Space Per Process Redhat Linux 32 bit 2 GB Redhat Linux 64 bit 3 GB Windows 98/2000/NT/Me/XP 2 GB Solaris x86 (32 bit) 4 GB Solaris 32 bit 4 GB ...

2015-10-27 · 2 min · 405 words · -