Linux操作系统的内存使用方法详细解析

我是一名程序员,那么我在这里以一个程序员的角度来讲解Linux内存的使用。

一提到内存管理,我们头脑中闪出的两个概念,就是虚拟内存,与物理内存。这两个概念主要来自于linux内核的支持。

Linux在内存管理上份为两级,一级是线性区,类似于00c73000-00c88000,对应于虚拟内存,它实际上不占用实际物理内存;一级是具体的物理页面,它对应我们机器上的物理内存。

这里要提到一个很重要的概念,内存的延迟分配。Linux内核在用户申请内存的时 候,只是给它分配了一个线性区(也就是虚存),并没有分配实际物理内存;只有当用户使用这块内存的时候,内核才会分配具体的物理页面给用户,这时候才占用 宝贵的物理内存。内核释放物理页面是通过释放线性区,找到其所对应的物理页面,将其全部释放的过程。

char *p=malloc(2048)    //这里只是分配了虚拟内存2048,并不占用实际内存。

strcpy(p,”123”)         //分配了物理页面,虽然只是使用了3个字节,但内存还是为它分配了2048字节的物理内存。

free(p)                //通过虚拟地址,找到其所对应的物理页面,释放物理页面,释放线性区。

我们知道用户的进程和内核是运行在不同的级别,进程与内核之间的通讯是通过系统调用来完成的。进程在申请和释放内存,主要通过brk,sbrk,mmap,unmmap这几个系统调用,传递的参数主要是对应的虚拟内存。

注意一点,在进程只能访问虚拟内存,它实际上是看不到内核物理内存的使用,这对于进程是完全透明的。

glibc内存管理器

那么我们每次调用malloc来分配一块内存,都进行相应的系统调用呢?

答案是否定的,这里我要引入一个新的概念,glibc的内存管理器。

我们知道malloc和free等函数都是包含在glibc库里面的库函数,我们试想一下,每做一次内存操作,都要调用系统调用的话,那么程序将多么的低效。

实际上glibc采用了一种批发和零售的方式来管理内存。glibc每次通过系统调用的方式申请一大块内存(虚拟内存),当进程申请内存时,glibc就从自己获得的内存中取出一块给进程。

内存管理器面临的困难

我们在写程序的时候,每次申请的内存块大小不规律,而且存在频繁的申请和释放,这样 不可避免的就会产生内存碎块。而内存碎块,直接会导致大块内存申请无法满足,从而更多的占用系统资源;如果进行碎块整理的话,又会增加cpu的负荷,很多 都是互相矛盾的指标,这里我就不细说了。

我们在写程序时,涉及内存时,有两个概念heap和stack。传统的说法stack的内存地址是向下增长的,heap的内存地址是向上增长的。

函数malloc和free,主要是针对heap进行操作,由程序员自主控制内存的访问。

在这里heap的内存地址向上增长,这句话不完全正确。

glibc对于heap内存申请大于128k的内存申请,glibc采用mmap的方式向内核申请内存,这不能保证内存地址向上增长;小于128k的则采用brk,对于它来讲是正确的。128k的阀值,可以通过glibc的库函数进行设置。

这里我先讲大块内存的申请,也即对应于mmap系统调用。

对于大块内存申请,glibc直接使用mmap系统调用为其划分出另一块虚拟地址,供进程单独使用;在该块内存释放时,使用unmmap系统调用将这块内存释放,这个过程中间不会产生内存碎块等问题。

针对小块内存的申请,在程序启动之后,进程会获得一个heap底端的地址,进程每次 进行内存申请时,glibc会将堆顶向上增长来扩展内存空间,也就是我们所说的堆地址向上增长。在对这些小块内存进行操作时,便会产生内存碎块的问题。实 际上brk和sbrk系统调用,就是调整heap顶地址指针。

那么heap堆的内存是什么时候释放呢?

当glibc发现堆顶有连续的128k的空间是空闲的时候,它就会通过brk或sbrk系统调用,来调整heap顶的位置,将占用的内存返回给系统。这时,内核会通过删除相应的线性区,来释放占用的物理内存。

下面我要讲一个内存空洞的问题:

一个场景,堆顶有一块正在使用的内存,而下面有很大的连续内存已经被释放掉了,那么这块内存是否能够被释放?其对应的物理内存是否能够被释放?

很遗憾,不能。

这也就是说,只要堆顶的部分申请内存还在占用,我在下面释放的内存再多,都不会被返回到系统中,仍然占用着物理内存。为什么会这样呢?

这主要是与内核在处理堆的时候,过于简单,它只能通过调整堆顶指针的方式来调整调整程序占用的线性区;而又只能通过调整线性区的方式,来释放内存。所以只要堆顶不减小,占用的内存就不会释放。

提一个问题:

char *p=malloc(2);

free(p)

