分配方案范例6篇

分配方案

分配方案范文1

年终奖是指每年度末企业给予员工不封顶的奖励,是对一年来的工作业绩的肯定。

年终奖的发放额度和形式一般由企业自己根据情况调整。好的年终奖办法要有较好的考评指标、评价方法、发放规则等等相应的各项制度,可以有效激励员工,增加企业凝聚力。

企业年终奖分配的几种方案

实践中,企业在设计年终奖金分配方案的时候,应该综合考虑组织、团队和个人三个层面的贡献和绩效来设计奖金分配系统。即基于组织、团队整体绩效及个人绩效的年终奖金分配方案。奖金分配方案有两种:封闭式和开放式。实施方案主要包括五个步骤。

封闭式年终奖金分配方案

步骤一:确定企业奖金包

根据企业的整体经济效益确定可以发放的奖金,常用确定公司奖金包的方式有三种。

第一种方式是采取企业的利润为基数,在组织和员工之间分享总利润的一定比例。

举例:某公司年终的利润额为1000万,按照规定提取10%的比例作为员工的年终奖金发放。

第二种方式是采用累进分享比例的方法,即规定若干个利润段,在不同的利润段采用不同的分享比例,利润越高提取比例也越高。

举例:某公司规定利润额的达标值为300万,300万利润以内分享比例为6%,在300万到800万之间分享比例为12%,800万到1500万之间的分享比例为16%,1500万以上的分享比例为22%.

第三种方式是采取按照利润率分段来分享的一种方法,即规定若干利润率段,利润率越高表明公司盈利的能力强,利润率分段越高则提取的净利润比例也越高。

举例:某公司利润率在2.5%以内的,则不发放奖金;当公司的利润率处于2.5%~5.0%之间时,则提取净利润的8%来发放奖金;当公司的利润率处于5.0%~7.5%之间时,则提取净利润的10%来发放奖金;以此类推。

步骤二:确定企业各部门战略贡献系数和部门绩效系数

部门战略贡献系数是表明企业各部门对企业的战略贡献的差异,需要企业对各部门的战略贡献能力进行评价。考虑到部门之间的协作与团结,尽量不要将各部门战略贡献系数差别太大。比如:通过对各部门的战略贡献能力进行评价,可以将组织内的各部门战略贡献系数界定在[1.2~0.8]之间,战略贡献系数变动单位为0.1.通常各部门的战略贡献系数跟企业所处的商业周期、企业战略、企业经营重点、企业文化、企业所处的行业、企业营销模式、企业核心人力资本等因素有关。

举例:某企业各部门战略贡献系数。

部门战略贡献系数

战略规划部0.9

总经理办公室1.0

信息中心(1级部门)

软件开发部1.0

系统维护部0.9

项目部1.1

行政部0.8

财务中心(1级部门)

会计部0.9

资金管理部0.8

成本中心1.0

营销中心(1级部门)

市场部1.2

企划部0.9

销售计划部1.0

销售部1.2

国际业务部1.2

国际客户服务部1.2

国内客户服务部1.2

人力资源中心(1级部门)

招聘部0.8

人才管理部1.1

工资福利部0.9

生产中心(1级部门)

制造一部0.9

制造二部1.0

制造三部1.0

制造四部1.0

制造五部1.1

技术中心

设计一部1.1

设计二部1.2

设计三部1.1

设计四部1.1

设计五部1.0

国际技术认证部1.0

……

我们可以定义各部门的绩效等级,并将部门绩效等级对应部门绩效系数。部门考核等级界定如下表,部门绩效系数界定为:[1.4~0.7]之间,部门绩效系数变动单位为0.1.

部门考核等级部门绩效系数

超出期望1.4/1.3

完成期望1.2/1.1

基本完成1.0

需努力0.9/0.8

需改进0.7/0.6

战略贡献系数、部门业绩系数权重分配比例

战略贡献系数权重部门绩效系数权重

40%60%

步骤三:确定部门奖金包

举例:假如某部门A对公司战略贡献系数为1.2,部门绩效系数为1.1,计算得出部门A的奖金系数。

战略贡献系数战略贡献系数权重部门绩效系数部门绩效系数权重部门奖金系数

部门A奖金系数1.2×40%+1.1×60%=1.14

将部门所有人员的月基本工资之和乘以部门奖金系数,根据下面的计算公司便可得到各部门的奖金金额了,计算公式如下:

部门i奖金包

步骤四:确定员工岗位绩效系数

1、根据定量与定性考核指标,得出员工个人绩效考核结果;

2、我们可以按照20%、70%、10%的比例来界定员工绩效等级比例;

