验证的程序

2025-01-28

验证的程序(共7篇)

验证的程序 篇1

0前言

由于设备清洗维护不当或防尘管理不当, 在过去二十年间, 因实际的或潜在的交叉污染问题已从市场上撤回了大量的药品。这些事件对消费者产生了伤害, 也给制药企业带来了恶劣影响。过去检查官更注意检查青霉素类与非青霉素类药物之间的交叉污染、药品与甾类物质或激素之间的交叉污染问题。现在检查官更关注可以共用一条生产线生产的品种的交叉污染问题。由于法规要求, 青霉素类与非青霉素类药物之间的生产已经进行了物理隔离, 而制药技术的进步使同一品种批间差异非常小, 即使清洁不彻底不会有很大风险, 最大的风险就是同一生产线不同品种的交叉污染, 这也是本文重点。

1 验证的准备

1.1 成立验证小组

以设备所在部门为主成立验证小组, 指定小组组长一名, 成员一般包括质量管理人员、检验人员、部门管理人员、岗位操作人员。列明在小组内人员的分工, 质量管理人员负责监督、指导整个验证过程, 按照公司的各个规程进行, 及跨部门的协调;检验人员负责验证过程中的样品检测, 需要具体写清楚谁来检测什么项目;部门管理人员负责协调人员、资源以保证验证的顺利实施, 并审核验证是否合理充分, 这些人员基本上经验丰富, 在验证中的作用也是最关键的;岗位操作人员负责验证的实施。小组组长一般由管理设备的技术人员或有经验的管理人员担任, 负责全面工作, 验证过程一定要保证全员参与。

1.2 风险评估

验证小组成立后, 在进行验证之前应先进行风险评估, 通过风险评估确定验证的范围和程度。验证的范围主要是要弄清楚有几个品种共用, 共用的设备有哪些, 验证的程度主要是弄清楚清洁过程的各项参数, 清洁后的检查项目。

1.2.1 品种的评估

列出共线品种, 分析各品种的性质是否接近, 清洗方法是否一致。如果清洗方法一致, 则选出一个品种或中间体作为清洗目标物。如果清洗方法不一致, 则需要进行多个清洁验证。首先, 按照清洗方法进行分类, 在每类中选出一个品种或中间体作为清洗目标物。如果每一个品种或中间体的清洗方法都不一致, 则建议不共用同一设备。

评估的内容应包括溶解性、清洗难度、日剂量、毒性、产品稳定性等内容。方法就是将每一产品的参数同时列出, 逐项对比, 找出清洗目标物。

一般情况下, 下一产品则选择批量最小的或是日剂量最小的。如果能够得到日剂量的信息, 则选用日剂量的千分之一和批量的10ppm中最小的;如果不能得到日剂量信息的原料药或中间体, 则选用批量最小。

1.2.2 设备的评估

列出设备清单, 清单内容包括:设备的名称, 生产商, 编号, 型号, 材质, 用途等, 必要时应附图纸。连接管道应写明长度, 直径, 坡度, 几个拐弯及弯度, 有无死角等信息。

找出共用的设备有哪些, 各部分与物料接触的内表面积多少, 依据内表面积的比例可以得出各个设备的安全系数。找出设备或连接管道中最难清洁的部位, 即最难清洗点。通过系统影响性评估和关键部件评估确定关键设备、关键部件。

1.2.3 清洁过程的各项参数

清洁过程的参数一般包括但不限于如下内容。

(1) 脏物保留时间:设备使用完成后, 最长可放置多长时间进行清洗, 或者放置多长时间后必须清洗。 (2) 使用的水及清洁剂的名称、浓度、配制方法, 用量。如需要加热, 则需注明溶剂的沸点、温度、回流时间等。使用注射用水时必须注明水温。 (3) 压力。 (4) 清洗时间。 (5) 清洗角度。 (6) 清洗间隔。 (7) 清洗循环次数。 (8) 浸泡时间及溶剂用量。 (9) 气吹循环次数。 (10) 气吹时间。⑾气吹间隔。⑿清洗有效期。

1.2.4 可接受标准

可接受标准的确定要依据药品的性质、要求。例如:药品难清洗不能够完全淋洗干净, 则采用擦拭法取样、检测。药品需要检测微生物限度或微生物对药品影响很大, 则最终检测要检测微生物限度。一般情况下, 可接受标准包括以下几项: (1) 目测淋洗水澄清透明, 无可见异物。 (2) 目测设备内壁及最难清洗处无可见异物, 对于光线不好的设备要借助照明设备。 (3) 淋洗 (擦拭) 取样并检测化学残留, 微生物限度, 细菌内毒素。如果测定特定的产品残留不现实, 则可以选择其他的代表性参数, 例如:总有机碳 (TOC) 和电导率。

1.3 验证支持文件的确认

风险评估后, 根据风险评估结论, 建立清洁程序;如果已有清洁程序, 查看清洁程序是否能对风险评估中的风险。清洁程序一定要有对风险评估中列出的各项参数、最难清洗部位、清洁剂、完整可操作性强的清洁方法。

针对清洁目标物建立相应的分析方法, 并验证。

建立取样程序并验证。取样程序一般包括淋洗法取样、擦拭法取样, 对其进行验证, 计算各取样方法的回收率。取样回收率要求:淋洗法取样, 回收率≥95%;擦拭法取样, 回收率≥50%, 回收率的RSD≤20%。

2 验证的实施

准备完成后, 进入了验证的实施阶段, 先做好验证方案, 按其计划的内容逐步进行验证操作, 得出结论后, 对结论总结形成验证报告。

2.1 验证方案的内容

验证方案应至少包括:封面、验证方案起草审核审批表及修订历史记录、目录、正文。正文应包括但不限于如下内容。

验证目的;系统描述;验证范围;验证小组及职责;相关文件、SOI、SOP符合性确认;实验项目与可接受标准;验证实施方案 (使用仪器、仪表、试剂, 实施步骤) ;验证进度计划;数据分析要求;偏差分析要求;验证小结要求。

附录 (仪器、仪表校验证书, 危险品易燃易爆品使用注意事项;验证原始记录格式等) 。

2.2 培训

验证方案批准后, 验证小组长对验证成员进行培训, 所有操作人员都应参加与其相关的验证方案内容的培训, 该培训应有培训记录并作为验证文件的一部分。对验证项目培训包含两方面。

2.2.1 验证方案的培训

授课人针对培训内容进行现场提问检查培训效果, 并将提问提纲及答案归档备案。

2.2.2 现场操作的培训

以观察实际操作的方法考核培训效果, 授课人评判是否合格。

具体培训内容要求:培训实施部门和授课人应根据需求和岗位技能要求以及参培人知识技能水平确定具体的培训内容的深度, 不仅要包括操作步骤, 还应包括技术理论、工作原理等。授课人在实施培训前应确定培训目标, 培训结束后进行培训效果评估判断是否达到培训目的, 并填写培训总结表。

2.3 现场实施

对所有参与人员培训后, 验证小组组长要监督和参与整个验证的实施, 对关键的最差条件、关键步骤一定要在现场, 并尽最大限度的要求更多的人员参与。

2.4 验证报告

验证报告中至少包括:封面、验证报告起草审核审批表及修订历史记录、目录、正文。正文应包括但不限于如下内容:验证目的;系统描述;验证范围;实验项目与可接受标准;验证小组及职责;验证实施情况;相关文件、SOI、SOP符合性确认;数据分析 (包括风险是否降低了的分析) ;偏差分析及措施;验证结论;再验证周期;附录。

3 结语

验证过程中发生偏差或变更都要及时记录, 并按照相关要求进行评估对验证的影响, 并且一定要被批准后, 才能继续进行验证, 在此不再赘述。

清洁验证是防止污染及交叉污染的一个很有效的手段, 各国的法规和指南对此都有相关的规定。公司在制定验证主计划时, 一定要注意将设备列全。原则就是与产品接触的必须做清洁验证, 不接触的则不用清洁验证。同时注意在操作之前一定要对人员进行培训, 操作过程中要实时监控。

因为药品的生产设备千差万别, 由于篇幅的限制, 不可能在此一一详述, 本文对于发酵原料药的清洁验证程序是适用的, 但对其他设备清洁程序也是很好的参考。

在做验证时, 一定要融入自己的想法, 说出我是怎么想的, 为什么这样想, 依据是什么, 通过阐述我对问题的理解和解决方案来说服检查官接受我的意见, 为药品清洁验证的效果和药品的质量提供保证。

参考文献

[1]国家食品药品监督管理局药品认证管理中心.药品GMP指南·原料药分册[S] (2011) , 北京:中国医药科技出版社, 229-237.

[2]国家食品药品监督管理局.药品生产质量管理规范[S] (2010年修订) .