为什么申请内存的时候,需要两个参数,一个是内存大小,一个是返回的指针;而释放内存的时候,却只要内存的指针呢?

这主要是和glibc的内存管理机制有关。glibc中,为每一块内存维护了一个chunk的结构。glibc在分配内存时,glibc先填写chunk结构中内存块的大小,然后是分配给进程的内存。

chunk ——size

p———— content

在进程释放内存时,只要  指针-4 便可以找到该块内存的大小,从而释放掉。

注:glibc在做内存申请时,最少分配16个字节,以便能够维护chunk结构。

glibc提供的调试工具:

为了方便调试,glibc 为用户提供了 malloc 等等函数的钩子(hook),如 __malloc_hook

对应的是一个函数指针,

void *function (size_t size, const void *caller)

其中 caller 是调用 malloc 返回值的接受者(一个指针的地址)。另外有 __malloc_initialize_hook函数指针,仅仅会调用一次(第一次分配动态内存时)。(malloc.h)

一些使用 malloc 的统计量(SVID 扩展)可以用 struct mallinfo 储存,

可调用获得。

struct mallinfo mallinfo (void)

如何检测 memory leakage?glibc 提供了一个函数

void mtrace (void)及其反作用void muntrace (void)

这时会依赖于一个环境变量 MALLOC_TRACE 所指的文件,把一些信息记录在该文件中

用于侦测 memory leakage,其本质是安装了前面提到的 hook。一般将这些函数用

#ifdef DEBUGGING 包裹以便在非调试态下减少开销。产生的文件据说不建议自己去读,

而使用 mtrace 程序(perl 脚本来进行分析)。下面用一个简单的例子说明这个过程,这是

源程序:

#include

#include

#include

intmain( int argc, char *argv[] )

{  

int *p, *q ;

#ifdef DEBUGGING  

mtrace( ) ;

#endif  

p = malloc( sizeof( int ) ) ;  

q = malloc( sizeof( int ) ) ;  

printf( "p = %p\nq = %p\n", p, q ) ;  

*p = 1 ;  

*q = 2 ;  

free( p ) ;  

return 0 ;

}

很简单的程序,其中 q 没有被释放。我们设置了环境变量后并且 touch 出该文件

执行结果如下:

p = 0x98c0378q = 0x98c0388

该文件内容如下

= Star

t@./test30:[0x8048446] + 0x98c0378 0x4

@ ./test30:[0x8048455] + 0x98c0388 0x4

@ ./test30:[0x804848f] – 0x98c0378

到这里我基本上讲完了,我们写程序时,数据部分内存使用的问题。

代码占用的内存

数据部分占用内存,那么我们写的程序是不是也占用内存呢?

在linux中,程序的加载,涉及到两个工具,linker 和loader。Linker主要涉及动态链接库的使用,loader主要涉及软件的加载。  

1、  exec执行一个程序

2、  elf为现在非常流行的可执行文件的格式,它为程序运行划分了两个段,一个段是可以执行的代码段,它是只读,可执行;另一个段是数据段,它是可读写,不能执行。

3、  loader会启动,通过mmap系统调用,将代码端和数据段映射到内存中,其实也就是为其分配了虚拟内存,注意这时候,还不占用物理内存;只有程序执行到了相应的地方,内核才会为其分配物理内存。

4、  loader会去查找该程序依赖的链接库,首先看该链接库是否被映射进内存中,如果没有使用mmap,将代码段与数据段映射到内存中,否则只是将其加入进程的地址空间。这样比如glibc等库的内存地址空间是完全一样。

因此一个2M的程序,执行时,并不意味着为其分配了2M的物理内存,这与其运行了的代码量,与其所依赖的动态链接库有关。

运行过程中链接动态链接库与编译过程中链接动态库的区别。

我们调用动态链接库有两种方法:一种是编译的时候,指明所依赖的动态链接库,这样loader可以在程序启动的时候,来所有的动态链接映射到内存中;一种是在运行过程中,通过dlopen和dlfree的方式加载动态链接库,动态将动态链接库加载到内存中。

这两种方式,从编程角度来讲,第一种是最方便的,效率上影响也不大,在内存使用上有些差别。

第一种方式,一个库的代码,只要运行过一次,便会占用物理内存,之后即使再也不使用,也会占用物理内存,直到进程的终止。

第二中方式,库代码占用的内存,可以通过dlfree的方式,释放掉,返回给物理内存。

这个差别主要对于那些寿命很长,但又会偶尔调用各种库的进程有关。如果是这类进程,建议采用第二种方式调用动态链接库。

占用内存的测量

测量一个进程占用了多少内存,linux为我们提供了一个很方便的方法,/proc目录为我们提供了所有的信息,实际上top等工具也通过这里来获取相应的信息。

/proc/meminfo 机器的内存使用信息  