3、管理层根据实际情况设计个人绩效考核结果与个人绩效系数之间的对应关系,比如,超出期望的员工,岗位绩效系数为1.3/1.4.

岗位考核等级岗位绩效系数绩效等级建议比例

超出期望1.3/1.420%

完成期望1.1/1.2

基本完成1.070%

需努力0.8/0.910%

需改进0.6/0.7

(岗位绩效系数变动单位为0.1)

步骤五:将部门奖金包分配到岗位,

将员工岗位绩效系数乘以员工月基本工资(也可以根据职位价值评价点数来计算),汇总

开放式年终奖金分配方案

实践中,假如某公司是一家集团公司或者公司含有多个事业部/多个业务单元,我们同样可以从公司、事业部/职能部门、岗位三个层面来考虑年度奖金的分配方案。

职等职位/资位公司绩效权重事业部/职能部门绩效权重岗位绩效权重目标奖金

年薪的%比例月工资倍数

企业在考虑员工个人收入跟公司经营绩效、事业部经营绩效和员工个人绩效相关联,可以根据员工的职位等级、对公司承担责任的程度,来分别确定不同的绩效权重比例和收入比例。目标奖金率可以根据设定目标的难易程度和市场平均水平来确定,同时具有市场竞争性。

1、对于公司总裁,是承担公司业绩主要责任者,其个人表现和决策对公司的总体业绩产生决定性影响,也就是说,其个人绩效结果将会全面体现在公司的整体业绩结果上。

2、对于业务单元级管理人员,其个人工作表现直接影响该业务单元运营结果,同时将其个人利益与公司的总体业绩挂钩以加强业务单元的团队合作。

3、员工级别越低,其个人表现与决定对业务单元与公司的业绩影响越小,而其对个人绩效结果所负的责任越大。同时个人承担部分公司绩效结果将促进员工参与意识,提高员工奉献精神,使员工与企业共同发展。

步骤一:确定公司绩效系数;

步骤二:确定事业部/职能部门绩效系数;

步骤三:确定员工个人岗位绩效系数;

步骤四:员工奖金系数=公司绩效系数×公司绩效权重+事业部/职能部门绩效系数×事业部/职能部门绩效权重+岗位绩效系数×岗位绩效权重

步骤五:员工个人年度奖金=员工年薪×目标奖金率×员工奖金系数

步骤一:确定公司绩效系数

根据公司发展战略,由董事会和公司总裁在制定预算时根据不确定收入的风险大小,设定对集团整体绩效考核指标和考核标准,并按超额累计计算:

示例:某公司绩效系数确定。

利润指标(亿)公司绩效系数

1.0

1.20.8

1.51

1.81.2

步骤二:确定事业部/职能部门绩效系数

根据部门的KPI指标的考核结果确定部门绩效系数,当部门的业绩超出组织期望时,部门绩效系数就大,如表所示:可能会是1.2/1.1;当部门的业绩未达标时,部门绩效系数则为0.9/0.8.我们可以将部门绩效系数界定为: [1.4~0.7]之间,部门绩效系数变动单位为0.1.

部门考核等级部门绩效系数

超出期望1.4/1.3

完成期望1.2/1.1

基本完成1.0

需努力0.9/0.8

需改进0.7/0.6

步骤三:确定员工岗位绩效系数

1、根据定量与定性考核指标,得出员工个人绩效考核结果;

2、按照20%、70%、10%的比例来界定员工绩效等级分布;

3、管理层根据实际情况设计个人绩效考核结果与个人绩效系数之间的对应关系,比如,超出期望的员工,岗位绩效系数为1.3.

岗位考核等级岗位绩效系数绩效等级建议比例

超出期望1.3/1.420%

完成期望1.1/1.2

基本完成1.070%

需努力0.8/0.910%

需改进0.6/0.7

(岗位绩效系数变动单位为0.1)

步骤四:员工奖金系数=公司绩效系数×公司绩效权重+事业部/职能部门绩效系数×事业部/职能部门绩效权重+岗位绩效系数×岗位绩效权重

示例:假设某部门经理A的月基本工资5000元,公司绩效系数为1.2,事业部绩效系数为1.3,岗位绩效系数为1.1,则个人年度奖金系数的计算过程如下:

公司绩效系数公司业绩权重业务单元业绩系数业务单元业绩权重个人绩效系数个人业绩权重员工奖金系数

部门经理A1.2×20%+1.3×60%+1.1×20%=1.24

步骤五:员工个人年度奖金=员工年薪×目标奖金率×员工奖金系数

示例:员工个人奖金计算:

A员工基本年薪目标奖金率员工奖金系数员工个人奖金

A5000×12×15%×1.24=11160

由以上可知:

分配方案范文2

二、实施范围:

车间在册正式职工,且根据公司有关规定所核定的享受奖金分配者。

三、考核内容:

由公司核定的技能工资、岗位工资、工龄工资和奖金投放基数以及其他有关奖励基金。

四、考核办法:

(一)技能工资

1.定额人员月度考核基本工时为206小时,当完成工时小于月度基本工时按下降比例扣减,当扣减后工资加各项政策性补贴小于规定的最低工资标准,则按最低工资标准发放。

2.无定额人员及管理人员当月累计五次(含五次)未完成临时交办任务者则按最低工资标准发放。

(二)岗位工资、工龄工资:

1.定额人员月度考核工时为250小时,当完成工时小于250小时则按5元/小时扣减。

2.无定额人员及管理人员当月累计二次(含二次)末完成临时交办任务者则按其所得额的50%给予扣罚,累计达三次(含三次)以上者则给予取消。

(三)超产奖:

定额人员月度完成工时大于250小时以上者则计发超产奖,为了充分体现多劳多得,奖勤罚懒的原则将采取激励机制,按台阶形式给予测算奖励。

(1)250<完成工时≤300小时,则按0.50元/小时计发;

(2)300<完成工时≤350小时,则按0.70元/小时计发;

(3)完成工时>350小时,则按1.00元/小时计发。

(四)基本奖:

1.基本奖的发放基数不作固定,必须根据公司对车间的综合考核以车间实际完成实绩所得额进行测算,在确保超产奖金额足够发放的前提下进行。

2.对未全额得到岗位工资、工龄工资的人员不得奖。

3.定额人员当月缺勤累计达5天(含5天)以上者不得奖。

4.无定额人员当月缺勤累计达3天(含3天)以上者不得奖。

(五)否决性指标考核:

1.因车间目标利润未完成指标或未完成公司下达的产品产量计划而被否决的,全车间不得奖。

2.发生重大工伤事故者(以填写工伤事故报告单为准)不得奖。

3.发生严重质量事故,造成经济损失较大,而被公司根据有关规定受处理者不得奖。

4.当季被评为不文明职工者不得奖(在季末次月扣罚)。

五、考核规定:

1.本方案与《精品车间综合管理考核规定》和《精品车间目标成本管理措施及考核办法》配套实施。

2.根据公司对车间目标利润的考核规定和工费成本的节(超)率情况,实行挂钩考核。

3.加班、加点费的发放,按每班28.00元计发,且按每班8小时扣除,同时个人可根据实际当月工时完成情况自行作调整。加点费每次按3.00元计发。

4.新进职工、实习人员,原则上从第四个月起按超产奖考核工时基数的50%测算,按台阶形式给予奖励,半年后按全额工时考核,实行超产奖和基本奖的发放。

分配方案范文3

一、项目组负责人工资分配

1、岗位工资。依据分公司相关分配规定,项目组负责人岗位工资为2176元。

2、绩效工资。项目绩效工资总额乘项目组负责人工资系数(0.25)等于项目组负责人当月绩效工资额。

3、提岗增资。项目组负责人2010年提岗工资额为300元,09年增资额按工资系数从本月09年增资总额中提取。

4、考核与奖励。项目组负责人除按照与营业部签订的《经营业绩责任书》进行考评外,每月如未完成营业部下达的必报任务,扣减2%的工资,如完成和超额完成营业部下达的任务则进行奖励。

二、项目组制单员工资分配

1、岗位工资。根据公司相关文件规定,制单员岗位工资为1370元。

2、绩效工资。项目绩效工资总额乘制单员工资系数(0.18)等于制单员当月绩效工资额。

3、提岗增资。制单员2010年提岗工资额为260元,09年增资额按工资系数从本月09年增资总额中提取。

4、考核及奖励。由于本项目仅一名制单员,由项目组负责人依据本月出勤、工作完成情况给予扣减或奖励。

三、项目组司机工资分配

1、岗位工资。根据公司相关文件规定,驾驶员岗位工资为1370元。

2、绩效工资,项目绩效工资总额乘驾驶员工资系数(0.16)乘出勤率等于当月驾驶员绩效工资额。

3、提岗增资。项目组司机2010年提岗工资额为260元,09年增资额按工资系数从本月09年增资总额中提取。

4、考核及奖励。由项目组负责人依据司机完成工作和车辆维护等情况给予扣减或奖励。

四、运转司机工资分配

由于项目货量发送存在严重不均衡,节假日前发货高峰时,本项目组司机往往无法完成货运任务,我项目组需向营业部借调运转司机完成货运任务。

1、计件工资。参照运转司机市内短驳费用,运转司机在项目按一趟30元计算工资,一日保底计件工资70元。