[3]EU GMP附录15:确认与验证[S].

[4]FDA清洁验证指南 (7/93) [S].Validation of cleaning processes (7/93) GUIDE TO INSPECTIONS VALIDATION OF CLEANING PROCESSES.

[5]APIC活性药物成分清洁验证指南 (2000) [S].Guidance on aspects of cleaning validation in active pharmaceutical ingredient Plants December 2000

[6]PDA技术报告[R]. (29, 49) .TR 29 Points to consider for cleaning validation TR 49 Points to consider for biotechnology cleaning validation.

[7]国家食品药品监督管理局药品安全监督司和药品认证管理中心.药品生产验证指南 (2003版) [S].北京:化学工业出版社, 2003.

[8]何国强, 陈跃武, 马义岭, 等.制药工艺验证实施手册 (2012) [S].北京:化学工业出版社, 230-256.

验证的程序 篇2

HACCP验证程序

1.目的

评价HACCP计划的有效性和符合性,满足食品安全控制和相关法律、法规要求,使食品安全体系有效地运行并适应各种条件变化的需要,提高其置信水平。2.范围

本程序适用于食品安全管理体系建立、运行和保持的所有阶段。3.职责

3.1 食品安全小组组长负责组织实施HACCP计划的验证活动。4.工作程序 4.1 首次确认

新制订的HACCP计划、产品说明、工艺流程图、危害分析、CCP的确定、以及HACCP验证要求等在发布实施前由食品安全小组进行首次确认,目的是证实HACCP计划的所有要素都建立在科学的基础之上。4.2 CCP验证

4.2.1 相关部门及责任人按照HACCP计划表规定的验证要求对CCP点进行验证; 4.2.2 相关部门及责任人按照HACCP计划表要求采取纠偏措施、做出相应的处理及记录;

4.2.3 由食品安全小组组长组织人员定期针对CCP点发起针对性的取样和检测,取样和检测的频率要求一年不少于2次;

4.2.4 食品安全小组每年2次对CCP点的偏离、纠偏情况进行回顾评估,根据评估情况修订HACCP计划;

4.2.5 CCP点的监视测量设备严格按照既定的检定计划进行检定,食品安全安全小组长每年2次对检定计划的执行情况进行复核。

4.3 单项验证

食品安全小组负责按照策划并进行单项验证,包括: 4.3.1 危害分析的输入的确认、更新;

4.3.2 前提方案和操作性前提方案的有效性的验证; 4.3.3 对基础设施和维护方案的有效性作出评价;

更多免费资料下载请进:http://

好好学习社区

德信诚培训网

4.3.4 其它相关程序实施的有效性验证记录 4.4 体系验证

4.4.1 内部审核和管理评审

4.4.1.1 食品安全小组通过内部审核负责组织和实施内部验证,每年一次。4.4.1.2 公司每年按照管理评审程序的要求对HACCP体系进行回顾,对体系的有效性进行评价。

4.4.2 当发生以下变化时,食品安全小组要对HACCP计划重新验证。

4.4.2.1 原料发生变化; 4.4.2.2 产品和工艺有了变化; 4.4.2.3 经常出现对关键限的偏离;

4.4.2.4 在对生产过程的观察中发现了新的问题; 4.4.2.5 销售方式和消费者发生变化; 4.4.2.6 产品回收计划启动时;

4.4.2.7 新的危害或新的控制技术或相关法律法规发生变化时; 4.4.2.8 当发生其它变化时。

4.4.3 验证内容一般情况下,应包括(但不限于):

4.4.3.1 对危害进行重新评估;

4.4.3.2 对CCP的设定和CL值的确定进行再确认;

4.4.3.3 对HACCP体系的所有记录进行审核、审查,尤其是CCP监控和纠偏的所有记录进行审核和检查;

4.4.3.4 对控制CL的方法和监控仪器进行再确认,以保证所控制的CL值确在范围之内;

4.4.3.5 收集并分析客户和有关部门对产品质量和安全卫生方面的信息;

4.5 产品质量的第三方验证

终产品应按照相应国家标准或行业标准等要求进行第三方检验以评价HACCP体系的有效性。

更多免费资料下载请进:http://

验证的程序 篇3

基于演绎推理的形式验证是程序验证的一种重要方法。其核心是由程序员书写断言描述程序的性质, 然后根据某种方式对断言进行演算产生验证条件, 最后使用某个自动定理证明器来证明验证条件。该方法的程序验证原型系统非常多,但是到目前为止还没有可供工业界使用的产品问世。其主要原因是验证原型系统的能力受限于自动定理证明器的能力。 在研究程序验证的过程中,必须考虑如何提高自动定理证明技术,同时也应该研究如何减少对自动定理证明器的依赖。

本实验室设计并且实现了一个源码级验证工具 ——面向Pointer C的程序验证器原型(简称原型系统)[1,2,3,4]。原型系统对Pointer C语言程序进行自动验证,先对程序进行形状分析生成形状图,然后根据程序员书写的前后条件以及循环不变式通过最强后条件演算方式生成验证条件,最后交给自动定理证明Z3[5]证明。本文研究的主要内容是,在引入自定义谓词增强断言语言的表达能力的同时,怎样减轻因此产生的自动定理证明器的负担。

原有的原型系统中由于断言语言能力的局限, 很多易变数据结构的性质无法简明准确的表达。为此,原型系统引入自定义递归谓词来描述这些比较复杂的程序性质。程序员在写代码的过程中有时会用到递归谓词的归纳性质。但是这样做带来的问题是,Z3在证明验证条件的过程中无法发现这些归纳性质,从而造成验证条件证明失败。

为了自动定理证明器能顺利完成验证条件的证明,原型系统由程序员提供自定义谓词之间的归纳性质定理来帮助自动定理证明器证明。同时由于性质定理是由程序员提供的,其正确性无法保证。本文给出一种先对性质定理本身进行具体分析然后再结合结构归纳的方法,实现了性质定理的自动证明。

本文接下来的内容安排如下,在第1节里介绍Pointer C程序验证器原型系统中断言语言的设计以及为什么需要引入自定义谓词;第2节给出程序员需要提供性质定理的原因;第3节详细阐述如何具体实现性质定理的自动证明;第4节简单介绍当前原型系统的组成以及可以通过的验证实例;第5节的主要内容则是全文总结以及相关工作的比较。

1程序断言语言设计

验证系统原型的核心是程序断言语言的设计, 其主要验证对象是操作易变数据结构的指针程序, 而易变数据结构的特点是递归性。为了准确用断言表达易变数据的性质,直观的方法就是引入谓词。 引入谓词有两种机制,一种是系统内部建立固定谓词让程序员使用,但是这种不满足多变的程序性质和复杂的数据结构;另一种是由程序员自己定义谓词来满足程序性质多变的情况,这也符合自动定理器的功能在不断扩展的事实。本文中采用的就是自定义谓词的机制。

1.1自定义谓词

自定义谓词是程序员自己提供的用以描述程序的性质的谓词,最常见是递归定义的谓词,也称归纳谓词。其详细文法可以参考Pointer C的程序验证器原型相关的文献[1,2,3,4]。

例如有结构体定义为:

typedef struct node{int data; Node* l; Node*r;}Node;

现在定义一棵二叉排序树(Binary Sort Tree),它提供性质定理的原因;第3节详细阐述如何具体实现性质定理的自动证明;第4节简单介绍当前原型系统的组成以及可以通过的验证实例;第5节的主要内容则是全文总结以及相关工作的比较。需要三个归纳谓词一起定义,其形式为:

符号:=的左边是谓词的名字以及谓词的参数, :=的右边是谓词的定义。谓词gt表示对于指针p来说, p指向空或者p指向一棵二叉树,且x的数值大于这棵树上所有节点的data域的数值。此时我们发现归纳谓词中的指针p不再是指向一个单独的存储单元,而是抽象成为了一棵二叉树。p可以为空树,也可以有左子树和右子树。这是由归纳谓词的定义决定的, 谓词体右边出现的同名谓词可以继续按照谓词的定义展开。所以BST的含义是:p可以为空树;当p不为NULL时,该树的上所有父节点的数据域data值小于右子树根节点的data值大于左子树根节点的data值。

1.2自定义谓词在程序验证中的作用

自定义谓词除了能够定义复杂的数据结构性质之外,还可以根据程序的实际特点定义指针之间的关系,只有灵活应用自定义谓词,才能正确书写正确的函数前后条件和循环不变式。现在用二叉排序树删除根节点的函数(图1)来具体阐述这个问题。函数的谓词定义为:

谓词(1),(2),(3)一起定义了一棵二叉排序树, 而谓词(4)则表示p指向的二叉树上所有的节点的data值都小于q指向的树 上所有节 点的数据 。 而BST_seg(p,q)则表示从p指针到q指针之间的树段上所有数据的性质。