/proc/pid/maps pid为进程号,显示当前进程所占用的虚拟地址。

/proc/pid/statm 进程所占用的内存

[root@localhost ~]# cat /proc/self/statm

654 57 44 0 0 334 0

输出解释

CPU 以及CPU0。。。的每行的每个参数意思(以第一行为例)为:

参数 解释 /proc//status

Size (pages) 任务虚拟地址空间的大小 VmSize/4

Resident(pages) 应用程序正在使用的物理内存的大小 VmRSS/4

Shared(pages) 共享页数 0

Trs(pages) 程序所拥有的可执行虚拟内存的大小 VmExe/4

Lrs(pages) 被映像到任务的虚拟内存空间的库的大小 VmLib/4

Drs(pages) 程序数据段和用户态的栈的大小 (VmData+ VmStk )4

dt(pages) 04

查看机器可用内存

/proc/28248/>free

             total       used       free     shared    buffers     cached

Mem:       1023788     926400    97388      0     134668     503688

-/+ buffers/cache:         288044     735744

Swap:      1959920      89608    1870312

我们通过free命令查看机器空闲内存时,会发现free的值很小。这主要是因为,在linux中有这么一种思想,内存不用白不用,因此它尽可能的cache和buffer一些数据,以方便下次使用。但实际上这些内存也是可以立刻拿来使用的。

所以 空闲内存=free+buffers+cached=total-used

查看进程使用的内存

查看一个进程使用的内存,是一个很令人困惑的事情。因为我们写的程序,必然要用到动态链接库,将其加入到自己的地址空间中,但是/proc/pid/statm统计出来的数据,会将这些动态链接库所占用的内存也简单的算进来。

这样带来的问题,动态链接库占用的内存有些是其他程序使用时占用的,却算在了你这里。你的程序中包含了子进程,那么有些动态链接库重用的内存会被重复计算。

因此要想准确的评估一个程序所占用的内存是十分困难的,通过写一个module的方式,来准确计算某一段虚拟地址所占用的内存,可能对我们有用。(T002)

 

 

转自: http://linux.ccidnet.com/art/302/20070524/1089197_1.html

一个windows上的wiki引擎

WikiPlex is a regular expression based wiki engine that allows developers to integrate a wiki experience into an existing .NET application seamlessly and with little effort. Built and used by the CodePlex team, WikiPlex has been thoroughly tested in real-world scenarios!

http://wikiplex.codeplex.com/

关于codeplex:
http://codeplex.codeplex.com/wikipage?title=About%20the%20CodePlex%20Site&referringTitle=CodePlex%20Documentation

好像是一个用于团队开发项目的程序

软件工程师的十个“不职业”行为

职业化是软件工程师的必然选择。本文根据我在教学和软件开发管理方面的实践,列举几个软件工程师“不职业”的行为或习惯,从另外一个侧面进一步探讨什么是真正的软件工程师职业化。


■ 文 / 陈尚义


职 业化之于软件工程师非常重要。因为:软件是看不见也摸不着的,它的进度也看不见摸不着,需要软件工程师严格自律、善于沟通;软件开发是创造性的劳动,创造 性劳动依赖个人主观能动性,没有自我激励是不可能成为出色的软件工程师的;软件在国民经济和人们日常生活中发挥着越来越重要的作用,软件工程师的道德行为 规范成为备受关注的问题。

下 面是软件工程师十个“不职业”行为。在一些特定领域工作的人们可能会认为这些不具有非常广泛的代表性。例如,IEEE和ACM联合发布的关于软件工程师职 业道德规范里,认为软件工程师首先要遵守的是社会公众原则,即所开发的软件要给人类带来福利,不能制造类似于计算机病毒那样的具有危害性的软件。由此,制 作病毒显然是最大的“不职业”。然而,在一般的商业型公司里这个问题不是最突出的,因此制作病毒并没有包含在本文列举的十大不职业行为之内。


行为一:对外交付半成品

我们的态度反映在我们的工作上,职业化的人士从不从自己手上交出不合格的工作产品。那些不职业的软件工程师满足于把工作做成半成品,等着让别人来纠正他们的错误。

开 发者总是不好好做单元测试,没有确认自己的代码符合不符合要求,就盲目自信地认为没有问题,提交给别人供集成和测试。殊不知,没有经过单元测试的代码,往 往在集成和系统测试阶段发现大量的问题,要修复这些问题需要付出更大的代价,这个代价比你自己发现并修复要大得多,给组织造成了巨大损失。


行为二:不遵守标准和规范

职业化的重要特征是遵守行业标准,不能肆意按照自己的想象来发挥。每个行业都有自己的技术规范,软件行业也同样如此,如IEEE发布的国际软件工程标准等;各个软件开发组织也有相应的代码规范、文档模板、代码审查清单等;有一定管理水平的软件开发组织还有相应的过程文件。