2、考核及奖励。本项目原则上不对运转司机进行考核,如运行过程中有特殊情况的,由项目组负责人上报调度室,由调度室决定处理。项目组根据运转司机的作业情况进行适当奖励。

五、快运项目操作组工资分配

1、快运项目操作组的分配由固定分配额及奖励两部分组成。

分配方案范文4

股票分配预案一般是在公告年报的同时一起公告的,一般出台预案后一般最快也要一个月才能进行实施分红的,主要原因是要经过股东大会同意通过这个分配预案后(同意后就会成为决案),再由上市公司安排实际实施的时间。

分红是股份公司在赢利中每年按股票份额的一定比例支付给投资者的红利。是上市公司对股东的投资回报。分红是将当年的收益,在按规定提取法定公积金、公益金等项目后向股东发放,是股东收益的一种方式。通常股东得到分红后会继续投资该企业达到复利的作用。

普通股可以享受分红,而优先股一般不享受分红。股份公司只有在获得利润时才能分配红利。

上市公司利润分配方案公布日之后,多久才是股权登记日要看上市公司利润分配定在哪一天,定在哪一天就是哪一天。股权登记日是在上市公司分派股利或进行配股时规定一个日期。

(来源:文章屋网 )

分配方案范文5

关键词:自动扫描;特性反射;单件模式;按需匹配;完全封装

中图分类号:TP

文献标识码:A

文章编号:1672-3198(2011)06-0248-01

1 优化目标

身份授权发生在账户登录系统后,执行操作前,旨在判断账户是否有权执行某项操作。该功能是任何系统的必要功能,常作为通用组件被封装。这里的“通用”不仅仅是指“重用”,它有着更为严格的四个目标:第一,重用性强。要求组件能够适用于任何Web系统。第二,可扩展性强。要求组件能够应对各种需求变化。第三,兼顾性能。不因为提高了安全性而降低性能。要实现这四个目标,必须充分分析现有方案,找准值得优化改善的关键点,最终提出确实可行的优化方案。

2 优化思路

权限分配为首先确定需要权限控制的操作,然后为该操作赋予相应的控制方式。例如,允许Admin角色查看系统日志。其中,操作指的是查看系统日志,相应的控制方式指的是允许Admin。针对权限分配,目前有两种方案,分别为编码型和配置型。经比较,编码型方案在操作及其控制方式方面都是常量编码,所以不管扩展操作还是扩展控制方式都要修改源代码。而配置型方式在控制方式方面采用变量配置,所以在扩展控制方式时只需修改配置文件即可。尽管如此,配置型方式仍存不足,即该方式在操作方面仍是常量编码,所以若要新增某项操作,必须修改源代码。为此,本文主张沿用配置型方案对控制方式采用变量配置的同时,对操作采用变量扫描。即自动扫描整个系统,从中发现需要权限控制的操作。具体改进如表1所示。

编码型常量编码常量编码

配置型(DB/XML)常量编码变量配置

扫描型变量扫描变量配置

比较可知,配置型在控制方式方面优于编码型。扫描型又在操作方面优于编码型。虽然扫描型在权限控制方面与配置型相同,但在发现操作方面不同。前者系统自动扫描发现需要权限控制的操作,后者则是开发人员手工录入需要权限控制的操作。

在技术方面,扫描型强调使用特性反射技术。首先在需要权限控制的操作上附加特性标记,然后根据标记反射出需要权限控制的操作。其中,为弥补反射会降低性能的不足,扫描型还强调使用基于静态变量的单件模式。因为静态变量能够使反射在系统初始化时执行,而单件模式能够使反射只执行一次,而后所有操作及控制方式存储于内存中。为客户分配权限时,系统直接从内存中获取,没有任何性能影响。综上所述,扫描型方案无论在操作扩展还是在控制方式扩展方面,都是可行的配置方案,有效增强了身份授权组件的重用性和扩展性。

3 扫描型权限分配的详细设计方案

(1)定义一个SecurityMarkAttribute特性,其中包含是否控制增加、是否控制获取、是否控制修改、是否控制删除、基本描述等字段信息。该特性用于附加在业务类上,表示要对该类实施某种操作控制。例如,要控制日志系统的增加、获取,但不控制其修改、删除。实现代码如下:

[SecurityMark(true,ture,false,false,“系统日志”)]

Class SystemLog{}。

(2)UI层定义一个web.config配置文件,其中标记需要进行安全控制的类的库文件,以便系统找到扫描的目标。例如,若SystemLog类在Library库中,必须使系统将库Library作为扫描目标,实现代码如下:

(3)定义一个包含类名、操作类型的SecurityMember类,表示对特定类的特定操作进行控制。其中,操作类型是一个枚举,分别代表增、删、改、查等四种操作类型。例如,要控制系统日志的新增。SecurityMember类对象的类名为SystemLog,操作类型为Add。要控制系统日志的修改。SecurityMember类对象的类名为SystemLog,操作类型为Edit。

(4)最为关键的就是定义一个SecurityMemberList类(SecurityMember类的集合),其中包含CreateList()和LoadSecure()两个方法。前者根据web.config配置文件中标记的路径确定扫描目标。后者通过反射技术将扫描目标中的类的特性读取出来形成SecurityMember对象集合,即动态获取所有权限。

4 总结

在权限分配方面,对发现操作采用扫描型方案,即使用特性反射和基于静态变量的单件模式使系统自动识别所有需要权限控制的操作,在不降低性能的情况下,提高重用性和扩展性。

参考文献

[1]HUANG Qing. An Application of Code Specification Based on CSLA [J]. In:International Conference on Information Management and Engineering (ICIME). 2010.

分配方案范文6

1 嵌入式系统中对内存分配的要求

①快速性。嵌入式系统中对实时性的保证,要求内存分配过程要尽可能地快。因此在嵌入式系统中,不可能采用通用操作系统中复杂而完善的内存分配策略,一般都采用简单、快速的内存分配方案。当然,对实性要求的程序不同,分配方案也有所不同。例如,VxWorks采用简单的最先匹配如立即聚合方法;VRTX中采用多个固定尺寸的binning方案。

②可靠性。也就是内存分配的请求必须得到满足,如果分配失败可能会带来灾难性的后果。嵌入式系统应用的环境千变万化,其中有一些是对可靠性要求极高的。比如,汽车的自动驾驶系统中,系统检测到即将撞车,如果因为内存分配失败而不能相应的操作,就会发生车毁人亡的事故,这是不能容忍的。

③高效性。内存分配要尽可能地少浪费。不可能为了保证满足所有的内存分配请求而将内存配置得无限大。一方面,嵌入式系统对成本的要求使得内存在其中只是一种很有限的资源;另一方面,即使不考虑成本的因素,系统有限的空间和有限的板面积决定了可配置的内存容量是很限的。

2 静态分配与动态分配

究竟应用使用静态分配还是动态分配,一直是嵌入式系统设计中一个争论不休的总是。当然,最合适的答案是对于不同的系统采用不同的方案。如果是系统对于实时性和可靠性的要求极高(硬实时系统),不能容忍一点延时或者一次分配失败,当然需要采用静态分配方案,也就是在程序编译时所需要的内存都已经分配好了。例如,火星探测器上面的嵌入式系统就必须采用静态分配的方案。另外,WindRiver公司的一款专门用于汽车电子和工业自动化领域的实时操作系统OSEKWorks中就不支持内存的动态分配。在这样的应用场合,成本不支持内存的动态分配。在这样的应用场合,成本不是优先考虑的对象,实时性和可靠性才是必须保证的。当然,采用静态分配一个不可避免的总是就是系统失去了灵活性,必须在设计阶段就预先知道所需要的内存并对之作出分配;必须在设计阶段就预先考虑到所有可能的情况,因为一旦出现没有考虑到的情况,系统就无法处理。这样的分配方案必须导致很大的浪费,因为内存分配必须按照最坏情况进行最大的配置,而实际上在运行中可能使用的只是其中的一小部分;而且在硬件平台不变的情况下,不可能灵活地为系统添加功能,从而使得系统的升级变得困难。

大多数的系统是硬实时系统和软实时系统的综合。也就是说,系统中的一部分任务有严格的时限要求,而另一部分只是要求完成得越快越好。按照RMS(Rate Monotoin Scheduling)理论,这样的系统必须采用抢先式任务调度;而在这样的系统中,就可以采用动态内存分配来满足那一部分可靠性和实时性要求不那么高的任务。采用动态内存分配的好处就是给设计者很大的灵活性,可以方便地将原来运行于非嵌入式操作系统的程序移植到嵌入式系统中,比如,许多嵌入式系统中使用的网络协议栈。如果必须采用静态内存分配,移植这样的协议栈就会困难得多。另外,采用动态内存分配可以使设计者在不改变基本的硬件平台的情况下,比较灵活地调整系统的功能,在系统中各个功能之间作出权衡。例如,可以在支持的VLAN数和支持的路由条目数之间作出调整,或者不同的版本支持不同的协议。说到底,动态内存分配给了嵌入式系统的程序设计者在比较少的限制和较大的自由。因此,大多数实时操作系统提供了动态内存分配接口,例如malloc和free函数。

3 RTOS提供的内存分配接口