这些谓词的定义都是原型系统验证二叉排序树 (非空树)根节点函数需要的。二叉排序树删除了根节点之后,还需要保持该数据结构是一棵二叉排序树,所以函数在while循环语句中寻找中序前驱,然后将它的值替换根点,最后删除这个中序节点。所以这个函数的性质的前条件是p!=NULL BST(p), 它的后条件是BST(p)。同时在循环语句中,指针s在该树的左子树上向右前进直至找到中序前驱,所以它的循环不变式是BST(p->r) lt_all(s,p->r) lt(q->data,s) BST_seg(p->l,q) BST(s) ,表明了它在循环语句执行的过程中程序代码一定会满足的性质。

2程序员提供的性质定理

由上文可以看出,自定义谓词为程序验证提供了便利,基于原有的谓词文法我们已经可以方便写出函数的前后条件以及循环不变式。但是新的问题诞生了,前后条件以及循环不变式演算完毕生成的验证条件交给Z3时,自动定理证明器无法证明结果。 而发生这个情况的原因是自动定理证明器Z3没有推导谓词之间的归纳性质的能力。

虽然Z3无法发现归纳谓词之间的归纳性质,但是程序员自己可以给出归纳性质的定理辅助Z3证明。 对于图1的二叉树根节点删除函数来说,提供几个性质定理,自动定理证明器就可以顺利进行验证条件的证明。这些性质定理如下:

二叉排序树删除根节点函数的循环不变形状图为:

图2中形状不变图表示循环语句中程序维持的形状。现在以性质定理(c)来说一下,为什么验证条件的证明需要它们。当BST_seg(p,q)的展开情况不为不动 点的时候 , 是基于p - > r上的谓词 性质B S T _ s e g ( p - > r , q ) , 将其他谓 词的性质 按照p - > r指向节点定义序列段的左边加入该谓词,得到BST_seg(p,q)。

根据图2的循环不变图,我们可以看图1函数循环体里的赋值语句{q= s; s = s->r; }中看出s从根节点到右子树前进方向,已经遍历过的节点序列的性质和当前指针指向的节点性质,再加上尚未遍历的节点性质综合起来才能证明循环出口的验证条件。也许就是说B S T _ s e g ( p - > l , q ) 可以扩大 到BST_seg(p->l,q->r),正是性质定理(c)表达的意思。

这个分析过程,实际上就给程序员提供了一种如何书写性质定理的思路。程序员在写代码的过程中,清楚谓词在形状图上的含义,也清楚自己利用了谓词上哪些归纳性质。比如在该例子中,程序员知道二叉树删除根节点后的中序节点就是该树左子树上最底层最右边的点,所以并没有直接将这个节点替换根节点,而是利用它的值是左子树上所有节点的最大值这个归纳性质。程序员将这个性质交给Z3作为推导的条件,就可以证明循环出口的验证条件。同时,程序员也可以对形状上各个节点附带的谓词性质进行分析,就能很容易地发现验证条件的证明缺少哪些性质定理。

3性质定理的自动证明

一般情况下,定理证明不存在自动发现归纳证明步骤的通用算法。但是对于原型系统的性质定理来说,出现的参数变量个数少,指针参数的递归结构明确而且形状固定,可以通过对定理各个组成部分的分析得到归纳证明的方法。本文提供一种自动证明性质定理的分析方法,并且按照这种方法在原型系统中实现了性质定理的自动归纳证明。

另外,本文采用的归纳方法不是自然数归纳法, 而是结构归纳法。它的基本思路是假设在某一个集合上某个命题成立,证明某个包含这个集合的集合上这个命题成立。接下来详细介绍这种方法的思路和具体实现过程中的步骤。

3.1证明思路

该方法的基本思路分为三个步骤,最后一步是归纳证明,前两步是分析性质定理的结构。本节会根据第2节二叉排序删除根节点函数的谓词和性质定理具体分析证明过程。

第一步,分析谓词间的依赖关系与谓词的归纳方式。谓词的依赖关系就是指谓词是基于哪些谓词定义,谓词lt的定义谓词不依赖其它谓词,谓词 ( 4 ) l t _ a l l依赖谓词 ( 2 ) l t 。同时也很容易得到谓词 (5)BST_seg依赖谓词谓词(3)BST、谓词(2)lt和谓词 (1)gt。而谓词的归纳方式在静态检查谓词时就已经完成。它从谓词参数的定义出发,比如谓词lt和gt都只有一个指针变量,所以按照二叉树的结构归纳。 而谓词lt_all有两个指针变量,但是它的谓词体中, 只有第一个指针的路径有变化,说明此谓词按照第一个指针变元归纳,并且归纳的方式是按照二叉树的结构。同理,我们可以得到谓词BST_seg的归纳变元也是第一个指针,但是他的归纳方式不再是按二叉树的结构,而是只按照节点的右子树路径r指针进行归纳。

第二步,利用性质定理(引理)间的依赖关系。 原则上来说,定理应该是按照各个谓词的定义就可以独立证明,比如定理(a)、(b)。实际上,证明某一个相对复杂的定理可以将其他的引理作为前提条件, 这样可以减少复杂定理的证明步骤。比如引理(e) 依赖于引理(a),没有引理(a),它要进行两次归纳证明。确定引理之间的依赖关系没有像谓词之间依赖关系那样直观,几乎没有明确的办法。一种简单的方法是,证明任意一条定理时,都将其他的定理作为前提条件。

第三步,按照第一步的分析出来的归纳变元跟归纳方式对性质定理进行证明。其具体的操作分为3小步:

1)按照第一步分析得到的归纳变元和归纳方式进行归纳基始证明。证明失败原型系统报错,退出程序验证;

2)按照第一步分析得到的归纳变元和归纳方式形成归纳假设;

3)将该引理外的其他引理和上一小步的归纳假设都作为前提条件跟引理一起交给自动定理证明器证明。证明失败原型系统报错。

3.2性质定理的自动证明过程

性质定理的抽象语法定义为其中P的形式为Q的格。下面我们以定理(d)

为例介绍如何在原型系统中实现性质定理的自动证明。

第一步,检查P和Q的归纳变元,决定是否需要归纳证明。系统原型在进行性质定理证明之前,会对每个谓词进行检查得到它们的归纳变元。如何寻找归纳变元第2节中有介绍。这样我们得到P的归纳变元集合A与Q的归纳变元集合B,A={a1,a2..ah}, B = { b1, b2. . b1} ,其中ai和bj都是指针路径(格式为ptr->next或者ptr->l),不包括指针数据域路径(格式为ptr->next->data)。同时我们还需要P、Q的指针路径集合X和Y。显然指针路径也包含了归纳变元集合的元素,因为单个谓词的指针路径中不会都是归纳变元。对于定理(d)来说,A={m,n->r},B={m}, X={m,n,n->r},Y={m}。

此外,我们定义函数NUM(x)求解集合的元素个数。根据NUM(A)和NUM(B)的值,我们得到三种情况。P与Q都没有归纳变元,直接交给Z3证明;P与Q只有一边有归纳变元,直接证明交给Z3证明;P与Q都有归纳变元,到第二步。的左边和右边都有归纳变元,所以到第二步证明。

第二步,得到归纳变元与归纳方式。归纳变元应该是P和Q中归纳变元的交集R中的元素,但是R≠ A∩B,而是A和B的等价交集。这里等价交集的元素分两种情况,第一种是它们是同一个变量,另一种是指如果不为同一个变量时它们互为别名。别名的含义为两个指针指向同一个节点。

得到等价元素的算法如下:先定义P中的指针路径等式集合 {1,2..n},根据 ,我们可以得到若干个指针路径的等价群组{E1,E2..Em},每一个群组都应该包括一组相等的指针路径。现在我们需要知道{a1,a2,a3..ah}和{b1,b2..b1}是否有等价的元素。当它们等价时,它们的减去同样的后缀后,留下的指针前缀至少有一组同时出现在某一个Ei中。具体来说,有路径p->next->next->next和q->next->next,那么它有三组需要验证的指针前缀,是(p->next->next, q - > n e x t ) ,( p - > n e x t , q ) 和( p - > n e x t - > n e x t - > n e x t ,q->next->next)。指针路径p->next和q->l不可能等价, 因为p和q不是一种结构体指针。

得到归纳变元之后,我们要寻找归纳方式。按照之前的内容介绍,每个谓词的归纳方式都不同。 我们按照归纳方式最有限制的谓词来,归纳方式最有限制就是二叉树的不动点限制最多,或者归纳路径的数目最少。当然我们可能有多种不同的最有限制的归纳方式,我们就一一尝试,如果每一个证明结果都是错误,我们就对性质定理报错。根据以上方法,很容易得定理(d)的归纳变元是m,归纳方式是m->r。