这 些都是软件工程师在软件开发过程需要遵守的规定。特别强调的是,自人们认识到软件危机以来,无论是学术界还是工业界都在不断地总结出软件开发的失败教训和 成功经验,并把他们总结成为最佳实践,进而形成标准,这些最佳实践是在大量实践的基础上提炼而成的,要充分利用这些最佳实践和标准指导自己的行动。


行为三:不积极帮助他人

技术人员最容易犯的错误是“保守秘密”,觉得自己开发的成果属于自己,不喜欢和别人共享。生怕影响自己在组织内的地位。

帮助别人也是帮助自己,这个简单的道理却被高智商的软件开发人士忽视。在其他行业中,帮助别人可能仅仅是一个美德,但在软件开发组织中,帮助别人还能为组织降低成本、缩短开发周期、提高产品质量,所有这些正是软件工程学科所研究、并试图解决的问题。


行为四:版权意识不敏感

我们既是软件的制造者,也是软件最积极的使用者。如果我们自身不遵守版权,就会给其他人造成极大的、负面的示范作用,也是对我们自己劳动成果的不尊重。在实际生活中我们看到太多的例子,大量的软件工程师盗版使用了其他公司的产品,并以此炫耀自己的能力。

不尊重版权的另一个例子是:不认真阅读开源代码的使用限制条款就随意使用;随便找到一个开发包,不问来龙去脉就嵌入到自己的系统;错误地认为它在组织内所做的工作成果是自己的,在离职后转让给他人;看到别人使用盗版软件不制止,而且还继续传播。


行为五:对待计划不严肃

软件工程强调计划性。在软件项目管理里,任何项目都要经过策划(Planning),策划的结果是项目计划。项目管理者跟踪项目计划的执行情况,记录计划执行过程中存在偏差的地方,对任何与计划有出入的想法都要事先经过评审和批准,然后才能付诸行动。

因此计划是严肃的。计划是大家沟通的平台,是检查项目状态(Project Status)的依据,也是控制项目变更的手段。计划还是一种承诺,因为策划过程是所有开发者都参与的,或者是征求过开发者意见的,承认了计划中的各种安排,就意味着你已经对外承诺了这些。

软件计划具有难以精确估计并动态变化的特性,因此需要我们软件工程师更加严肃地对待计划,而不应该成为我们不按计划行事的借口。


行为六:公事私事相混淆

公私分明是职业化的另一个重要特征。利用公司设备做自己的事情;在上班时间浏览自己感兴趣、和工作无关的网站,如上班炒股票,都是不职业化的行为和习惯,属于假公济私。

反 过来也一样是不职业的:用自己私人的设备处理公司的事务,用免费的邮箱发送和接收公司的邮件;带个人的电脑来办公室处理公司的业务。这样做,可能给组织的 软件安全性造成危害,也可能对组织的工作造成麻烦、惹出版权官司。在公和私之间画上一道红线,做到公私分明,是职业化软件工程师必备的素质。


行为七:不注意更新自己

职业的与非职业的软件工程师一个重要区别就在于职业化的人士经常学习,不断更新自己的知识,保持自己在本行业的竞争能力。

我接触到的很多工程师,他们想走捷径,对技术浅尝辙止;知其然不知其所以然;他们畏难而退:不想在一线战斗,喜欢搞他们想象的所谓的管理;想做测试,因为他们错误地认为测试对技术的要求不高……这些都是和职业化的软件工程师很不相称的。


行为八:不主动与人沟通

沟通,在软件开发领域,是责任问题,不是性格问题。

不 主动沟通,其背后隐藏的更为重要的原因是工程师的责任感不够。主动和上级、同行、下属沟通是职业化所必需的,因为软件开发需要团队协作,任何一个工程师的 工作都可能会影响别人,进而影响全局。软件工程的实践表明,个别人缺乏主动沟通,往往导致整个团队的技术方案出现偏差,或整个项目的进度受到影响。

报告(Report)是沟通的一个方式,有时显得特别重要。当你承担的任务进展顺利的时候,要报告;特别当任务进展遇到困难、可能会影响别人或引起变更的时候,更要报告。配合项目经理和QA人员跟踪项目的计划执行情况,是每一个工程师分内的职责。


行为九:不遵守职场规则

一些工程师不能很好地遵守软件行业的职场规则。比如:互相告知或打听工资和奖金的多少;离职时带走公司的源代码和文档;或急于到新单位工作而不专心交接等等。

软件计划的不精确性,导致开发任务的分布不均匀,特别是重要里程碑(如产品发布)之前,往往需要一定程度的加班。对此,职业化的软件工程师应给予理解和配合。


行为十: 不够诚实和正直