不同的RTOS由于其不同的定位,采用不同的内存分配策略。例如VRTX中,采用类似于GNU C中由Doug Lea开发的内存分配方案,即Binning算法,系统内存被分成了一些固定尺寸的内存块的算法,系统内存被分成了一些固定尺寸的内存块的集合。这种方法的优点是查找速度快而且不会产生内存碎片。但是,它的缺点也很明显,就是容易造成浪费,因为内存块的尺寸只有有限个,分配时只能取较大的内存块来满足一个较小的需求,累积起来,浪费就很大了;而且操作系统管理这样一个内存分配表也是一个很大的负担。

下面详细介绍一下我们常用的RTOS——美国风河公司(WindRiver)的VxWorks中采用的内存分配策略。VxWorks的前身就是VRTX,据说VxWorks的名称来自make vrtx work。

VxWorks的内存管理函数存在于2个库中;memPartLib(紧凑的内存分区管理器)和memLib(完整的内存分区管理器)。前者(memPartLib)提供的工具用于从内存分区中分配内存块。该库包含两类程序,一类是通用工具创建和管理内存分区并从这些分区中分配和管理内存块;另一类是标准的malloc/free程序提供与内存分区的接口。系统内存分区(其ID为memSysPartId是一个全局变量)在内核初始化时由usrRoot调用memInit创建。其开始地址为RAM中紧接着VxWorks的BSS段之后,大小为所有空闲内存,如图1所示。

当创建其它分区时,一般需要先调用malloc从系统内存分区中分配一段内存才能创建。内存分区的结构定义为mem_part,包含1个对象标记,1个双向链表管理空闲块,1个信号量保护该分区及一些统计信息,如总尺寸、最大块尺寸、调试选项、已分配的块数、已分配的尺寸等。其语句如下:

typedef struct mem_part {

OBJ_CORE objCore; /*对象标志*/

DL-LIST freeList; /*空闲链表*/

SEMAPHORE sem; /*保护分区的信号量*/

Unsigned totalWords; /*分区中字(WORD)数*/

Unsigned minBlockWords; /*以字为单位的最小块尺寸*/

Unsigned options; /*选项,用于调试或统计*/

/*分配统计*/

unsigned curBlocksAllocated; /*当前分配的块数*/

unsigned curWorkdAllocated; /*当前分配的字数*/

unsigned cumBlockAllocated; /*累积分配的块数*/

unsigned cumWordsAllocated; /*累积分配的字数*/

}PARTITION;

一般系统中只有1个内存分区,即系统分区,所有任务所需要的内存直接调用m

alloc从其中分配。分配采用First-Fit算法(注意这种算法容易导致大量碎片),通过free释放的内存将被聚合以形成更大的空闲块。这就是VxWorks的内存分配机理。分配时可以要求一定的对齐格式。注意,不同的CPU架构有不同的对齐要求。为了优化性能,malloc返回的指针是经过对齐的,为此的开销随构不同而不同。例如,68K为4字节对齐,开销8字节;SPARC为8字节对齐,开销12字节;MIPS为16字节对齐,开销12字节;I960为16字节对齐,开销16字节。MemLib库中提供了增强的内存分区管理工具,并且增加了一些接口,而且可以设置调试选项。可以检测2类错误:①尝试分配太大的内存;②释放内存时发现坏块。有4种错误处理选项,当发生错误时记录消息或挂起任务。

但是,使用动态内存分配malloc/free时要注意到以下几方面的限制。①因为系统内存分区是一种临界资源,由信号量保护,使用malloc会导致当前调用挂起,因此它不能用于中断服务程序;②因为进行内存分配需要执行查找算法,其执行时间与系统当前的内存使用情况相关,是不确定的,因此对于有规定时限的操作它是不适宜的;③由于采用简单的最先匹配算法,容易导致系统中存在大量的内存碎片,降低内存使用效率和系统性能。

针对这种情况,一般在系统设计时采用静态分配与动态分配相结合的方法。也就是对于重要的应用,在系统初始化时分配好所需要的内存。在系统运行过程中不再进行内存的分配/释放,这样就避免了因内存的分配释放带来的总是。而且在系统初始化,因为没有内存碎片,对于大的内存块的需求容易满足。对于其它的应用,在运行时进行动态内存分配。尤其是某些应用所要求的大量固定尺寸的小内存块,这时就可以采用一次分配多次使用的内存分配方案。下面详细介绍这种内存分配方案及其应用场合。

4 一次分配多次使用的内存分配方案

