原文链接:https://www.cnblogs.com/yaongtime/p/14594567.html前面的几篇笔记记录dma-fence的一些用途,这里简单写了个DMA-FENCE的测试代码。dma-fence本身的实现和使用并不复杂,其只有两种状态signaled和unsigned。可能正是因为其本身的精简,在融入其他概念中时,在不同的环境下,赋予了dma-fence不同的含义。所以通常需要根据dma-fence的具体使用的情况来理解其含义。dma-fence是内核中的同步原语,本身只能表示两种状态,这点上就和complete有点类似了。但是dma-fence是可以跨设备,跨进程的。具体来说:1.就是A设备驱动程序中创建的dma-fence可以被B驱动程序使用。2.dma-fence是由内核创建,但是可以在进程间传递,并且可以在用户层获取fence的当前状态。而常规的内核中的同步方法,则不具备对上述两点的支持。基本原理:一个被初始化的dma-fence,使用wait函数后,会将当前进程换出,即当前进程会sleep,而当调用signal函数时会唤醒被wait函数换出的进程。dma-fence的使用还可以通过向dma-fence添加一个或多个callback函数,当dma-fence调用signal操作时,会依次遍历callbacklist,并调用每个callback函数。当调用wait函数时,会把默认的一个callback函数加入到dma-fence中,而这个函数就起到唤醒的作用。dma-fence在内核中被创建,可以通过导出一个文件描述符fd到user层,然后用户层可以对该fd做常规的文件操作,也可以把该fence传递给其他进程。这个fd给到内核中后,又可以还原出dma-fence的内核数据结构。所以在user层看到的dma-fence是一个文件描述符。其中提到的几个操作对用函数如下:init:dmac5690c076f5f55b7540455e64ee416800fencec5690c076f5f55b7540455e64ee416801init()wait:dmac5690c076f5f55b7540455e64ee416802fencec5690c076f5f55b7540455e64ee416803wait()signal:dmac5690c076f5f55b7540455e64ee416804fencec5690c076f5f55b7540455e64ee416805signal()callback:dmac5690c076f5f55b7540455e64ee416806fencec5690c076f5f55b7540455e64ee416807addc5690c076f5f55b7540455e64ee416808callback()具体的例子:driver通过一个字符设备驱动程序实现的。在字符设备被open时,会新创建一个dma-fence的内核数据对象。通过ioctl实现了三个命令,主要实现三个功能,1.导出内核dma-fence的fd到user层;2.user层导入一个fd到内核中,并还原为内核dma-fence对象;3.触发dma-fence变为signaled。user层的测试代码会使用driver层提供的ioctl命令,操作dma-fence。并通过系统函数poll(),在user层等待内核中dma-fence的变为signaled。ioctl命令实现对dma-fence的操作:DMAc5690c076f5f55b7540455e64ee416809FENCEc5690c076f5f55b7540455e64ee4168010INc5690c076f5f55b7540455e64ee4168011CMD:通过将fd将一个外来的fence传递到driver层,driver中先向该dma-fence添加一个callback回调函数,然后在显示调用wait函数,进程会阻塞直到该dma-fence变成signaled。DMAc5690c076f5f55b7540455e64ee4168012FENCEc5690c076f5f55b7540455e64ee4168013OUTc5690c076f5f55b7540455e64ee4168014CMD:将driver创建的dma-fence通过fd的方式导出到user层DMAc5690c076f5f55b7540455e64ee4168015FENCEc5690c076f5f55b7540455e64ee4168016SIGNALc5690c076f5f55b7540455e64ee4168017CMD:对driver创建的dma-fence调用signal操作1.内核中对dma-fence初始化:staticDEFINEc5690c076f5f55b7540455e64ee4168018SPINLOCK(fencec5690c076f5f55b7540455e64ee4168019lock);staticvoiddmac5690c076f5f55b7540455e64ee4168020fencec5690c076f5f55b7540455e64ee4168021cb(structdmac5690c076f5f55b7540455e64ee4168022fencec5690c076f5f55b7540455e64ee4168023f,structdmac5690c076f5f55b7540455e64ee4168024fencec5690c076f5f55b7540455e64ee4168025cbc5690c076f5f55b7540455e64ee4168026cb){printk(dma-fencecallback!);}staticconstcharc5690c076f5f55b7540455e64ee4168027dmac5690c076f5f55b7540455e64ee4168028fencec5690c076f5f55b7540455e64ee4168029getc5690c076f5f55b7540455e64ee4168030name(structdmac5690c076f5f55b7540455e64ee4168031fencec5690c076f5f55b7540455e64ee4168032fence){returndma-fence-example;}staticconststructdmac5690c076f5f55b7540455e64ee4168033fencec5690c076f5f55b7540455e64ee4168034opsfencec5690c076f5f55b7540455e64ee4168035ops={.getc5690c076f5f55b7540455e64ee4168036driverc5690c076f5f55b7540455e64ee4168037name=dmac5690c076f5f55b7540455e64ee4168038fencec5690c076f5f55b7540455e64ee4168039getc5690c076f5f55b7540455e64ee4168040name,.getc5690c076f5f55b7540455e64ee4168041timelinec5690c076f5f55b7540455e64ee4168042name=dmac5690c076f5f55b7540455e64ee4168043fencec5690c076f5f55b7540455e64ee4168044getc5690c076f5f55b7540455e64ee4168045name,};staticstructdmac5690c076f5f55b7540455e64ee4168046fencec5690c076f5f55b7540455e64ee4168047createc5690c076f5f55b7540455e64ee4168048fence(void){structdmac5690c076f5f55b7540455e64ee4168049fencec5690c076f5f55b7540455e64ee4168050fence;fence=kzalloc(sizeof(c5690c076f5f55b7540455e64ee4168051fence),GFPc5690c076f5f55b7540455e64ee4168052KERNEL);if(!fence)returnNULL;dmac5690c076f5f55b7540455e64ee4168053fencec5690c076f5f55b7540455e64ee4168054init(fence,&fencec5690c076f5f55b7540455e64ee4168055ops,&fencec5690c076f5f55b7540455e64ee4168056lock,0,0);returnfence;}2.内核中,dma-fence导出fd到user层:syncc5690c076f5f55b7540455e64ee4168057file=syncc5690c076f5f55b7540455e64ee4168058filec5690c076f5f55b7540455e64ee4168059create(outc5690c076f5f55b7540455e64ee4168060fence);outc5690c076f5f55b7540455e64ee4168061fencec5690c076f5f55b7540455e64ee4168062fd=getc5690c076f5f55b7540455e64ee4168063unusedc5690c076f5f55b7540455e64ee4168064fdc5690c076f5f55b7540455e64ee4168065flags(Oc5690c076f5f55b7540455e64ee4168066CLOEXEC);fdc5690c076f5f55b7540455e64ee4168067install(outc5690c076f5f55b7540455e64ee4168068fencec5690c076f5f55b7540455e64ee4168069fd,syncc5690c076f5f55b7540455e64ee4168070file-file);if(copyc5690c076f5f55b7540455e64ee4168071toc5690c076f5f55b7540455e64ee4168072user((voidc5690c076f5f55b7540455e64ee4168073c5690c076f5f55b7540455e64ee4168074userc5690c076f5f55b7540455e64ee4168075)arg,&outc5690c076f5f55b7540455e64ee4168076fencec5690c076f5f55b7540455e64ee4168077fd,sizeof(int))!=0)return-EFAULT;3.内核中,接收user层传递的fd,还原出dma-fence内核对象,并通过调用dmac5690c076f5f55b7540455e64ee4168078fencec5690c076f5f55b7540455e64ee4168079wait()等待in-fence变为signaled:if(copyc5690c076f5f55b7540455e64ee4168080fromc5690c076f5f55b7540455e64ee4168081user(&inc5690c076f5f55b7540455e64ee4168082fencec5690c076f5f55b7540455e64ee4168083fd,(voidc5690c076f5f55b7540455e64ee4168084c5690c076f5f55b7540455e64ee4168085userc5690c076f5f55b7540455e64ee4168086)arg,sizeof(int))!=0)return-EFAULT;inc5690c076f5f55b7540455e64ee4168087fence=syncc5690c076f5f55b7540455e64ee4168088filec5690c076f5f55b7540455e64ee4168089getc5690c076f5f55b7540455e64ee4168090fence(inc5690c076f5f55b7540455e64ee4168091fencec5690c076f5f55b7540455e64ee4168092fd);/c5690c076f5f55b7540455e64ee4168093addacallbackfuncc5690c076f5f55b7540455e64ee4168094/dmac5690c076f5f55b7540455e64ee4168095fencec5690c076f5f55b7540455e64ee4168096addc5690c076f5f55b7540455e64ee4168097callback(inc5690c076f5f55b7540455e64ee4168098fence,&cb,dmac5690c076f5f55b7540455e64ee4168099fencec5690c076f5f55b7540455e64ee41680100cb);dmac5690c076f5f55b7540455e64ee41680101fencec5690c076f5f55b7540455e64ee41680102wait(inc5690c076f5f55b7540455e64ee41680103fence,true);4.user层中,通过系统调用poll()函数在用户层判断dma-fence的状态值:staticinlineintsyncc5690c076f5f55b7540455e64ee41680104wait(intfd,inttimeout){structpollfdfds={0};intret;fds.fd=fd;fds.events=POLLIN;do{ret=poll(&fds,1,timeout);if(ret0){if(fds.revents&(POLLERR|POLLNVAL)){errno=EINVAL;return-1;}return0;}elseif(ret==0){errno=ETIME;return-1;}}while(ret==-1&&(errno==EINTR||errno==EAGAIN));returnret;}5.signaldma-fence:dmac5690c076f5f55b7540455e64ee41680105fencec5690c076f5f55b7540455e64ee41680106signal(outc5690c076f5f55b7540455e64ee41680107fence);完整代码:https://gitee.com/yaongtime/dma-fence-demo.git参考:https://www.kernel.org/doc/html/latest/driver-api/dma-buf.html#dma-fences
标签: 内核, user, fence, callback, dma, fd