Shim 和 Polyfill 常出现的一个术语是 Shim。Shim 单词的意思是垫片,相当于在 API 和调用者之间加了一层。 理解了这个例子再来看维基百科 上的定义就容易多了: A shim is a library that transparently intercepts API calls and changes the Shim 通常是一个代码库,它能够"透明地"拦截 API 请求并修改参数,自行处理操作或者重定向。 总结:Shim 可以封装自己的 API,概念比 Polyfill 大一点,两者并不冲突。 有人也从两个单词的"软/硬"含义理解:Polyfill 填充你感受不到它的存在,而 Shim 填充则能明显地感知到。 使用场景 前面的例子是偏向解决 IE 兼容问题。
Shim 和 Polyfill 常出现的一个术语是 Shim。Shim 单词的意思是垫片,相当于在 API 和调用者之间加了一层。 理解了这个例子再来看维基百科 上的定义就容易多了: A shim is a library that transparently intercepts API calls and changes the Shim 通常是一个代码库,它能够"透明地"拦截 API 请求并修改参数,自行处理操作或者重定向。 总结:Shim 可以封装自己的 API,概念比 Polyfill 大一点,两者并不冲突。 有人也从两个单词的"软/硬"含义理解:Polyfill 填充你感受不到它的存在,而 Shim 填充则能明显地感知到。 使用场景 前面的例子是偏向解决 IE 兼容问题。
这就要用到本文的主角:Shim。Shim的本意是垫圈或垫片。理论上说,任何的计算机问题都可以新增一层逻辑来解决。Shim也是这么一个垫在应用程序和windowsAPI之间的逻辑层。 利用Shim的攻击 除了微软自带的Shim数据库以外,用户还可以给任意程序自定义Shim修复方式。这在提高兼容性的同时也引入了一些安全隐患。 因为“InjectDLL”是自定义的Shim,而沙盒上没有设置同样的Shim。 利用shim 缓存进行取证 每次执行应用程序,系统都要根据Shim数据库来检查该应用程序是否需要被Shim。而Shim数据库里有5000+记录,每次都比对会使效率变得很低。 Shim缓存使用了LRU(Leastfrequently used 最近最少使用)淘汰算法,因此最近执行过的程序会出现在Shim缓存里, 下一次运行该程序的时候就不需要比对Shim数据库。
CRI shim是什么? 计算机科学领域的任何问题都可以通过增加一个中间层来解决,我们的 CRI shim就是加了这样一层。 并且,Streaming Server 会在 CRI shim 启动时就一起启动。此外,Stream Server 这一部分具体怎么实现,完全可以由 CRI shim 的维护者自行决定。 这就很麻烦,就意味着我有 100 种这样的 CRI ,我就要写 100 个shim去集成,而且他们的功能全部都是重复的。 所以这就产生了Containerd ShimV2的这样的shim来解决这个问题。我们下回分解。
) pb.Response { return shim.Success(nil) } func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface =nil){ return shim.Error(err.Error()) } return shim.Success([]byte("Saved Student!")) =nil{ return shim.Error("getListResult failed") } return shim.Success(students) } 5.2 富查询 =nil{ return shim.Error(err.Error()) } var result,_= getHistoryListResult(it) return shim.Success = nil { return shim.Error(err.Error()) } return shim.Success(nil) } 事件设置完毕后,需要在客户端也做相应的修改
当然,除了官方正式支持的 shim 之外,任何人都可以编写自己的 shim,并让 Containerd 调用该 shim。 客户端在创建容器时可以指定使用哪个 shim,如果不指定就使用默认的 shim。 如果你想实现自己的 shim,下面是相关参考资料: (v2) shim RPC API 的详细定义[3] 实现 shim 二进制和RPC API的辅助工具[4] shim 的使用方式[5] 你只需要实现一个接口 shim 需要重点关注的是内存使用,因为每个容器都有一个 shim 进程,随着容器数量的增加,shim 的内存使用会急剧上升。 一旦连接字符串初始化完成,shim 开始监听之后,start 命令就会返回。 containerd 使用 shim start 命令返回的连接字符串,打开一个与 shim API 的连接。
这就很麻烦,就意味着我有 100 种这样的 CRI ,我就要写 100 个shim去集成,而且他们的功能全部都是重复的。 所以这就产生了Containerd ShimV2的这样的shim来解决这个问题。 我们来看一下,最大的区别在于:在这种方式下,你可以为每一个 Pod 指定一个 Shim。 因为在最开始的时候,Containerd 是直接启动了一个 Containerd Shim 来去做响应,但我们新的 API 是这样写的,是 Containerd Shim start 或者 stop。 我的实现方式是我只在 Sandbox 时候,去创建 containerd-shim-v2,而接下来整个后面的 container 层的操作,会全部走到这个 containerd-shim-v2 里面,去重用这个
jsonview/jquery.jsonview', bootstrapDialog: 'plugin/bootstrap-dialog/bootstrap-dialog' }, shim 如果其中一个命名被其它库使用了,我们可以用另一个 define: 定义一个模块 使用 shim shim是将依赖中的全局变量暴露给requirejs,当作这个模块本身的引用。 requirejs.config({ baseUrl: '/public/js', paths: { hello: 'hello' }, shim: { hello: {
shim属性,专门用来配置不兼容的模块。 require.config({ shim: { 'underscore':{ exports: '_' }, 'backbone': { console.log(myCustomMod.max(1, 2, 3)); }) /* myCustomMod.js */ var myCustomMod = {}; // 很重要,和shim ({ waitSeconds: 0, baseUrl: '/', paths: { myCustomMod: "myCustomMod" }, shim DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Test Require Shim</title>
shim进程 shim直接调用runc的包函数,shim与containerd之前通过rpc通信 真正用户想启动的进程由runc的init进程启动,即runc init [args ...] = nil { //启动了一个shim进程 } return connectShim(socket) // 这里返回了与shim进程通信的客户端} 再去看看shim的代码: shim进程启动干的最主要的一件事就是启动一个 通信模型介绍 再看shim与runc的关系,这个比较简单了,直接进入shim service 实现的Create方法即可 1 sv = shim.New(path) 123456 func (s *Service 其本质是调用了runc create --bundle [bundle] [containerid] 命令,在此不多作介绍了 shim进程与runc进程之间 上文可知,shim进程创建runc子进程。 "containerd-shim" Name or path of shim --pprof-address
__globals__.popitem() 剥离尾巴, 此刻 _=('remove_shim', <function _remove_shim at 0x7ff7846daf80>) 需要再回到< class '_distutils_hack.shim'> . __globals__.popitem() 剥尾 返回:_=('insert_shim', <function insert_shim at 0x7ff0a6696f80>) .__class__. __subclasses__().pop() 回到 _distutils_hack.shim .__enter__.__globals__.popitem() 剥尾 返回:shim . __globals__.popitem() 剥尾 返回: _=('add_shim', <function add_shim at 0x7ff0a6696830>) .__class__.
= 3 { return shim.Error("Incorrect number of arguments. = nil { return shim.Error("Failed to get state") } if Avalbytes == nil = nil { return shim.Error("Failed to get state") } if Bvalbytes == nil = nil { return shim.Error(err.Error()) } return shim.Success(nil) } 2 (success)") return shim.Success(nil) } 相比第一个例子转账加强了些些, Marble是资产, 对应有拥有人。
= nil { return shim.Error("Failed to delete Student from DB, key is: "+key) } return shim.Success =nil{ return shim.Error("query failed") } return shim.Success(person) } 16.8.1.7. stub.GetHistoryForKey =nil{ return shim.Error(err.Error()) } var result,_= getHistoryListResult(it) return shim.Success = nil { return shim.Error(err.Error()) } return shim.Success(nil) } func (t *SimpleChaincode ) sc.Response { return shim.Success(nil) } func (s *SmartContract) initLedger(stub shim.ChaincodeStubInterface
= 0 { return shim.Error("Incorrect number of arguments. { return shim.Error("color field must be a non-empty string") } if marbleInput.Size <= 0 { return shim.Error = nil { return shim.Error(err.Error()) } // Save index entry to state. = 1 { return shim.Error("Incorrect number of arguments. = 1 { return shim.Error("Incorrect number of arguments.
Fabric官方提供了两种开发node.js链码的途径:fabric-shim和fabric-contract-api。 使用fabric-shim开发Fabric链码 fabric-shim是较底层的链码开发包,它封装了与节点通信的grpc协议。 安装方法如下: ~/fabric-shim-chaincode-demo$ npm install fabric-shim fabric-shim要求链码开发者定义一个实现两个预定义方法的类。 例如,下面的代码实现了一个最小化的node.js链码,每次调用链码都会更新acc0的状态(例如:可以使用这个状态代表账户余额): const shim = require('fabric-shim'); 例如: const shim = require('fabric-shim'); class EzChainCode {...} shim.start(new EzChaincode()); 这就是一个完整的
shim.Success(nil) } func (s *SmartContract) transferToken(stub shim.ChaincodeStubInterface, args []string )) return shim.Success(nil) } func (s *SmartContract) mintToken(stub shim.ChaincodeStubInterface, args ) return shim.Success(nil) } func (s *SmartContract) setLock(stub shim.ChaincodeStubInterface, args return shim.Success(nil) } func (s *SmartContract) frozenAccount(stub shim.ChaincodeStubInterface, )) return shim.Success(nil) } func (s *SmartContract) balanceToken(stub shim.ChaincodeStubInterface
)) } return shim.Success(nil) } func (s *SmartContract) Query(stub shim.ChaincodeStubInterface) pb.Response ) return shim.Success(accountAsBytes) } func (s *SmartContract) initLedger(stub shim.ChaincodeStubInterface } return shim.Success(result) } func (s *SmartContract) mintToken(stub shim.ChaincodeStubInterface, return shim.Success(nil) } func (s *SmartContract) frozenAccount(stub shim.ChaincodeStubInterface, )) } return shim.Success(nil) } func (s *SmartContract) showAccount(stub shim.ChaincodeStubInterface
链码必须依赖 chaincode shim 包和 peer protobuf 包,它们分别用于链码的控制与数据传输,其次定义 KeyValueStore 类型,作为 chaincode shim 的载体 = 2 { return shim.Error("Incorrect arguments. = nil { return shim.Error(fmt.Sprintf("Failed to create asset: %s", args[0])) } return shim.Success = nil { return shim.Error(err.Error()) } return shim.Success([]byte(result)) } 为了完成对账本的读写 func main() { if err := shim.Start(new(KeyValueStore)); err !
=3{ return shim.Error("Incorrect number of arguments.Expecting 3") } A=args[0] B=args[1] //获取A、B =nil{ return shim.Error("Failed to get state") } if Avalbytes==nil{ return shim.Error("Entity not =nil{ return shim.Error("Failed to get state") } if Bvalbytes==nil{ return shim.Error("Entity not =nil{ return shim.Error(err.Error()) } err=stub.PutState(B,[]byte(strconv.Itoa(Bval))) if err! =nil{ return shim.Error(err.Error()) } return shim.Success(nil) }
package main import ( "chainmaker/pb/protogo" "chainmaker/shim" ) // AgeContract save and get err := shim.Start(new(AgeContract)) if err ! shim.Error("no contarct method") } // saveAge 保存用户年龄信息 func (ac *AgeContract) saveAge(stub shim.CMStubInterface := shim.Start(new(AgeContract)) if err ! := shim.Start(new(AgeContract)) if err !