在嵌入式系统设计中,经常有一些类似于内存数据库的应用。这些应用的特点是在内存中管理一些树,比如以太网交换机中的MAC地址表、VLAN表等,或者路由器中的路由表。这些树是由许多相同尺寸的节点组成的。这样,就可以每次分配一个大的缓冲池,比如包含多个内存单元的数组,每个内存单元用于1个节点。我们用一个空闲链表来管理该数组中的空闲内存单元。每次程序需要分配内存以创建1个新的节点时,就从空闲链表中取1个单元给调用者。程序删除节点并释放内存时,将释放的内存单元返还给空闲链表。如果链表中的空闲内存单元取空了,就再次调用malloc从系统内存中分配一个大的内存块作为新的缓冲池。采用这样一种方案主要有如下优点:①减少了malloc/free的调用次数,从而降低了风险,减少了碎片;②因为从缓冲池中取一个内存单元是时间确定的(当然,如果缓冲池耗尽从而需要重新调用malloc分配除外),因此它可以用于严格时限的场合从而保证实时性;③它给用户以自由来添加一些用于内存分配和释放的调试函数以及一些统计功能,更好地监测系统中内存的使用情况。

这种方案必然涉及到一个缓冲池的结构。一般缓冲池的结构由以下几部分组成:单元尺寸、块尺寸(或者单元数目)、缓冲池指针、空闲链表、用于统计和调试的参数等。对缓冲池的操作包括创建缓冲池、释放缓冲池、从缓冲池中分配1个内存单元、释放内存单元回缓冲池等。下面举2个例子说明一下该方案的具体使用情况。

4.1 Intel交换机驱动程序中内存分配

在以Intel的交换芯片为基础的交换机方案中,因为采用的是软件地址学习的方式,需要在内存中维护许多数据,如MAC地址表的软拷贝、VLAN表、静态单播地址表、组播地址表等。这些表都是由一些树组成,每个树由一些固定尺寸的节点组成。一般每个节点几十个字节,每棵树的节点数是可增长的,少则几十,最多可到16K个节点。因此,很适合于采用该方案,具体的实现如下:

(1)缓冲池结构BlockMemMgr

typedef struct{

MemSize data_cell_size; /*数据单元的尺寸*/

MemSize block_size; /*块尺寸*/

/*下面的变量为预定义的每个管理器最多包含的块数,如64

MAX_BLOCKS_OF_MEM_SIZE*/

Unsigned short blocks_being_used;/*已使用的块数*/

Void mem_ptr[PAX_BLOCKS_OF_MEM_SIZE];

/*块数组*/

SLList free_data_cells_list; /*空闲链表*/

}BlockMemMgr;

结构中的参数包括:单元尺寸、块尺寸、已用块数、所有块的地址、空闲链表(单向链表)。

(2)缓冲池的管理函数

block_mem_create:创建块内存管理器,参数包括内存指针(如为NULL,表示自己分配)、块尺寸、单元尺寸、返回管理器指针。

过程如下:

①检验参数合法性。

②单元尺寸4字节对齐,计算每个块中的单元数。对内存指针进行4字节对齐或者分配内存指针。

③初始化结构BlockMemMgr,包括单元尺寸和块尺寸。设置第1个内存块的指针。如果内存是外来的,设置块已用标志(已用为0),表示不能增加块;否则,已用块数设为1。

④创建空闲链表,将块内所有单元添加到链表中,最后一个单元处于链表的最前面。

⑤返回BlockMemMgr。

block_mem_destroy:解构一个块内存管理器,释放它所分配的所有内存,调用者负责外部内存的释放。参数为BlockMemMgr。返回成功失败标志。

①参数合法性检测。

②删除单向链表(设链表指针为NULL)。

③如果块是动态分配的,释放它们。

④释放结构BlockMemMgr。

block_malloc:从块内存管理器中分配1个单元

⑤释放结构BlockMemMgr

block_malloc:从块内存管理器中分配1个单元。参数为BlockMemMgr,返回数据单元指针。

①参数合法性检测。

②判断空闲链表是否为空(是否为NULL)。如果为空,判断是否可以动态分配块,如果不能,返回失败;如果可以动态分配块,则分配1个块,执行与block_mem_create一样的操作。

③从空闲链表中分配第1个单元,返回其指针。

注意这里有一个小技巧,即数据单元在空闲时其中存放空闲链表的节点信息,而分配后则存放数据内容。

block_free:释放1个数据单元,返回块内存管理器。小心不要对1个单元释放2次。参数为BlockMemMgr和单元指针。

①参数合法性检测。

②地址比较,判断数据单元属于哪个块。

③判断数据单元的内容是否为空闲链表节点信息(也就是块内某单元的地址),从而确定是否为2次释放。

④将该数据单元插入到空闲链表的前面。

⑤引用该单元的指针设为NULL。