第三步,证明归纳基始。这个过程就是按照谓词的不动点的定义化简性质定理,然后交给Z3证明。 化简得方式就是将不动点的定义直接合取P。定理(d)的归纳基始:容易得证。

第四步,归纳假设的生成。我们按照第二步得到的归纳方式,将性质定理里的归纳变元替换为归纳路径就是归纳假设。有几种归纳路径,就生成几个归纳假设公式。定理(d)只有一个归纳路径,所以归纳假设为:

第五步,将归纳假设,归纳基始,所有谓词定义和其他性质定理作为条件,将性质定理本身交给自动定理器证明。如果证明结果如果为false,原型系统退出。

4原型系统简介

研究小组设计并且实现了面向Pointer C语言的的程序验证原型系统(简称原型系统)。它的基本流程为以下三个步骤:

1)预处理阶段(编译器前端)。这个阶段处理Pointer C语言,包括词法分析,语法分析和类型检查。具体的过程是,对程序员的源程序(包括编程语言跟断言语言)进行词法分析和语法分析,生成符号表和抽象语法树AST。同时还要进行类型检查,类型检查类似于C语言。

2)程序分析阶段(形状系统):遍历(1)生成的程序的语法树AST,根据形状图逻辑的演算规则生成各个程序点的形状图,还要进行形状检查和得到循环不变图。

3)程序验证阶段(验证条件生成器):以函数为单位,根据程序员提供的函数的循环不变式和前后条件,按照最强后条件演算方法和专有逻辑形状图逻辑演算得到验证条件,最后将验证条件交给自动定理证明器证明。

现阶段原型系统已经可以通过以下程序的验证, 一种是不涉及易变数据结构的非指针程序,快速排序,二分查找,二叉堆(数组实现)等;另一种是涉及易变数据结构的指针程序(全部包含性质定理跟自定义归纳谓词),有序单(双)链表的插入删除,有序单(双)向链表逆置,有序单链表合并, AA树插入,平衡二叉树、二叉排序树、treap树和splay树的插入和删除。

对原有的原型系统来说中,通过验证的大多数实例都包含性质定理。系统在假设其正确的情况下对所有的实例进行程序验证,实际上这种验证结果并不可靠。而在本文的工作实现之后,现有的实例中所有的性质定理都通过了验证,之前原型系统通过的实例的正确性得到了保证。

5总结与相关工作比较

本文的内容主要是实现了当前所有包含谓词的测试用例里中性质定理的自动归纳证明。性质定理描述了自定义谓词之间的关系,它和自定义谓词一样由程序员自己提供,其目的是辅助自动定理证明器证明验证条件。自动定理证明器的局限性,使其在不提供性质定理的情况下,需要推导出归纳性质的验证条件证明失败。此外,自动定理证明器也不具备归纳证明的方法。本文通过对性质定理本身以及谓词的分析给出了一种自动证明归纳定理的方法。

近年来,还有很多其他的国内外实验室也在开发源码级的验证工具。比如,Veri Fast是一个可以验证C和Java程序的工具原型[6]。它为了提高表达程序性质的能力,允许程序员定义归纳数据类型(类似于结构体定义)及其上的递归函数,还有允许定义基于分离逻辑的谓词。递归函数跟本文归纳谓词的最大区别是,递归函数需要提供更多参数,实际表达含义可以一样。

Veri Fast和本文的验证工具还有一个区别就是, 程序中的定理证明由程序自己提供。因为这个证明过程在Veri Fast中就是一个函数。但是本文是原型系统的工作,程序员只需要根据形状图分析书写性质定理就可以了,难度相对会小不少。此外,Dafny[7]工具的最新实现[8]和本文方法的自动证明定理的方法很接近似。它和我们原型系统一样,提供性质定理,在Dafny中叫做lemma。同样对lemma进行归纳证明,不过它和我们原型系统不同的是,它作的是自然数归纳证明,并且允许多个变量归纳的情况。

还有其他一些类似于本实验原型系统的工具, 大多数验证工具都和原型系统一样,引入自定义谓词提高程序断言语言的表达能力,比如有[9,10]。但是这些工具都没有提供像本文中实现的自动证明性质定理的功能。而且这里面的某些工具,为了验证谓词归纳性质的方便性,在编程语言中限制了循环语句的使用,极大的降低了编程的灵活性。

参考文献

[1]ZHANG Zhi-tian,LI Zhao-peng,CHEN Yi-yun,et al.An Automatic Program Verifier for Pointer C:Design and Implementation[J].Journal of Computer Research and Development,2013,Vol.50(No.5):1044-1054.

[2]Zhaopeng Li,Yu Zhang,Yiyun Chen.A shape graph logic and a shape system.Journal of Computer Science and Technology.28(6):1063-1084,Nov.2013.

[3]XU Wen-yi,CHEN Yi-yun,LI Zhao-peng.Verifier Prototype for Programs with User-defined Predicates in the Assertion Language[J].Journal of Chinese Computer Systems,2013,Vol.34(No.7):1482-1486.

[4]SONG Yan-hui,LI Zhao-peng,CHEN Yi-yun.Automatic Inference of Pre and Post Shape Graphs for Pointer-type Recursive Functions[J].Journal of Chinese Computer Systems,to be published.

[5]Leonardo de Moura and Nikolaj Bjørner.Z3:An Efficient SMT Solver,Conference on Tools and Algorithms for the Construction and Analysis of Systems(TACAS),Budapest,Hungary.Vol 4963 of LNCS,pages 337–340,2008.

[6]Bart Jacobs,Jan Smans,Pieter Philippaerts,Frédéric Vogels,Willem Penninckx,and Frank Piessens.Veri Fast:A Powerful,Sound,Predictable,Fast Verifier for C and Java.In NASA Formal Methods,pages 41-55,2011.

[7]K.Rustan and M.Leino.Dafny:An Automatic Program Verifier for Functional Correctness.In LPAR-16,LNCS 6355,pages 348-370,2010.

[8]K.Rustan and M.Leino.Automating Induction with an SMT Solver.In VMCAI 2012,LNCS 7148,pages 315-331,2012.

[9]W.-N.Chin,C.David,H.H.Nguyen,and S.Qin.Automated verification of shape,size and bag properties via user-defined predicates in separation logic.Science of Computer Programming,doi:10.1016/j.scico.2010.07.004,2010.

验证的程序 篇4

为了确定分析室进行某些特定检测的能力,监控分析室的持续能力,识别分析室中的问题并制定相应的补救措施。2 范围

本程序适用于本分析室与其他实验室间进行的比对和能力验证试验;适用于实验室认可机构安排进行的能力验证试验。3 权责

3.1 实验室负责人主持比对和能力验证工作的开展,及对结果进行评价。3.2 实验室负责人制定实验室比对和能力验证实施计划。

3.3 比对和能力验证试验所涉及的本分析室岗位按照比对和能力验证试验计划要求,组织开展比对和能力验证试验。

3.4 资料管理员负责实验室比对和能力验证工作中有关资料的归档管理。4 定义

无 5 作业

5.1 比对和能力验证试验的方式

5.1.1 CNAS安排进行的比对和能力验证试验。对此类试验,本分析室均应积极主动参加,如当时确有实际困难无法参加时,必须以书面形式申请暂不参加;如果没有提出暂不参加申请或申请未被认可,不可无故拒绝参加。

5.1.2 本分析室自行组织的与外部实验室之间的比对和能力验证试验。5.1.3 实验室间比对和能力验证试验频次要求

5.1.3.1 实验室比对频次按“分析室品质管制活动计划”规定要求实施。

5.1.3.2 能力验证试验频次按“CNAS-RL02能力验证规则”和“CNAS-AL07能力验证领域

和频次表”文件要求执行实施。5.2 验证项目的选择

5.2.1 实验室认可机构下达的比对和能力验证试验计划所涉及项目。

5.2.2 本分析室自行组织的比对和能力验证试验,项目由质量、技术负责人共同商定,主要包括以下几方面内容:

 客户投诉项目; 无法溯源的仪器设备; 新开展的检测项目; 

 使用非标准检测方法的项目;

其他技术水平要求较高或有必要的检测项目。

5.3 比对和能力验证试验的组织

5.3.1 明确比对和能力验证试验的任务后,由技术负责人联系参与比对和能力验证试验的外部实验室,安排比对和能力验证试验的时间,以及核算所需实验经费。

5.3.2 技术负责人编制比对和能力验证试验工作计划。计划内容主要包括:

 比对和能力验证试验的项目;

参加比对和能力验证试验的外部实验室; 比对和能力验证试验的时间安排; 经费核算。

5.3.3 外部实验室的选择

