指针篇之十 传递指针共享内存

    受硬件工艺制约,CPU访问外部内存的速度远远慢于寄存器以及片上内存,常常成为程序性能的最大瓶颈。而指针作为内存间接访问的索引,可实现内存共享机制,代替内存间的大数据搬运和拷贝。打个粗俗的比方,小孩在家里随地大小便,大人每次都要在后面处理,这时真希望他会蹲马桶啊!第一步一定是告诉并让他记住马桶在哪里,否则一旦既成事实,臭臭落地,就只能“拷贝搬运”了。所以,马桶的位置就是指针!

函数调用链上的多余中转内存导致的额外拷贝

    一些C初学者一看到需要buffer存数据,不管三七二十一,立马先定义个数组放着,然后懵懵懂懂走一步看一步,这样最后就不可避免的导致多余内存拷贝,比如:

  extern void tran(char *pin, char out[X_SIZE], int size);

  void initParams(Params * param,char *pECC)

  {

    char A[X_SIZE]={0}//祸根埋下

    ……

    tran(&pECC[0], A, X_SIZE);   //走一步看一步

    memcpy(param->mA,A, X_SIZE);  //最终无法避免的多余拷贝

  }

    tran函数需要一块buffer(即参数out[X_SIZE])保存结果,如果为此专门定义一个数组A,就意味着要先把tran的输出保存在数组A的中间栈内存,而外层initParam又希望通过另一块内存(param->mA)输出结果,要在两块不同内存间传递数据,memcpy无法避免。因此函数内部这种低级的多余拷贝,根源往往在于多余的中间内存。把tran计算结果直接存到param->mA所指内存,不就结了。即tran(&Pecc[0], param->mA,X_SIZE),既不需要A,也省了memcpy

    以前汇钱必须先到银行取出钞票,再到邮局把钞票汇到别人存折上,现在用不着钞票这个烫手的中转物了,直接端到端网上转帐,这就是省略多余中间量的好处。

多模块间的内存共享

    设计第三方模块库时也要考虑省略中间内存的问题。比如有前后相连的两个库ABA的输出数据要做为B的输入,理想情况是双方共享一块内存,不需拷贝。但试想一下,如果A/B都在各自内部分配bufferAbuffer向外输出,即“推数据”,B则用内部buffer从外部“拉数据”,这样先天决定了AB数据分开存在不同内存里,无法直接挂钩共享,必须增加一个内存拷贝环节来传递数据流。所以设计第三方模块时,为使其具备与其他模块共享内存的能力,就要包含直接使用外部内存的接口,或者说可接受外部分配内存

    例如显示模块受硬件限制,一般要求把数据传入固定显存,而如果上层视频解码库按照自己逻辑解码完成,解码完的数据已存在decoder库内部申请并吐给外部的内存上,这两块内存间就不得不进行一次数据拷贝。此时避免拷贝的做法是为视频解码模块添加获取外部output buffer的接口,由外部提供output数据期望存放的位置,然后decoder直接把数据解码到那里(呵呵,就是直接排到马桶里),指针在这个过程中为双方指路。这种在串行调用的模块间共享内存的方式,基础就是模块双方事先共享指针。

多进程间的内存共享

    在嵌入式多任务系统中的server/client应用中,多任务条件下的内存共享就是典型的生产者/消费者问题,任务双方交错访问某内存队列(环形buffer),一方往某内存地址写入数据的同时,另一方从已ready的内存块读取数据,通过信号量/事件等手段确保任务间读写操作互不冲突,就可通过内存共享数据,而避免拷贝。

    On many platforms shared memory allows fast, zero-copy, unstructured communication between a client and a service. This feature is particularly useful for minimizing the overhead incurred when a service has to deal with large data buffers, such as multimedia files or encrypted disk partitions.(One of Specifications from ARM

    现代操作系统大多为用户进程间以及用户与内核空间的内存共享提供现成接口(linuxshmget/mmapwindowsCreateFileMapping等),只要按流程调用即可获取共享的内存指针。这些系统层API接口,本质也是生成并传递共享指针,然后双方对共享内存交替互斥访问,代替内存拷贝(详细机制超出范围,可自己查阅相关资料)。进程间内存共享时间上看似并发同时访问,实际利用多任务的互斥手段,最终交错串行访问的内存共享。

贪官给情人送车房钥匙,不会直接把房子和车扛过去。指针就是内存财富的钥匙。

你可能感兴趣的:(C语言基础-指针篇)