内存管理代码遵守如下约定:①管理的内存是实际可写的内存;②分配内存是4字节或32位对齐;③block_malloc、block_free在中断级调用是部分安全的,除非BLOCK中已经没有空闲CELL,需要重新调用malloc分配新的BLOCK(而malloc和free就不是安全的,因为其中使用了信号量和搜索算法,容易引起中断服务程序阻塞)。当然,block_mem_create和block_mem_destroy必须在进程级调用。

4.2 TMS中的内存分配

TMS是WindRiver公司为可管理式交换机推出的开发包。它用用IDB来管理各种协议的数据,比如STP和GVRP等。为了支持IDB,它建立了自己的缓冲池管理方案,程序在bufPoolLib.c中。该程序包含用于缓冲池管理的函数,这些函数允许从1个池中分配固定数目和大小的缓冲区。通过预先分配一定数目固定大小的缓冲区,避免了反复的小的内存块分配/释放相关联的内存碎片和浪费。既然它从1个单一的块中分配缓冲池,也比对每一个缓冲区执行1次分配有更高的空间效率。模块对每个缓冲区加上1个标记(MAGIC),释放时会检查标记。

模块给用户提供分配和释放操作定义回调函数的能力。这样可以做到自动的对象创建和解构,同时允许由多个缓冲池分配的成员组成的对象做为1个单一的实体删除。这类似于C++中自动的对象构建和解构,不过是用C语言并且没有堆栈分配的负担。模块既允许从堆栈中分配缓冲池(通过calloc),也可以在用户分配的空间中创建它们。模块用1个单向链表来维护未分配的缓冲区,但不跟踪已分配的缓冲区。模块并不是任务安全的,用户需要用信号时来保护缓冲池。(1)缓冲池结构

typedef struct

{

ulong_t magic; /*用于一致性检测的特殊标记*/

Boolean localAlloc; /*内存是否在创建缓冲区时分配*/

SL_LIST freeList; /*空闲链表*/

Void store; /*缓冲区指向的内存指针*/

STATUS(*createFn)(void*,ulong_t argl); /*创建缓冲区时的回调函数指针*/

STATUS(*destroyFn)(void*,ulong_targl);/*释放缓冲区时的回调函数指针*/

Ulong_t argVal;/*回调函数的参数*/

} buf_pool_t;

结构中的参数包括检查标记MAGIC、是否本地分配、空闲链表、内存指针、创建缓冲池的回调函数指针、释放时的回调函数指针、回调函数参数。

(2)相关函数

BufPoolInitializeStorage:分配和初始化存储区。参数包括存储区地址(如为NULL,则本地分配)、缓冲区大小、缓冲区个数。

①根据缓冲区大小和个数获得所需的内存大小。

②如果指针为NULL,则调用calloc分配内存。设置本地分配标志。

③初始化内存为0。

④初始化指针。分配的内存块最前面为缓冲池结构buf_pool_t。实际的存储区紧随其后。Buf_pool_t包含参数检查标记、是否本地分配、存储区地址、分配时回调函数、释放时回调函数、回调函数变量。此时只设置存储区指针。

BufPoolCreate:创建缓冲池。参数为内存制止。缓冲区尺寸和个数,创建时回调函数、释放时回调函数、回调函数参数。

①尺寸对齐。

②调用bufPoolInitializeStorage初始化内存区和buf_pool_t结构。

③用传入参数填充buf_pool_t结构。

④将缓冲区添加到空闲链表中,最后的缓冲区在最前面。

BufPoolDestroy:删除缓冲池。参数为buf_pool_t指针。

①检查缓冲池结构中的MAGIC字段是否被个性。

②如果是本地分配的则翻放内存区。

BufPoolAlloc:从缓冲池中分配一个缓冲区,参数为缓冲池结构指针。如果存在空闲缓冲区,则从空闲链表中除并提供给调用者,执行创建时回调函数。如果回调函数返回错误,则将缓冲区返还给空闲链表。

①检查缓冲池结构中的MAGIC标记是否完好。

②从空闲链表中取出头一个节点。

③如果节点不为空,清空节点,以其地址为参数调用回调函数。

④如果回调函数返回错误,则将节点还给空闲链表。

⑤返回得到空闲缓冲区地址。

BufPoolFree:将缓冲区返回给缓冲池。如果定义了回调函数,将在归还缓冲之间调用回调函数。参数为缓冲池结构和缓冲区指针。

①缓冲池MAGIC标记是否完好。

②如果定义回调函数、调用之。如果返回错误,则设置错误号。

③将缓冲区添加到空闲链表中头部。

注意该函数有2点:①回调函数返回错误,照样归还缓冲区。②没有检查缓冲区是否二次释放,这一点与Intel的驱动程序不同。

另外,TMS的缓冲池没有BLOCK要领,不需要判断哪个CELL属于哪个BLOCK,简化 了操作。