配 合项目经理做好计划是工程师不可推脱的职责。进度的安排是根据任务承担者的经验、水平来确定的,对所安排的任务,工程师本人应该有比较正确的判断。实际工 作中,却碰到有些工程师一天能完成的任务故意说成是两天,为自己争取到过分宽松的环境。虽然,也有组织要求软件工程师对工作量和进度有一定的判断和估计能 力,但这和故意虚报计划的性质是不一样的,前者是水平问题,后者是诚信问题。

工程师的正直来自于强烈的社会责任感。只有维护行业的道德水准和职业规范,软件行业才能持久健康发展。牺牲职业道德和规范水准,换来了暂时的经济利益,伤害的却是整个软件职业的荣誉和信任度。


作者简介:

陈尚义,1989年毕业于北京航空航天大学计算机系。现任中软通用产品研发中心总经理,北京航空航天大学兼职教授、硕士研究生导师,中科院研究生院硕士生导师,IEEE授权培训结构高级讲师。

(本文来自《程序员》杂志0910期,更多精彩内容敬请关注0910期杂志)

PHP中的数据计算

1. PHP中的整型的最大值和平台有关,如32位、64位

2. 原来以为超过2^32时就会出错,其实不是的,如果在2^32以内你做的是位操作,你们当超过2^32是,位操作可能就出现了你意想不到的结果,因为这时数据类型从整型变成了float了,表示数据的位数发生了变化。

3. 2^32 + 1 并溢出了整型,但是变成了浮点型,数据运算是没有问题的;原来以为超过了2^32时就出错的想法是错误的。

4. 相关知识参考PHP手册的“整型”“浮点型”部分

windows上如何查看文件或目录正在被哪个进程使用

微软官方提供的一个功能强大的任务管理器Process Explorer: http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx

使用该任务管理器可以替代系统默认的任务管理器,可以通过“find”菜单来查看某个文件或目录被具体哪个进程使用了。还有更多功能看看文档,自己研究一下吧

        

8 款用来代替 Windows 内置程序的更好的软件

http://www.appinn.com/8-freesoft-replace-windows-applications

windows 上的wowexec.exe是什么东西

  进程文件:wowexec 或者 wowexec.exe
进程名称:Microsoft Windows On Windows Execution Process
描述:wowexec.exe是操作系统相关程序,用于支持16位进程。
出品者:Microsoft Corp.
属于:Microsoft Windows On Windows Execution Process
系统进程:是

   wowexec.exe是系统进程,但是如果前面带一个空格,比如“ wowexec.exe”不一定是病毒。而是父进程下面的子进程,任务管理器中不会显示内存使用。如果让任务管理器不显示16位任务,则会消失。

关于虚拟内存的一点理解

1. 单个程序使用的最大的内存空间的大小收到内存指针的大小的限制,对于32位机,指针是4字节类型,最大标识4G的内存空间,所以32位机单个程序使用的内存空间不可能超过4G,实际上具体多少?我也不知道

2. 对于windows来讲,虽然好像每个程序都可以使用接近(可能差的比较远点儿)4G的内存空间,但是总的虚拟内存的大小也是有一个限制的,在“我的电脑”=》属性=》高级=》性能(设置)=》高级=》虚拟内存 这里可以设置,这里设置允许使用的磁盘空间的大小,虚拟内存的总大小是我们的物理内存和这里设置的总和。如果总和为5G, 则你的任务管理器里面的内存项最大为5G,当所有程序开辟的内存大于5G时,则开辟内存失败,系统提示“虚拟内存不足”。

3. 对于linux,好像没有处理指针的限制没有在开辟的时候做其他的限制,没有想windows上所谓的总的虚拟内存的限制,linux上的swap只是限制用于交换的磁盘空间的大小,但是并不用于限制是否开辟的内存超过了物理内存+swap的大小。

4. 我这里的测试都是使用的malloc函数,就是说,申请的内存实际上并没有真正使用这些内存,大概这就是“记账”的概念吧; 如果你用calloc函数来做这些测试,结果会不一样的,因为calloc是需要初始化内存的,和我想要证明的问题不符,所以不用。

5. linux的free命令说明的是物理内存和swap的使用情况,至于(某个)程序“想”使用(已经malloc,但是还没有初始化,可能没有这样的程序)的虚拟内存的大小是体现不出来的。