本分析室一般优先选择以下实验室参与实验室间比对和能力验证:

 质量管理体系符合ISO/IEC 17025要求,并经有关组织认可的实验室(如通过国家实验室认可的实验室);

 实验室间比对和能力验证项目应是该实验室经过认可的项目。

5.3.4 比对和能力验证试验工作计划需经分析室负责人批准后,方可实施。5.4 比对和能力验证试验的实施

5.4.1 实验室认可机构组织的比对和能力验证试验中,实验室负责人领取样品后,将其发给分析室分析检测。

5.4.2 本站组织的比对和能力验证试验中,由实验室负责人根据计划要求准备数份同样的样品,一份作为检测任务下达给本分析室分析检测,其它分送给参加比对和能力验证试验的外部实验室委托检测。

5.4.3 比对和能力验证试验任务下达到分析室后,由实验室负责人负责组织实施。5.4.4 参加比对和能力验证试验的检验人员在接到检测任务后,应以严谨的科学态度开展工作,包括检测环境的确认,仪器设备及有关消耗品的准备,检测过程的控制和检验结果的记录等。

5.4.5 检验人员完成比对和能力验证试验任务后,以化学分析报告的形式出具检验结果,交实验室负责人或技术负责人汇总。

5.5 比对和能力验证试验的总结

5.5.1 实验室负责人对本分析室返回结果和外部实验室的检测结果(或给定的参考值)进行分析比较,写成分析报告,并将相关资料汇总后,组织分析评审会议,召集有关

人员讲评比对和能力验证试验结果,当比对结果有差异时,要求有关岗位分析可能原因,提出进一步提高检验水平的具体措施。

5.5.2 实验室负责人综合评审内容,编写比对和能力验证试验总结报告。

5.5.3 比对和能力验证试验总结报告和其它有关资料由资料管理员整理,按照《记录管制程序》的要求,归档保存。

5.6 比对和能力验证试验结果的利用 5.6.1 对可接受的比对和能力验证结果

必要时,实验室应评价方法的偏移和精密度来确定比对和能力验证结果是否具有超

出或不可接受的高的概率;同时,评估结果比对的趋势或明显的趋向,是否能发现

其可提示或潜在存在的一些问题。

5.6.2 对不可接受或离群数值的比对和能力验证结果

当实验室的比对和能力验证结果报告为离群数值时,应组织相关人员对其检测的质控系统每一个方面全面进行评估,分析原因并及时予以整改;评估过程按文件

验证的程序 篇5

软件事务内存(STM)[1,2,3]是基于软件的事务内存实现,近些年的研究[4,5,6]表明,STM不仅能有效利用现已大量投入使用的多核多处理器,而且有希望像垃圾收集器一样被广泛应用在现代编译器的开发中,为自动实现对共享资源的互斥安全访问提供运行时的支持,从而大大减轻程序员开发并发程序的负担。但STM算法通常采用乐观投机和细粒度并发的实现方式,算法思想十分精妙,可靠性难以保证。因此,研究STM并发机制的验证方法对提高并发软件的可靠性和安全性有重要意义。

Transactional Locking II(TL2)[7]是经典的基于锁的STM算法,它通过细粒度并发代码来实现事务的原子性。验证底层细粒度并发代码的正确性等价于证明它与高层抽象事务原子块间的上下文精化关系[8],即在任意的调用环境下底层代码产生的行为不会比原子事务的行为多。但该算法思想巧妙,验证难度很大。据作者所知,目前还没有在代码级上对TL2事务底层实现的验证工作。

本文基于TL2算法给出了一个典型的读写事务T(3行)对应的底层细粒度并发代码P(28行),使用基于依赖保证的程序模拟技术证明代码P是对事务T的一个精化实现,即在代码级上验证读写事务底层实现的正确性。

本文的主要贡献如下:应用程序精化技术完成了TL2事务的底层实现在代码级的验证,总结出了TL2算法中具体状态和抽象状态对应关系满足的不变式和基于时间戳的读集检验策略满足的不变式,为完成整个TL2算法在代码级的验证奠定了基础。

1 软件事务内存和TL2算法

STM是模拟数据库事务的并发控制机制来控制并行计算时的共享内存访问的一种技术,它是锁的一种替代机制。在STM中,一个事务指的是一段读、写共享内存的代码。这些读写操作在逻辑上是一个独立的单元,其中间状态对于其它的事务而言,是不可见的。与现在许多并发应用程序广泛使用的锁机制不同,STM通常采用一种乐观投机的并发控制方式:一个线程独立完成对共享内存的修改,完全忽略可能存在的其它线程,线程在日志中记录对共享内存的每一个投机的读写动作,然后根据日志中的记录进行共享内存的一致性检查,如果没有冲突就提交事务并更新共享内存,否则根据日志中的记录进行回滚,并重新开始一个新的事务。这种乐观投机的策略往往可以增加系统的并发度:任何线程无需等待一个资源,多个线程可以并发而且安全地修改同一共享数据结构的多个部分,从而实现共享数据结构的细粒度同步访问控制。

STM机制提供一些接口,主要包括以下几个重要接口:STM_begin()表示开始一个事务并完成对事务的初始化操作;STM_read(x)用于读共享变量x并更新读集;STM_write(x, buffer)将新的值写入写集buffer; STM_validate()用于冲突检测; STM_c o m m i t ( ) 用于提交 事务并更 新共享内 存 ;STM_abort()用于事务失败时进行回滚。图1左边表示“STM_atom{y=x+3}”,表示一个被原子执行的事务,而右边则是调用STM机制提供的接口进行程序变换后得到的运行时程序。

TL2和多数STM算法思想类似,采用“投机→检查→提交或回滚”的方式实现对共享数据的同步访问控制,它通过维护一个全局时间戳来完成对共享数据的一致性检查,并为每个事务存储单元额外添加锁和版本号两个域,事务在提交时会根据最新的全局时间戳来更新存储单元的版本号。因而事务可通过比较存储单元的版本号与全局时间戳之间的关系来判断共享存储是否已过时,是否需要回滚重新读取。事务对共享存储单元进行写入操作时,不是直接写入,而是写在一个缓冲区中,最后提交前才获取该单元的锁,最后提交时写入并释放锁。

图2是一个支持共享存储读写访问的原子事务。该事务中x和y是整型共享变量(事务共享存储),它们会被多个并发执行的事务同时访问。tmp是事务内部的局部整型变量,只能被当前线程访问。该事务提供给 程序员的 抽象行为 是原子地 执行STM_atom{}内的三行代码。

图4给出上述事务基于TL2算法的底层实现,可认为它是TL2算法对上述事务编译的目标代码。其中每个共享变量会被翻译成为一个结构体(如图3所示)。该结构体中,data保存与高层对应的值;ver是版本号;lk是底层共享结构体的保护锁,锁空闲时为0,被线程id获取后为id。代码中gt是全局时间戳,是一个可被多个并发执行的事务同时访问的整型共享变量。代码中的NAN类似C语言中的NAN,意思是“非数(Not a Number)”,在验证时表示某个变量的值是未定义的。

图4中,函数increment_and_fetch(>)原子地把全局时间戳gt加1并返回gt的新值。函数trylock(&x)非阻塞地获取结构体x的锁:如果锁空闲,便获取锁并返回0;如果锁已被占用,直接返回1。函数unlock(&x)释放结构体x的锁。

程序用fail作为指示标志,用来表示事务是否成功提交。当fail为1时,表示失败;当fail为0时,表示成功。程序主干部分由while循环构成。如果事务未成功提交,则fail为1,就继续执行循环体直至事务成功提交。

底层细粒度代码执行过程如下:首先将fail置为0(第3行)并进行STM_begin操作(第4~5行),读取全局时间戳并初始化各变量。之后对变量x进行投机读操作(STM_read):首先检查x的锁是否空闲(第6行),之后读取x的值保存在tmp中(第8行),再检查锁是否空闲、版本号是否小于等于rv(第9行)。读前和读后的这两次检查就保证了从开始执行事务至今,x未被其他线程更改。随后进行STM_write操作,将值存在缓冲区中(第10~11行)。之后尝试获取x与y的锁(第12~15行)。之后改变全局时间戳并且把这个新的全局时间戳记录在一个线程局部变量wv中(第17行)。在这以后执行STM_validate操作(第18行),再次检查x的版本号是否小于等于rv。如果有不符,则将fail置为1。这就保证了从开始执行事务至今,x的值未被修改。最后进行提交(STM_commit,第21~22行):把缓冲区内的值写入x和y,用wv更新版本号,并释放锁。整个过程存在很多检查,任意一次检查失败就把fail置为1并进行回滚。