潜规则与显规则

   【世界经理人编者按】  只有显规则,则“水至清而无鱼”,只有潜规则,则会走向无序和混沌。  阴阳共存于太极;企业的发展,总是在两种规则的交替中进行;  “潜”与“显”之间均衡博奕,企业才能走向强大;清与浊之间从容游弋,经理人才能走向成功!

  显规则是地上河,潜规则是地下河,看不见,但更汹涌;  

   在企业之中,显规则和潜规则,就象是沙漠中的河流,显规则是奔腾的地上河,在这条奔腾河流的底下,还有一条激流暗涌的地下河流,这条河流我们看不到,但是,它真实存在,如果没有这个地下河,地上河很容易干涸,从这个意义上说,潜规则与显规则,是共存与企业之中的。它们各自担负着不同的企业使命。

  而实际上,潜规则和显规则,还存在一个博奕的问题,在什么时候,是显规则的力量可以制约潜规则的力量?在什么时候,是潜规则的力量可以制约显规则的力量?而在潜规则和显规则之间保持怎样一个关系的时候,企业才能够达到和谐?对于个人来说,如何把握潜规则和显规则之间的微妙关系,才能获得事业上的发展? 

  (一)阴阳两级的共振    

  “在企业内部和外部,实际上是存在着潜规则和显规则两种不同的规则,潜规则和显规则就是太极图案的阴阳两面,他们同时构成了企业中一切规则。而在企业运行的过程中,潜规则与显规则的作用都是不同的,他们都有其存在的合理性” 维尔肯有限公司市场总监,资深企业管理专家李炯明说。

  “企业是从没有规则开始的,它在运行过程中,逐步形成自己独特的,符合一定企业运行规律的行为模式,可以说,显规则是企业行为模式的沉淀,是一种稳定化和合理化的秩序。同时,显规则必须具备一个重要的特征,就是要能够普遍实施,比如说,公司规定每天9点上班,那么,工作日的九点钟,绝大多数员工必须要在9点钟的时候进入工作场所”。李炯明认为。

  至于显规则存在的意义,李炯明认为主要有两点。“显规则的一个重要意义,是使企业行为可以预期,比如过马路,我们要制定交通规则,车在左边,人在右边,如果没有这个规则,你走在大街上就没有安全感觉,车祸会接踵而至,而有了显规则,就可以预期企业的运行,企业也是一样,有了显规则,企业的明天和今天,就会有很大的连贯性,能够有秩序地延续。显规则的另外一个重要意义,是对于企业长远利益的保障”。

  对此,合众资源懂事长刘承元认为,显规则的存在意义,在不同的企业中有所区别,比如,他认为,越是在一些管理比较先进的企业,越是在一些知名的大企业,显规则越是意义重大,它对企业的经营管理起到了非常重要的指引和规范作用,不仅如此,显规则还享有名义上的正当性,有时候,潜规则还得受到它的制约。

  至于潜规则的形成,就有更广泛和深刻的原因。而其存在的意义,更多的是一种中和与过渡,是一种利益调节。对此,深圳邓皓时装设计有限公司总经理邓皓深有感触,“企业刚开始的时候,很多人跟我们一起创业,吃了不少苦,当我们的时装公司发展到现在,面临着新的飞跃的时候,很多人的能力已经不太适应了,但是,给个面子,讲讲人情,这是普遍存在的潜规则,我们并没有让他们走,而是给他们一定的重任,看看他们是否能够随企业的发展进步,观望一下,万一不行,我们也很希望有外面的更能干的人进来,在这里,潜规则实际就起了一个中和作用,可以使我们既能照顾一下老下属,又能够有机会请更能干的人进来,同时,在时间上也有个过渡”。

  深圳市企业家联合会秘书长李朝曙讲了个故事:“我有个朋友人很困惑,他以前所在的企业里面,流行拉山头,朋友在企业里面做事情,非常遵守规则,工作也很优秀,可是,一天醒来上班后,突然被人事部门叫去谈话,他被干掉了,原因不是他不遵守显规则,而是不遵守潜规则:没有在企业内部派系斗争中站队,一派胜利了,他成为另类,被人所不容。”

  实际上,很多成功的企业,都拥有比较先进的显规则,同时,也存在很多潜规则,它们是企业发展中的两条腿,缺了谁都不行。企业如此,企业中的人也如此。在企业中生存,就得既服从显规则,又要了解和遵从某些潜规则,除非自己不愿意干。        (二)交互与变易

  中国的传统文化讲究变易,我们看太极图,在上者为阳,但是,阳级的末梢深入到阴级中,阴级的末梢也渗透到阳级之中,形成一个阴中有阳,阳中有阴的交叉图案,而且,阴阳是可以互相转化的的,潜规则与显规则作为企业规则的两级,也是交互和变易的。

  企业中显规则的变化,是非常明显的,企业每发展到一个阶段,都有不同的企业文化,不同的战略安排,不同的管理制度,这些,都是可以通过文字的形式来固化的,这个变化是可见的;相对来说,企业潜规则的变化,则不是那么明显,甚至有几分神秘和诡异。

  老张是某企业的前元老,谈到以前的企业时愤愤不平,认为企业抛弃了他,老板在刚开始的时候,喜欢一些很听话的人,听话”才是真正起作用的潜规则,老张比较听话,做事卖力,就被提拔做了部门经理,近几年,企业飞速发展,需要很能干的人。老板又开始喜欢能干人,企业的潜规则就变了,有些元老看到这个潜规则的变化,加强了学习,于是,他们就成为副总什么的,但是,老张等另外几个元老却看不到变化,不去学习,能力不能提高,这个时候,老板已经不需要这种忠诚了,看到老张不能给企业带来明显的效益,就对老张动了刀。其实,老张被老板“过河拆桥”,就是因为没有看到企业潜规则也是变化的。

  而实际上,潜规则和显规则不仅是自身不断变化,而且是可以转化的,潜规则可以变成显规则,显规则也可以变成潜规则。

  比如说很多企业老板设立副总后,老怕副总会搞猫腻,或者是难以控制,于是,在工作中不敢放权,但是,又不会说,老板对于副总的防范,就是一个潜规则,而在华为,这个潜规则就变成了显规则,因为任正非通过显规则来制衡副总,他在华为设立了十几个副总,明确规定了各个副总的权限,使副总的权力分散,这些都可以写进章程中的,华为的这些规则,实际上就是把普遍存在于一些企业之间的潜规则显规则化。

  实际上,潜规则的显规则化,是企业中的一个普遍现象,今天的显规则,很可能就是从昨天的潜规则中来的,特别在一些不确定因素的影响下,很多规则不能定型,这时候就需要一种潜规则来指引企业和个人的行为,而当这些潜规则逐步积淀以后,就可以变成显规则。实际上,让潜规则中的积极因素发挥作用,无疑有益于企业的治理。

  从某种意义上说,显规则的潜规则化,是一个更漫长的过程,在企业中,有大量先进的显规则,但是,让显规则深入人心,使之潜规则化,成为企业人员内心一种潜移默化的,自觉遵守的一种东西,这才是规则力量的真正体现。而在一定意义上说,显规则一定得被信仰,否则,企业将会失去稳定和秩序,并且无法预期和操控。

  真正强大的组织,一定有一套先进的显规则,并且这个显规则成为大家普遍遵照的行为模式,西方发达国家的繁荣,就在于一套良好的社会制度,以及他们对这个制度的普遍信仰有意思的是,亚洲有些国家同样是西方的体制,但是,却无法达到西方国家的法治社会。其重要原因,就在于好的制度并没有成为他们内心认同的东西。马来西亚,印度尼西亚,韩国等,都未能彻底走出人治的阴影,出现强人政治和独裁统治,无法真正走向有序的,理性的社会。同样,我们与国际知名企业的最大差距,不在于显规则,而在于对显规则的真正认同,以及显规则的存在土壤和执行基础。

  一些企业之于显规则,就象是叶公好龙,真正从内心认同的很少,特别是一些强势的企业领袖主导型的企业,企业家个人的思想和理念,甚至是个人行事方式和人格,都对企业发挥着至关重要的作用,企业领袖的个人影响力场所形成的潜规则,比显规则所起的作用还要大,在企业领袖个人看来,显规则只不过是对自己“无形”和神秘操控的补充而已,更多的是个花瓶和摆设,甚至,在企业领袖的内心深处,对显规则有所排斥,不愿意使个人意志淹没在显规则中。而其巨大的弊端就是,当企业领袖已日益没落的时候,显规则和整个企业一样,已经成为殉葬品。

  显规则存在的土壤也很重要,国内企业“以洋为师”,工夫已经学得差不多,但是,为什么同样的东西,拿到自己手中就变了呢?橘生淮南为橘,生淮北则为枳,关键是土壤不同,前几年,麦肯锡兵败实达,就非常发人深思,麦肯锡设计的一套制度,在国外行得通,而且为很多知名企业的崛起和提升立下不小的功劳,但是,把它移植到国内企业,这套制度就失灵了。所以,很多时候,显规则的潜规则化,更需要土壤,企业基础管理的提高,企业文化的改造,甚至企业外部环境的变革等等,都是显规则潜规则化的重要条件。

  而只有显规则为企业所真正认同,并且通过企业行为不断地固化,成为企业人员自觉遵守的潜规则,才能使企业的发展具备有序和持续性。 

   (三)博奕与均衡

  在企业中,显规则和潜规则同时存在,也必然同时发挥作用,他们到底该发挥什么样的作用,如何形成和谐的共振,这其中包含着一个博奕的过程,而且这个博奕是交叉的,而且是多重的,主要表现在三个方面:企业内部各种利益的博奕,规则与人性的博奕。个体与规则的博奕。

  从博弈论来看,任何一个组织中的个体,在潜规则和显规则之间,其行为具有多种策略选择,而不同的选择带来的收益与付出的成本会有所不同,从整个组织来说,人们选择遵守显规则能够促进组织的持续和有序的发展,但从局部的小群体来看,由于单个的个体之间往往只重视眼前利益或局部利益,这就是潜规则往往成为人们的优先选择的原因。但是,当这种潜规则的影响达到足以使企业发展停滞的时候,形式就发生了变化,要么这个潜规则随着企业灭亡,要么必须彻底清除某一潜规则,而多数企业,则是在潜规则和显规则之间的博弈后,达到一种均衡。理性的个体,也应该选择那些使双方利益最大化的均衡策略。

  人性和制度之间,也存在博弈关系,由于人性本身的缺点,可以派生很多潜规则,比如,在很多企业,都把任人唯贤,以人为本作为显规则,但是人都有情感倾向,这就容易形成谁忠诚,谁跟自己交情深就提拔谁的潜规则,然而企业要发展,又必须遵守“任人唯贤”的显规则,到底遵循显规则还是潜规则,各遵守到什么程度,这就存在一个博弈,完全按照潜规则来办,很有可能企业会因人才凋敝而衰亡,而真的不参杂一点感情,也不符合人的本性,结果是失去人的支持,最后,通过博弈达到和谐。我们可以发现,国内一些能够强大的企业,都达到了人性和制度之间博弈均衡。美的处理创业功臣的问题时,何享健给创业功臣一定程度的股份,充分照顾到个人感情,同时,让他们退出舞台,使用人机制得以畅通,这个结果,是人性和制度博弈均衡的结果,而均衡才能达到和谐,美的由此圆满地解决了创业功臣的问题。成为企业界的经典之作。

  个人由于理念,能力,以及由此而来的影响力,与显规则和潜规则之间都存在一种博弈关系,而个人和企业之间的非均衡博弈都是企业的不吉之兆。

  个人对潜规则的挑战,如果全部失败的话,这个企业就得反思,为什么会留不住人,而且,当一个企业的潜规则足以使人无法生存的时候,必然给企业带来巨大的祸患。当年段永平由于无法适应“小霸王”的潜规则,离开了风头正劲的“小霸王”,而段永平离开“小霸王”不仅抽空了其中层管理人员,使其元气大伤,更致命的是,段永平后来创立了步步高,成为小霸王的主要竞争对手。

  更严重的事情,还是个人与企业显规则博弈的非均衡,特别是专制型的企业领袖,他们的影响力达到足以使显规则失效的程度,这个时候,企业就到了危险的边缘。当年巨人的倒掉,很大程度上就是因为史玉柱实在太强大了,巨人的制度根本无法约束他,在他建巨人大厦的过程中,很多人表示反对,但是,由于“老板一个人说了算”的潜规则,使他得以一意孤行,最后,巨人集团被拖死,一个庞大的企业帝国就此坍塌。

  理想的境地,应该是人与规则的博弈达到均衡的状态。而这个均衡,也一定是在规则之下的均衡。企业中人与规则博弈均衡的典型,是王石与万科。作为职业经理人而对企业有决定性的控制权,王石是一个特例,但是,这个特例是博弈的结果。在企业中,潜规则是资本大于人力,王石要改变这个局面,就要对规则进行一定程度的改变,王石的做法,是在遵守相关规则的情况下,稀释股东的股权,最后,达到和股东的抗衡。在这里,王石对潜规则的博弈,是在遵守相关股权变根的显规则下进行的,而不是通过新的潜规则去与这个潜规则进行博弈,这样,才能达到有序与和谐。

  附文:土豆,石头,咖啡豆

  有一个关于土豆,石头,咖啡豆的故事:人们把这三样东西放在锅里煮的时候,人们发现,土豆一会儿就烂熟了,变成一堆土豆泥,石头则纹丝不动,又硬有没有味道,而咖啡豆,则既可以保持一定的硬度,又可以散发出诱人的清香,熬出醇美的咖啡汁。

  这个故事在企业中广为流传,而在其中,我们也可以发现,土豆,石头,咖啡豆的隐喻,基本上代表了企业人对于潜规则的三种态度。

  “石头”型的人,一般很难以在企业生存,这种类型的人显著的特点,是比较顽固,不容易接受企业文化,也就很容易有意无意中与潜规则 “触网”,被人排斥,最后只好离开。

  “土豆”型的人,在企业里面比较遵从潜规则,但是,很容易变得过于世故,被企业规则同化,难以有发展后劲。

  ‘咖啡“型的人则非常受欢迎,一方面,他们能够在”潜规则“的浸淫下保持自己的风格和理念,另一方面,他们还可以为企业带来一些好的改变,在他们身上,潜规则和显规则得到了很好的平衡,事业能够得到和谐的发展。

  看看自己,是企业所喜欢的咖啡豆吗?

  (作者罗建法,欢迎您与作者探讨您的观点和看法,电子信箱:ljf96da@21cn.com