验证TL2实现时,通常把实现事务的底层代码的每一步对应到高层事务代码的某一步上,即找到底层代码每执行一步时高层代码执行到的对应位置(高层代码可以不执行,也可以执行若干步),本文把这个对应位置称作“线性化点”。找到这些线性化点后,证明两层程序状态满足某个对应关系,而这个关系体现了两层程序状态的一致性,进而体现了实现的正确性。但验证难度很大。

首先,验证时很难确定底层代码每执行一步时高层代码执行到的对应位置。比如底层代码改变全局时间戳之后,就要进行STM_validate和STM_commit操作。大多数人直观地认为再次检查x版本号是否小于等于rv后的那个程序点或者提交过程中的某个子步是线性化点,和高层事务执行后的那个程序点对应。但是因为检查x版本号后,x就可被其他线程修改,这样高层执行事务代码后,高层x和底层x的值就不一致。这样就不能建立一个清晰的对应关系。另外线性化点也不能“简单地”放在再次检查x版本号这步之前,因为在检查完成后才知道是否可以提交,才能确定这个到底是不是线性化点。

另外验证时要指定在线性化点上高层程序状态和底层程序状态的对应关系。但是TL2算法实现的代码的粒度很细,因此这个对应关系非常微妙。大多数人很容易直观地以为这个对应关系可以表述为“如果一个共享变量的锁空闲,那么该共享变量在高层程序状态上的值和在底层程序状态上的值相等”。但这个对应关系无法描述如下情况:如果最后一次检查x的版本号后要进行回滚,那么即使已经获取了一个共享变量的锁,它在高层程序状态上的值和在底层程序状态上的值依然相等。

2 TL2事务的精化验证

如果要对STM的实现进行验证,那么就必须对其正确性有一个定义。目前有许多对STM正确性的定义,比如可线性化(linearizability)[9]、可串行化(serializability)[10]、不透明度(opacity)[11]以及其他几种变形。这些都是针对事务执行历史定义的,很难直接应用在STM代码级的验证上。最近Attiya等人使用上下文精化关系来刻画STM实现的正确性[8]。基于这个定义,如果一个原子事务的实现是正确的,那么该原子事务和实现这个事务的底层代码之间具有精化关系,即底层实现事务的代码在执行过程中表现出来的可观测行为不比原有事务在执行过程中表现出的可观测行为多。这个定义很直观,通俗易懂,可以在代码层面对事务内存的实现进行验证,所以本文采用这个定义来描述TL2实现的正确性。

图4实现事务的底层代码 (参见下页)

验证两个程序之间是否满足上下文精化关系可采用Liang等人提出的基于依赖保证的模拟技术(RGSim)[12]。这个技术可用于模块化验证两个并发程序之间的精化关系。验证时需要指定两个程序在执行时的依赖保证条件以及两个程序在执行时程序状态要满足的不变式。两个程序状态始终要满足这个不变式,这个不变式反映了两个程序状态之间的对应关系,也就体现了两个程序状态之间的一致性,进而体现了实现的正确性。验证精化关系时,要确定高层和底层代码的对应点(即线性化点),验证不变式在这些对应点上始终成立;同时要验证在程序执行过程中,每个指令的前后条件都在环境(由依赖条件指定)中始终成立。Liang等人提出的基于依赖

保证的向前向后模拟技术[13]扩展了RGSim,通过证明并发数据结构提供的并发操作满足上下文精化关系,来证明并发数据结构的可线性化性。采用这项技术验证程序A是程序B的精化实现时,需要模拟地执行A和B。A每执行一步,就要找B的对应点(即线性化点)。如果对应点确定,那么B执行到对应点,即B执行线性化操作到达线性化点。如果对应点不确定,此时就遇到了“疑似的”对应点,那么在此做一个尝试性的线性化操作,将线性化后的程序结果与未线性化的程序结果均记录在验证时使用的程序状态中。以后检查中,如果发现某个条件不满足,此前的线性化结果要被舍弃,那么就在程序状态中舍弃线性化后的结果。如果发现条件都满足,此前的线性化结果应该被保留,那么就在程序状态中舍弃没有线性化的结果。本文验证时就采用RGSim和基于依赖保证的向前向后模拟技术。

对于线性化点确定的代码,RGSim验证精化关系非常有效。为了降低验证的复杂性,本文在高层和底层中加入一个中间层,将高层代码转换为中间层代码,然后验证高层代码和中间层代码的精化关系,之后再验证中间层代码和底层代码的精化关系。在验证高层和中间层代码的精化关系时,因为高层和中间层的线性化点确定,所以采用RGSim。

首先将高层代码转换为中间层代码,如图5所示。表示中间层共享变量的结构体和表示底层共享变量的结构体类似,但只有data和lk两个域。函数lock(&x)获取结构体x的锁,如果这个锁被其他线程占用,函数便阻塞直至锁被本线程获取。函数unlock(&x)释放结构体x的锁。图5中的尖括号“< >”将若干语句包含在一起组成一条原子指令。中间层先原子地执行如下操作:获取x和y的锁并执行原始事务。之后逐一释放x和y的锁。

验证高层和中间层之间的精化关系时,依赖保证条件可根据操作语义得出,此处省略。用到的不变式是

此不变式中,对高层和中间层都存在的变量,用下标进行区别,H表示高层,M表示中间层。此不变式体现了高层变量和中间层变量应始终保持的一致性,即x与y两个共享变量在高层和中间层中的值始终相等,且高层和中间层对应的局部变量tmp的值始终相等。高层和中间层的对应点是:当中间层线程执行第一个原子操作时,高层线程执行事务;当中间层线程执行余下操作时,高层线程不执行任何操作。经过推导,高层和中间层的精化关系便可得到验证。

验证中间层和底层的精化关系时,因为线性化点不确定,采用基于依赖保证的向前向后模拟技术。首先考虑中间层代码和底层代码在执行时的线性化点:底层代码在用increment_and_fetch函数改变全局时间戳之后,中间层代码尝试性地进行线性化。在提交之前,底层代码要对读取的共享变量x进行再次检查。如果发现没有问题,就进行提交,同时保留中间层线性化后的结果,舍弃中间层没有线性化的结果;如果发现有问题,那么就需回滚,同时保留中间层没有线性化的结果,舍弃中间层线性化后的结果。

在验证中间层和底层的精化关系时,依赖保证条件可以根据操作语义得出,此处不再赘述。用到的不变式反映了算法的本质,是验证的关键,所以下文主要对不变式进行阐述。表示不变式时,对中间层和底层都存在的变量,用下标进行区别,M表示中间层,L表示底层。

首先阐述的是中间层和底层程序状态的对应关系满足的不变式,即TL2算法中具体状态与抽象状态对应关系满足的不变式。该不变式为

该不变式是说,如果一个共享变量在中间层或底层的锁空闲,那么它在中间层和底层的值对应相等。该不变式保证了中间层和底层共享变量的一致性。同时它也体现了引入中间层的必要性。为了看清这个问题,假设没有中间层,那么就需要讨论高层和底层状态的对应关系满足的不变式,这个不变式可以写作

假设底层代码投机执行时已获取了x和y的锁,但是在最后STM_validate检查中失败,必须回滚。回滚前,x和y的锁没有被释放,不变式的前提为假,因此不变式为真。回滚后,不变式的前提为真,要保证不变式依然成立,不变式的结论必须为真,但这个是无法推导出的。在加上中间层后,就可以解决这个问题。在中间层尝试进行线性化操作后,程序状态中有两种结果,一种是线性化后的结果,一种是没有线性化的结果。如果在STM_validate检查中失败,那么就要保留没有线性化的结果。在这个结果中,回滚前,由于不变式成立,并且中间层的锁空闲(即不变式的前提为真),所以不变式的结论为真;回滚后,不变式的前提依然为真,回滚操作不改变共享变量的data域,这就使得不变式的结论依然为真,所以不变式依然为真。因此加入中间层后,这个不变式就能恒成立。

另外一个重要的不变式是基于时间戳的读集检验策略满足的不变式,这个不变式为

它的意思是如果1)共享变量x已经通过了初次检查并读取了x的值,并且2)x的锁在中间层或底层空闲,并且3)x的版本号不大于rv,那么读取x时保存值的局部变量tmp和对应的底层共享变量x的值相等。在读取x前的那次检查可使得条件1)成立,读取x后的那次检查可使得条件2)和3)成立。因为共享变量的版本号单调增加,所以只要在任意程序点条件3)成立,那么在这个程序点之前它始终成立。因此如果读取x之后的那次检查没问题,那么在读取x前检查锁的时刻以及读取x的时刻,条件3)都成立。这个就可以保证读取的x的值正确。类似地,也可以推导出在STM_validate时,如果通过了检查,读取的x的值正确。

最后还有一个不变式比较重要,这个不变式是

它是说线程局部变量rv和共享变量的版本号都始终小于或等于全局时间戳,这反映了全局时间戳单调增加的性质。在验证时这个不变式是一个重要的辅助。

采用基于依赖保证的向前向后模拟技术进行验证时,根据操作语义推导出每个语句在执行过程中的前后条件,同时验证这些前后条件在环境(由依赖条件指定(中始终保持。推导后便验证了中间层和底层的精化关系。

在验证高层和中间层的精化关系以及中间层和底层的精化关系之后,根据精化关系的定义,便可知高层和底层之间也有精化关系。这样便在代码级上完成了对这个TL2读写事务底层实现的精化验证。

3 相关工作

已有的许多工作[14,15,16,17]使用模型检查(modelchecking)验证STM算法,但为了减少状态数量并简化验证,他们的抽象模型通常将STM算法的若干步合为一个原子指令,这样就忽略了真实的STM算法在线程交叉执行时的微妙状态。而本文在代码级上对TL2事务的底层实现进行验证,并关注了这些微妙状态,同时还给出了这些状态对应关系满足的不变式。

Tasiran[18]对STM算法在代码级上进行了精化验证,但所验证的STM算法的策略与TL2的策略不同,所以所用方法不适用于TL2的验证。Mohsen等人[19]基于模拟技术提出了验证STM的框架,但只支持向前模拟,不支持向前向后模拟,也无法验证TL2事务的实现。而本文采用向前向后模拟技术验证了TL2事务的底层实现。

4 结束语

本文用TL2算法实现的代码具有代表性,体现了TL2算法的本质,帮助人们对TL2算法有更深入的理解。

引入中间层后,本文使用基于依赖保证的向前模拟技术(RGSim)验证了高层和中间层的精化关系,再使用基于依赖保证的向前向后模拟技术验证了中间层和底层的精化关系。这样便验证了高层和底层的精化关系,完成了对一个典型读写事务基于TL2算法的底层实现在代码级的验证工作。

验证的程序 篇6

1 主要功能

表单验证对于任何一个编程者都不陌生, 此类程序主要应用在用户注册、信息采集、网络报名等程序流程中, 对于表单严整不严格的程序会给后期数据加工、数据处理工作带来很大的麻烦, 所以在做表单验证程序的时候, 需要尽量详细地考虑存在的相关问题。

常用的表单验证主要包括是否填写信息、填写信息是否规范、密码强度判断、两次密码输入是否一致、中英文数字的处理判断、出生日期格式判断、电子邮箱的验证、留言信息长度限定等功能, 最后在提交表单时出现是否确认提交的提示, 提交成功后出现提示框。

密码已经是人们生活工作中必不可少的工具, 但一个不安全的密码有又有可能会给人们造成不必要的损失。作为设计者, 如果在网页中能对用户输入的密码进行安全评估, 并显示出相应的提示信息, 那么对用户设置一个安全的密码将有很大帮助。评估方式:

(1) 如果密码少于5位, 那么就认为这是一个弱密码。

(2) 如果密码只由数字、小写字母、大写字母或其他特殊符号当中的一种组成, 则认为这是一个弱密码。

(3) 如果密码由数字、小写字母、大写字母或其他特殊符号当中的两种组成, 则认为这是一个中度安全的密码。

(4) 如果密码由数字、小写字母、大写字母或其他特殊符号当中的3种以上组成, 则认为这是一个比较安全的密码。

出生日期在数据库中存储是有一定格式要求的, 如果不是规范存储则填写的日期将无法进行处理、分析。所以出生日期需要用标准的“xxxx—xx—xx (年-月-日) 这种方式进行填写。

电子邮箱的填写能否收集用户联系方式, 这就需要用户按照规范填写, 填写时要按照电子邮箱的填写标准进行填写, 一般电子邮箱的格式为username@***.net、username@***.com.cn等, 这样就可以按照规范进行判断。

下面对验证的主要功能进行详细分析:

(1) 验证用户名是否填写, 并且填写是否规范, 用户名需要是A-Za-z0-9_。

(2) 密码和确认密码是否一致。

(3) 密码强度的评估。

(4) 检测是否为中文。

(5) 检测姓名拼音是否都为字母。

(6) 日期的格式检测。

(7) 电子邮件的格式检测。

(8) 手机号码应该全部为数字。

(9) 填写留言信息字数限制以及现有字符数显示。

(10) 提交表单后出现的确认对话框提示。

此程序在开发过程中存在的难点问题:

(1) 密码强度的评估, 弱、中、强的判断与检测。

(2) 利用正则表达式来对用户输入信息进行验证。

2 代码详解

程序主要由若干部分组成, 可以把每一部分功能都定义为一个函数模块, 下面分别介绍详细程序代码, 如图1, 图2所示。

2.1 用户标识判断

主要利用form1.name.value获取所填写的内容, 判断内容是否为空, 如果为空则出现相应提示, 并且利用form1.name.focus () ;获取当前焦点。

利用正则表达式的知识来对条件进行限制, 用户标识需要是字母或者是数字。JavaScript中的RegExp对象用于正则表达式相关的操作, 这个对象提供了一个方法test来判定某个字符串是否满足某个表达式, 返回值是true/false。

2.2 用户密码、确认密码

判断两次密码输入是否一致, 如果不一致则出现错误提示。并且利用form1.pwdok.focus () ;获取当前焦点, form1.pwdok.select () ;选中当前不相同密码。

2.3 中文姓名

判断输入的字符是否为中文, 在正则表达式中u4E00-u9FA5 (unicode码) 中表示汉字, reg0.test对输入的字符串进行检测, 如果输入的不是中文, 则出现相应提示信息。

2.4 姓名拼音

此部分对拼音进行判断, 利用for循环字符串的遍历出所有输入字符, 然后利用form1.ename.value.charAt (i) 获取每一个字符, 进行字母的判断, 如果不是大写或小写字母, 则会出现错误提示。此部分判断也可以利用正则表达式来校验, 读者可以根据相关知识认真思考一下。

2.5 出生日期

利用正则表达式来列出日期的条件, 2009-12-30为标准格式, 不符合此格式就会出现错误提示。Str.match (reg) 表示规定要匹配的模式的RegExp对象, 若没有找到任何匹配的子串, 则返回null。

2.6 电子邮件

利用正则表达式来列出电子邮件的条件, 在上一部分内容中详细分析了电子邮件的基本格式, username@***.com和username@***.com.cn两种标准格式, 不符合此格式就会出现错误提示。Str.search (reg) 方法用于检索字符串中指定的子字符串, 或检索与正则表达式相匹配的子字符串。如果没有找到任何匹配的子串, 则返回-1, 在此实例中-1表示输入的电子邮件格式有误, 不符合正则表达式的规范。

2.7 手机号码

手机号码的验证主要是判断它是否为数字, 如果输入汉字或者字符则输入错误, 此部分利用isNaN来判断当前输入的是否为数字, isNaN表示返回一个Boolean值, 指明提供的值是否是保留值NaN (不是数字) 。

2.8 留言信息

留言信息主要判断输入字符的长度, 如果超过40个字符出现错误提示。程序利用form1.liuyan.value.length来获取当前长度来判断是否超出范围, 如果超出范围则出现alert错误提示, 并且利用form1.liuyan.focus () ;获取焦点, 同时利用form1.liuyan.select () ;选中当前字符, 如图3所示。

2.9 信息提交判断

此部分代码主要使用confirm方法, confirm是Windows中的一个方法。它可以弹出一个包含“确定”与“取消”的对话框, 如果用户按下了确定, 返回true;如果按下了取消, 返回false。form1.reset () ;表示重置表单中的所有信息, 程序中/n的含义表示在JavaScript中的回车, 如图4所示。

2.1 0 计算字符

在留言信息中可以计算当前字符的数量, onkeydown和onkeyup是键盘的两个事件, 通过onkeydown="showlen (this) "和onkeyup="showlen (this) "这两个事件调用showlen () 函数, 表示每输入一个字符都会有当前的数值变化, 利用form1.contentlen.value=obj.value.length;把当前的字符显示到contentlen文本框中。

style="border-width:0;background:transparent;"表示隐藏文本框的边框。

2.1 1 密码强度

密码强度判断主要是通过以下4个函数构成, 分别是CharMode () , bitTotal () , checkStrong () , pwStrength () , 如图5所示。

2.1 1. 1 CharMode函数

CharMode () 主要是测试输入的每一个字符都是哪一类, 主要分为4类, 数字、大写、小写和特殊字符。

2.1 1. 2 modetotal函数

Modetotal函数计算出当前密码一共有多少种模式, 此部分使用了不太常用的移位操作符>>>, 它是一种“无符号”右移位操作符 (>>>) , 它使用了“零扩展”:无论正负, 都在高位插入0。移位可与等号 (>>>=) 组合使用时, 操作符左边的值会移动由右边的值指定的位数, 再将得到的结果赋回左边的变量。

2.1 1. 3 checkpwd函数

Checkpwd函数是返回密码的强度级别, 主要分为4个级别0, 1, 2和3以上, 主要利用循环方式把当前输入的密码进行按位或的运算, 分别会得出0, 1, 2和3以上。

2.1 1. 4 pwdstrong函数

pwdstrong函数是当用户放开键盘或密码输入框失去焦点时, 根据不同的级别显示不同的颜色。

通过以上JavaScript版表单验证程序的学习, 基本可以使用学习过的知识进行实例的操作, 此表单验证基本囊括了目前收集客户信息时需要验证的内容, 在以上程序讲解中, 读者可能会注意到正则表达式这个概念经常出现, 在JavaScript的表单验证中起了很重要的作用, 目前关于正则表达式出版了很多相关的书籍提供参考, 书中对验证的介绍更加详细 (包括一些复杂验证) , 此程序的介绍意在抛砖引玉, 使更多的初学者入门, 并深入学习。

3 结语

以上代码是在Internet Explore6.0、Internet Explore7.0中测试通过, 实例截图为Internet Explore6.0中运行效果。此表单验证比较简单, 此程序的学习对于初学者来说有很大的帮助, 该实例长期作为JavaScript这门课程的一个典型实例为学生进行讲授, 在一些报名系统中表单验证程序均使用此代码, 所以此实例的学习对于今后想深入学习JavaScript这门语言的读者有一定促进作用。

摘要:通过实例对表单验证程序进行详细讲解, 实例中基本包括了用户在填写表单时需要验证的信息, 每部分功能使用函数来完成, 这让初学者能够很容易接受并且理解语句段的含义, 快速地掌握JavaScript这门语言。

验证的程序 篇7

形式化方法是保证微内核操作系统正确性的重要方法。形式化验证[1]就是从数学上完备地证明系统是否实现了设计者的意图,是指用形式化方法描述程序的规范,然后通过一定的验证规则对这些形式化规范以及相关代码进行验证,判断这个程序是否依照程序规范所指示的方式执行主要包括模型检测和定理证明。定理证明[2]是将软件按照需求、设计描述为形式化系统,将需要满足的性质描述为系统中的定理,并建立推理规则,将待检测软件的各个要素与形式化系统中的变量对应起来,证明这些要素满足系统中的定理和规则。模型检测[3]是将测试对象建立状态机模型,将待检测属性用逻辑语言描述,然后用有限状态穷举的方法判定状态机模型是否满足用逻辑语言描述的待检测性质。本文主要是在UPPAAL中使用模型检测方法,对微内核操作系统程序验证方法进行探索和研究。

1 模型检测工具 UPPAAL

UPPAAL[4]是由瑞典的Uppsala大学与丹麦的Aalborg大学于1995年联合研发的一种以R.Alur和Dill提出的时间自动机作为行为模型的自动验证工具,可以用于实时系统模拟、仿真、验证,主要采用一组带有整形变量的时间自动机对实时系统的行为进行模拟,可以有效地对实时系统建模,模拟和验证,它可以验证实时系统中的可达性以及由可达性所衍生的一些性质,特别适合对实时系统的安全性和有界活性进行自动验证,从而确保了系统在实际运行中的高度正确性。

UPPAAL对系统性质的描述采用形式化描述语言CTL(timed computation tree logic)逻辑,UPPAAL中的模型检测采用的方法是状态空间的穷搜索,其自动验证器主要用于检查简单不变式,系统的安全性,可达性以及受限活性等。CTL查询语言由路径公式和状态公式组成,状态公式描述单独的状态;路径公式量化模型的路径或轨迹,可以分为可达性、安全性、活性。UPPAAL使用的规范验证语言形式如下:

Prop::=A []Expression|E<> Expression|E []Expression|A<>Expression|Expression Expression

UPPAAL使用的规范验证语言归纳见表1:

具体查询语句的含义如下,其中p、q表示某个状态性质:

(1)E<>p:表示Possibly,存在一条路径,p最终成立,E<>p为真当且仅当在时间自动机中存在一个序列S0→S1→…→Sn,使得S0是起始状态,Sn是p。

(2)A[]p: 表示Invariantly,对于所有的路径,p总是成立,A[]p等价于notE<>notp。

(3)E[]p: 表示Potentially always,存在一条路径,p总是成立。在时间自动机中,E[]p为真当且仅当存在一个序列S0→S1→…→Si→…使得p在所有状态si中得以满足。

(4)A<>p: 表示Eventually,对于所有的路径,p最终成立,A<>p等价于notE[]notp。

(5)p→q: 表示Lead to,无论何时p成立,q最终成立,p→q等价于A[](p implyA<>q)。

2 基于 UPPAAL的程序验证

2.1 验证的研究方案

模型检测[5]使用状态空间搜索的办法来全自动地检验一个有穷状态系统是否满足其设计规范。这类方法的优点在于它有全自动化的检测过程且验证速度快、效率高,并且如果一个性质不满足,它能给出这个性质不满足的理由,据此可对系统描述进行改进。

在模型检测中涉及两种形式说明语言:性质说明语言,例如CTL,用于描述系统的性质;模型描述语言,例如时间状态自动机,用于描述系统的模型。模型检测技术用于检验由模型描述语言描述的系统模型是否满足性质说明语言描述的系统性质。

因此,采用模型检测方法对程序进行验证时主要分为建模、规约、验证三步。其中,建模是采用时间状态自动机对程序进行建模分析;规约是对抽取的程序性质进行描述;验证是通过模型检测工具UPPAAL来检验在所建立的模型上,给出的系统性质是否能够得到满足。基于模型检测的验证研究方案如图1所示。

2.2 ucosII 任务管理在 UPPAAL中的模型表示

本节以微内核操作系统ucos-II[6]任务管理部分中的taskinitusers .c文件中初始化用户任务源函数代码作为实例进行分析。μcosII的任务看起来与任何C函数一样,具有一个返回类型和一个参数,只是它从不返回,任务的返回类型必须被定义成void型,任务必须是图2、图3两种结构之一:

根据所需验证代码实现的功能,通过函数调用、同步信号等形式,判断返回值情况以及函数调用是否成功,建立代码到UPPAAL模型的对应关系,对应的模型如图4、图5所示。

2.3 属性表示及验证

利用UPPAAL验证器进行属性的验证,可对如下的性质进行验证:

(1)E<>Initialize_user_tasks.Internal_error_Occurred验证Internal_error_Occurred状态是否可达。若可达则说明存在一条路径从函数的入口到达该状态,反之亦然。能够有效自动的判定,程序中的重要状态是否可达,从而验证程序编写的正确性。

(2)A []not deadlock可以验证该函数是否出现死锁。若出现死锁,则说明函数的编写有问题,不能正常的传递参数,得到正确的返回值等信息,可以根据模型,动态跟踪错误发生的位置。

验证结果如图6所示。

由验证结果可以清晰的看出,所建立的模型不会产生死锁,Internal_error_Occurred状态是可达的。根据这些属性的验证结果,当发现代码的不安全和不完善后,可以及时的进行修改,以满足代码正确性的要求。

3 结束语

在形式化验证程序正确性的领域中,模型检测以其自动化程度高、强大的时态逻辑描述能力而得到了广泛的研究与应用。模型检测基于时态逻辑,为验证对象建立状态机模型,将待检测属性用逻辑语言描述,然后用有限状态穷举的方法判定状态机模型是否满足用逻辑语言描述的待检测性质,是形式化验证的主流方法之一。本文采用模型检测方法对微内核操作系统的程序进行分析和验证,采用这种方法对程序进行验证的自动化程度高,用时间自动机对程序分析结构进行建模,形象且直观易懂,通过实验的验证结果可知,模型检测方法可以应用于微内核操作系统软件的验证,能够得到正确的验证结果,具有一定的研究和验证实用价值。

摘要:随着航天、航空工业的发展,机载嵌入式软件的可信属性验证是新一代飞机研制最关注的软件质量保障问题。形式化方法具有严密的数学基础,能够准确的对系统进行建模、描述和验证,能够在软件系统的设计初期发现潜在的错误,是保证机载软件可信性和安全性的软件正确性验证技术。形式化验证以形式化描述为基础,对所描述系统的特性进行分析和验证,以评判系统是否满足期望的性质,分为定理证明和模型检测两类。文章研究模型检测方法应用于程序形式化描述和验证的技术,提出基于模型检测的验证程序正确性的方案,并进行微内核操作系统程序分析,最后在UPPAAL中进行程序属性的验证。

上一篇:商业企业资金管理问题下一篇:井冈山革命精神