两年前实习时的文档——Platform学习总结

Platform.Uno介绍 编者语:Xamarin国内很多人说缺乏可用的实例,我在写书过程中在完善一些常用场景的例子,希望帮到大家。Build 2018结束一周了,善友问我要不要谈谈Xamarin的一些变化,但碍于时间有限一直没有付诸行动。想想总得写点什么给大家,其实之前也谈过一些,具体就等日后我的书吧。今天我反而想谈一个在Build上一个引起关注的框架Platform.Uno.     XAML在微软推了快10年,主要应用... 阅读详情

1  概述

驱动程序实际上是硬件与应用程序之间的中间层。在Linux操作系统中,设备驱动程序对各种不同的设备提供了一致的访问接口,把设备映射成一个特殊的设备文件,用户程序可以像其他文件一样对设备文件进行操作。

Linux2.6引入了新的设备管理机制kobject,通过这个数据结构使所有设备在底层都具有统一的接口,kobject提供基本的对象管理,是构成Linux2.6设备模型的核心结构,它与sysfs文件系统紧密联系,每个在内核中注册的kobject对象都对应于sysfs文件系统中的一个目录。

在这些内核对象机制的基础上,Linux的设备模型包括设备结构device、驱动程序driver、总线bus和设备类结构class几个关键组件。

一个现实的linux设备和驱动通常都需要挂接在一种总线上,比较常见的总线有USB、PCI总线等。但是,在嵌入式系统里面,SoC系统中集成的独立的外设控制器、挂接在SoC内存空间的外设却不依附于此类总线。基于这样的背景下,2.6内核加入了platform虚拟总线。Platform机制将设备本身的资源注册进内核,由内核统一管理,在驱动程序使用这些资源时使用统一的接口,这样提高了程序的可移植性。

Platform设备概念的引入是能够更好地描述设备的资源信息。Platform设备是系统中自治的实体,包括基于端口的设备、外围总线和集成入片上系统平台的大多数控制器,它们通常直接通过CPU的总线寻址。每个platform设备被赋予一个名称,并分配一定数量的资源。

Platform总线对加入到该总线的设备和驱动分别封装了结构体——platform_device和platform_driver并且提供了对应的注册函数。


Platform虚拟总线

由上图可知,在platform虚拟总线上我们分别对device和driver进行注册,这样我们能够更加方便的进行驱动设备的管理。这样当有总线或者设备注册到该虚拟总线上时,内核自动的调用platform_match函数将platform_device绑定到platform_driver上。

2  platform数据结构

Linux在启动的时候就注册了platform总线,看内核源码:

struct bus_type platform_bus_type = {

       .name             ="platform",

       .dev_attrs       = platform_dev_attrs,

       .match            =platform_match,

       .uevent           =platform_uevent,

       .pm         =&platform_dev_pm_ops,

};

可以看到,总线中定义了.match函数,当有总线或者设备注册到platform总线时,内核自动调用.match函数,判断device和driver的name是否一致。

platform_device的结构体定义如下:

struct platform_device {

       constchar       * name;//设备名字,这将代替device->dev_id,用作sys/device下显示目录名

       int          id;//设备ID,用于给插入该总线并且具有相同name的设备编号,如果只有一个设备的话填-1

       structdevice   dev;//结构体中内嵌的device结构体

       u32         num_resources;//资源数

       structresource * resource;//用于存放资源的数组

 

       conststruct platform_device_id     *id_entry;

 

       /*arch specific additions */

       structpdev_archdata      archdata;

};

可以看出,在platform_device中定义了name,并且内嵌了structdevice结构体。另外,包含的structresource如下:

struct resource {

       resource_size_tstart;

       resource_size_tend;

       constchar *name;

       unsignedlong flags;

       structresource *parent, *sibling, *child;

};

platform_driver的结构体定义如下:

struct platform_driver {

       int(*probe)(struct platform_device *);

       int(*remove)(struct platform_device *);

       void(*shutdown)(struct platform_device *);

       int(*suspend)(struct platform_device *, pm_message_t state);

       int(*resume)(struct platform_device *);

       structdevice_driver driver;

       conststruct platform_device_id *id_table;

};

可以看出,在platform_driver中内嵌了structdevice_driver,以及一些回调函数。structdevice_driver的具体定义如下:

struct device_driver {

       constchar              *name;

 

       int(*probe) (struct device *dev);

       int(*remove) (struct device *dev);

       void(*shutdown) (struct device *dev);

       int(*suspend) (struct device *dev, pm_message_t state);

       int(*resume) (struct device *dev);

       conststruct attribute_group **groups;

 

       conststruct dev_pm_ops *pm;

 

       structdriver_private *p;

};

此处定义了name用于和platform_device匹配。因为platform_device和platform_driver的匹配就是通过内嵌的structdevice和structdevice_driver的name进行匹配的。

static int platform_match(struct device *dev,struct device_driver *drv)

{

       structplatform_device *pdev = to_platform_device(dev);

       structplatform_driver *pdrv = to_platform_driver(drv);

 

       /*match against the id table first */

       if(pdrv->id_table)

              returnplatform_match_id(pdrv->id_table, pdev) != NULL;

 

       /*fall-back to driver name match */

       return(strcmp(pdev->name, drv->name) == 0);

}

3  platform device

3.1  register

注册一个platform层的设备。注册后,会在sys/device目录下创建一个以name命名的目录,并且创建软连接到/sys/bus/platform/device下。

int platform_device_register(structplatform_device *pdev)

{

       device_initialize(&pdev->dev);

       returnplatform_device_add(pdev);

}

其中,第一步device_initialize(在kernel文件夹下)用于初始化一个structdevice。函数的定义如下:

void device_initialize(struct device *dev)

{

       dev->kobj.kset= devices_kset;

       kobject_init(&dev->kobj,&device_ktype);

       INIT_LIST_HEAD(&dev->dma_pools);

       mutex_init(&dev->mutex);

       lockdep_set_novalidate_class(&dev->mutex);

       spin_lock_init(&dev->devres_lock);

       INIT_LIST_HEAD(&dev->devres_head);

       device_pm_init(dev);

       set_dev_node(dev,-1);

}

第二步,添加一个platformdevice到device层 。函数的定义如下:

int platform_device_add(struct platform_device*pdev)

{

       inti, ret = 0;

       if(!pdev)

              return -EINVAL;

       if(!pdev->dev.parent)

       pdev->dev.parent= &platform_bus;//如果p->dev.parent不存在则赋值&platform_bus

       pdev->dev.bus= &platform_bus_type;//设置pdev->dev.bus的bus类型

       if(pdev->id != -1)    //pdev->id!=-1说明存在多于一个的设备

              dev_set_name(&pdev->dev,"%s.%d", pdev->name, pdev->id);

       Else   //否则对唯一的设备进行命名

              dev_set_name(&pdev->dev,"%s", pdev->name);

 

       for(i = 0; i < pdev->num_resources; i++) {

     //遍历资源并且资源加入到资源数组中

              struct resource *p, *r =&pdev->resource[i];

              if (r->name == NULL)

                     r->name= dev_name(&pdev->dev);

              p = r->parent;

              if (!p) {

                     if(resource_type(r) == IORESOURCE_MEM)

                            p = &iomem_resource;

                     elseif (resource_type(r) == IORESOURCE_IO)

                            p = &ioport_resource;

              }

              if (p && insert_resource(p, r)) {

                     printk(KERN_ERR

                            "%s: failed to claim resource%d\n",

                            dev_name(&pdev->dev), i);

                     ret= -EBUSY;

                     gotofailed;

              }

       }

       pr_debug("Registeringplatform device '%s'. Parent at %s\n",

               dev_name(&pdev->dev),dev_name(pdev->dev.parent));

 

       ret= device_add(&pdev->dev);//(在core/core.c中定义)

       if(ret == 0)

              return ret;

 failed:

       while(--i >= 0) {

              struct resource *r =&pdev->resource[i];

              unsigned long type = resource_type(r);

 

              if (type == IORESOURCE_MEM || type ==IORESOURCE_IO)

                     release_resource(r);

       }

       returnret;

}

 

3.2   unregister

platform_device_unregister用于注销一个platform-leveldevice。函数的定义如下:

void platform_device_unregister(structplatform_device *pdev)

{

       platform_device_del(pdev);

       platform_device_put(pdev);

}

在注销一个设备时,第一步调用platform_device_del函数。此函数的定义如下:

void platform_device_del(structplatform_device *pdev)

{

       inti;

 

       if(pdev) {

              device_del(&pdev->dev);

//遍历所有的resource如果是IORESOURCE_MEM或者IORESOURCE_IO类型则调用release_resource函数释放掉resource。

              for (i = 0; i <pdev->num_resources; i++) {

                     structresource *r = &pdev->resource[i];

                     unsignedlong type = resource_type(r);

 

                     if (type == IORESOURCE_MEM || type== IORESOURCE_IO)

                            release_resource(r);

              }

       }

}

此函数的作用是:移除一个platform-leveldevice。其中的IOSOURCE_MEM和IORESOURCE_IR是CPU对外设I/O端口物理地址的两种编制方式。Resource是一个指向platform资源数组的指针,该数组有num_resource个资源,下面是资源结构体的定义(linux/ioport.h):

struct resource {

       resource_size_tstart;  //起始地址

       resource_size_tend;   //终止地址

       constchar *name;     //名称

       unsignedlong flags;    //标志

       structresource *parent, *sibling, *child;

};

在structplatform_device中可以设置多种资源信息。资源的flags标志包括:

#define IORESOURCE_IO      0x00000100   //IO资源

#define IORESOURCE_MEM   0x00000200   //内存资源

#define IORESOURCE_IRQ    0x00000400   //中断资源

#define IORESOURCE_DMA   0x00000800   //DMA资源

第二步,调用platform_device_put函数。

void platform_device_put(structplatform_device *pdev)

{

       if(pdev)

              put_device(&pdev->dev);

}

销毁一个platformdevice,并且释放所有与这个platformdevice相关的内存。

4  platform driver

4.1  register

通过调用函数platform_driver_register实现为platformlevel的设备注册一个驱动。注册成功后,内核会在/sys/bus/platform/driver/目录下创建一个名字为driver->name的目录。具体的函数定义如下:

int platform_driver_register(structplatform_driver *drv)

{

       drv->driver.bus= &platform_bus_type;

       if(drv->probe)

              drv->driver.probe =platform_drv_probe;

       if(drv->remove)

              drv->driver.remove =platform_drv_remove;

       if(drv->shutdown)

              drv->driver.shutdown =platform_drv_shutdown;

 

       returndriver_register(&drv->driver);

}

此函数首先对struct  platform_driver变量的driver进行赋值。然后调用driver_register并且返回。driver_register函数的定义如下:

int driver_register(struct device_driver *drv)

{

       intret;

       structdevice_driver *other;

 

       BUG_ON(!drv->bus->p);

//如果driver的方法和总线上的方法不能匹配则驱动的名称需要更新

       if((drv->bus->probe && drv->probe) ||

           (drv->bus->remove &&drv->remove) ||

           (drv->bus->shutdown &&drv->shutdown))

              printk(KERN_WARNING "Driver '%s'needs updating - please use "

                     "bus_typemethods\n", drv->name);

 

       other= driver_find(drv->name, drv->bus);

       if(other) {

              put_driver(other);

              printk(KERN_ERR "Error: Driver '%s'is already registered, "

                     "aborting...\n",drv->name);

              return -EBUSY;

       }

 

       ret= bus_add_driver(drv);//将驱动加载到总线上,如果成功就返回

       if(ret)

              return ret;

       ret= driver_add_groups(drv, drv->groups);

       if(ret)

              bus_remove_driver(drv);

       returnret;

}

4.2  unregister

通过调用函数platform_driver_unregister函数实现platform_driver级设备的注销。

void platform_driver_unregister(structplatform_driver *drv)

{

       driver_unregister(&drv->driver);

}

在此函数中调用了driver_unregister函数,将驱动从系统中移除。函数的具体定义如下:

void driver_unregister(struct device_driver*drv)

{

       if(!drv || !drv->p) {

              WARN(1, "Unexpected driverunregister!\n");

              return;

       }

       driver_remove_groups(drv,drv->groups);

       bus_remove_driver(drv);

}

分两步走,第一步调用driver_remove_groups。函数的具体定义如下:

static void driver_remove_groups(structdevice_driver *drv,

                             const struct attribute_group **groups)

{

       inti;

 

       if(groups)

              for (i = 0; groups[i]; i++)

                     sysfs_remove_group(&drv->p->kobj,groups[i]);

}

其中,调用了

static inline void sysfs_remove_group(struct kobject *kobj,

                                const struct attribute_group *grp)

{

}

第二步从总线中将驱动删除。调用如下函数:

void bus_remove_driver(struct device_driver *drv)

{

      if (!drv->bus)

             return;

 

      if(!drv->suppress_bind_attrs)

             remove_bind_files(drv);

      driver_remove_attrs(drv->bus,drv);

      driver_remove_file(drv,&driver_attr_uevent);

      klist_remove(&drv->p->knode_bus);

      pr_debug("bus: '%s':remove driver %s\n", drv->bus->name, drv->name);

      driver_detach(drv);

      module_remove_driver(drv);

      kobject_put(&drv->p->kobj);

      bus_put(drv->bus);

}

此函数的作用是:将驱动从它控制的设备中卸载,并且从驱动的总线链表中将它移除。

power platform 低代码平台 ----(不知不觉就大四了,很久没写blog,趁着做项目的间隙也写一下。) 《Microsoft Power Platform — 微软低代码应用平台》 近两年在中国开始被开发者们关注了。于是我也申请了一个学习学习... 1、power apps,主张 app in a day。它提供快速开发环境的应用程序,用于构建自定义应 用程序以满足业务需求。 它具有服务、连接器和数据平台。PowerApps 可以在笔记本电脑、平板电脑或手机上运行。 power apps 能够快速的构建一个前端框架,使用简单 阅读详情

相关推荐

Vue3项目实战:CKEditor5富文本编辑器从安装到隐藏不需要的功能

本文详细介绍了在Vue3项目中集成并深度定制CKEditor5富文本编辑器的完整流程。通过分析其模块化架构,指导开发者从标准构建出发,移除图片、表格等冗余插件,创建专属轻量构建,从而显著减小打包体积并提升用户体验。文章结合实战代码,涵盖了环境搭建、自定义构建配置、高级优化技巧等关键步骤。

weixin_29016833的博客 283

使用Vivado的Block Design详细步骤

1.选择创建Block Design并命名 2.点击Add IP,并选择ZYNQ7 3.双击 ZYNQ Processing System,打开 ZYNQ 系统的配置界面 1)PS_PL 页面提供了 PS 到 PL 的相关接口配置信息以及 PS 部分一些配置信息; 2)Peripheral I/O Pins 页面主要是对一些通用外设接口的配置; 3)MIO Configruation 页面主要是对 MIO 已经EMIO 的分配控制; 4)Clock Configruation 页面主要是对 PS 端时钟

syrg520的博客 3万+

振动分析中相位的确定

更是定位不平衡量角度的关键。是确定振动信号与转子旋转位置之间时间关系的核心步骤,而。以内,以确保校正配重安装角度的有效性。在实际动平衡中,相位角的误差需控制在。在振动分析和动平衡中,

轩辕霸天L 2735

第1篇:创建Platform Designer系统

使用Platform Designer工具创建带IP核的FPGA自定义硬件系统

weixin_47841246的博客 1309

WinCC ActiveX控件“许可证缺失”故障排查:从注册表修复到系统兼容性全解析

本文深入解析WinCC ActiveX控件报错“未找到许可证信息”的根本原因与解决方案。核心在于系统注册表中控件的设计时许可证密钥丢失或损坏。文章提供了从手动修复注册表、排查64位系统兼容性,到预防性环境部署的全流程专业指南,帮助工程师彻底解决这一常见故障。

oil88的博客 646

单片机:实现FFT快速傅里叶变换算法(附完整源码)

单片机:实现FFT快速傅里叶变换算法(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 1101

深入解析Linux Platform_device 及驱动

深入解析Linux Platform_device 及驱动 [导读] 前文分析了Linux设备驱动的驱动模型,本文来聊聊Platform_driver/Platform_device这个类。做嵌入式Linux的驱动,这个也是绕不开的,所以来学习分析总结一下。 上文阅读: 注:代码分析基于linux-5.4.31 为什么有Platform_driver 前文谈到的总线驱动模型(注这个图是照着bootlin的文档绘制的): 同时,根据代码分析其基础数据结构框架关系如下(UML关系并不严谨,仅为理

u010783226的专栏 1762

【网络基础2】路由器的 “两扇门”:二层接口和三层接口到底有啥不一样?

家里的路由器背后总有几个网线接口,有的标着 “LAN”,有的标着 “WAN”;公司机房的路由器上,接口更是五花八门,有的插着网线,有的连着光纤,旁边还贴着 “GE0/0/1”“Eth-Trunk1” 这样的标签。你可能会想:不就是插网线的地方吗?有啥区别?其实,这些接口分 “二层接口” 和 “三层接口”,它们的作用差得远了 —— 就像你家的门,有的是 “小区内的单元门”(只通小区内部),有的是 “小区的大门”(能通往外面的世界)。接下来,咱们用大白话 + 生活例子,一点点把这两种接口讲透。

jundao1997的专栏 565

关于platform_device一些讲解

从2.6版本开始引入了platform这个概念,在开发底层驱动程序时,首先要确认的就是设备的资源信息,例如设备的地址, 在2.6内核中将每个设备的资源用结构platform_device来描述,该结构体定义在kernel\include\linux\platform_device.h中: struct platform_device { const char * name; u32 id; struct device dev; u32 num_resources; struct resou

Gick 6361

【Go语言实战】(9) gRPC 实现一个简单微服务

文章目录写在前面1. 安装1.1 grpc1.2 proto1.3 protobuf2. 编写代码2.1 初始化项目2.2 编写proto2.3 编写服务端2.4 实现客户端3. 演示 写在前面 这一次我们用gRPC实现获取用户的信息 1. 安装 1.1 grpc grpc的安装直接go get即可 go get google.golang.org/grpc 1.2 proto 下载proto,我是下载这个的。 然后解压出来把bin目录放在直接放在系统变量当中 1.3 protobuf 我们在

面向生活编程 3272

解决微信小程序长页面滚动到底部点击底部的输入框后输入框漂浮且页面滚动到顶部

一、问题描述 项目中有一个长页面上部展示部分信息下部为信息录入,页面长度为三屏幕(不同手机屏幕大小略有差异),当滚动到第二屏或者第三屏去填写信息时点击输入框后输入框漂浮起来了并且页面向上滚动了一段距离,回到了第一屏中展示的内容。效果如图。 滚动到第二屏,证件号输入。 点击输入框 可以看到证件号输入框漂浮了起来并且页面滚动到了第一屏展示的内容。 注意:小程序是2018年上线,在2020年4月份之前该页面从未出现过这种现象。推测:微信的后续更新中对微信小程序基础库进行了重构,导致点击输入框后页

仰望星空的代码 3260

Linux内核平台设备驱动模型platform_device和platform_driver框架

关于Linux内核的平台设备驱动模型框架

D584640810的博客 4390

【unity实战】Unity游戏开发:如何用ScriptableObject与序列化多态实现可复用的模块化效果系统?

本文介绍了两种实现卡牌游戏效果系统的模块化设计方案。方案一使用ScriptableObject创建独立的效果资产,通过组合实现不同效果,优点是数据可复用、可视化编辑,缺点是同类不同参数效果需创建大量SO文件。方案二利用SerializeReference特性直接嵌套效果实例,避免SO文件过多,但需要插件支持编辑器多态显示。两种方案都将效果与卡牌解耦,提高了代码复用性和扩展性,解决了硬编码带来的重复、维护困难和扩展不便等问题。开发者可根据项目需求选择合适方案,或结合两者优势构建更灵活的系统。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 436

两年前实习时的文档——MMC学习总结

1  概述 驱动程序实际上是硬件与应用程序之间的中间层。在Linux操作系统中,设备驱动程序对各种不同的设备提供了一致的访问接口,把设备映射成一个特殊的设备文件,用户程序可以像其他文件一样对设备文件进行操作。 Linux2.6引入了新的设备管理机制kobject,通过这个数据结构使所有设备在底层都具有统一的接口,kobject提供基本的对象管理,是构成Linux2.6设备模型的核心结构,它与s

曹太强的专栏 2606

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Platform.sh用户文档:构建高效、可扩展的技术文档平台

Platform.sh用户文档:构建高效、可扩展的技术文档平台 项目介绍 Platform.sh User Documentation 是一个开源项目,旨在为Platform.sh和Upsun提供全面的用户文档。该项目不仅托管了文档网站 docs.platform.sh 和 docs.upsun.com,还展示了如何利用Platform.sh的强大构建和部署系统来托管和构建静态网站。每个Pull ...

gitblog_00425的博客 828

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Backtrader 文档学习-Platform Concepts

介绍平台的概念,数据载入,快捷访问数据,Lines的定义和数据类型,继承,长度,索引,切片等概念,cerebro加载多个数据源,重构的操作符。

六月闻君 1631

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

一天学习开发一个APP!PDF转Word文档,Power Platform也能搞定

之前,给大家分享了微软Power Platform开发课程——手把手教你搭建二维码识别器,大家都很感兴趣。听说,很多小伙伴对于PDF转Word文档有困扰,这期我们继续为大家分享Power Platform的开发能力与技巧,怎么通过Power Platform解决这个问题。今天,就为大家介绍如何开发⼀个文档转换器(PDF转Word)。

M15219285876的博客 1008

WinVisor vs Simpleator 终极对比:两大 Windows Hypervisor Platform 虚拟化工具深度解析

**WinVisor** 是一款基于 Windows Hypervisor Platform(WHP)API 的开源模拟器,它能在虚拟环境中执行任意 Windows x64 用户态程序(cmd.exe、ping.exe 等),而同样使用 WHP 技术的 **Simpleator** 则走了另一条实现路线。本文带你快速读懂这两个项目的核心差异、工作原理与上手方法,帮你判断哪个更适合你的学习与实践需求

gitblog_00343的博客 391

IntelliJ Platform SDK 文档项目教程

IntelliJ Platform SDK 文档项目是 JetBrains 官方提供的开源项目,旨在帮助开发者理解和使用 IntelliJ 平台的 SDK。该项目包含了丰富的文档、代码示例和最佳实践,适用于希望开发 IntelliJ 插件和扩展的开发者。 ## 项目快速启动 ### 环境准备 1. **安装 IntelliJ IDEA**:确保你已经安装了 IntelliJ IDEA 开发环...

gitblog_00022的博客 587

Uno Platform 文档贡献指南:如何编写高质量技术文档

在开源项目Uno Platform中,优秀的文档对于开发者体验至关重要。本文将深入探讨如何为Uno Platform贡献高质量的文档内容,帮助开发者更好地理解和使用这个跨平台UI框架。 ## 文档类型与适用场景 ### 1. 分步指南(教程类文档) 这类文档针对开发者可能遇到的特定问题或使用场景,提供详细的解决方案。 **最佳实践:** - 对于复杂主题,可考虑拆分为多个页面 - 每个步骤...

gitblog_00825的博客 396

【亲测免费】 IntelliJ Platform SDK 文档项目介绍

IntelliJ Platform SDK 文档项目是JetBrains公司开源的官方文档项目,旨在为开发者提供开发IntelliJ IDEA插件所需的详细指南和示例。该项目主要使用Markdown、Java、XML等编程语言编写。 ## 1. 项目基础介绍 本项目是IntelliJ Platform SDK的官方文档,包含了开发插件所需的全部指南、API参考、教程和示例。通过该项目,开发者可...

gitblog_00083的博客 579

Nop Platform 2.0 技术文档

Nop Platform 2.0 技术文档 【免费下载链接】nop-entropy Nop Platform 2.0是基于可逆计算理论实现的采用面向语言编程范式的新一代低代码开发平台,包含基于全新原理从零开始研发的GraphQL引擎、ORM引擎、工作流引擎、报表引擎、规则引擎、批处理引引擎等完整设计。nop-entrop...

gitblog_01409的博客 786
上一篇: Setting up Minicom in Ubuntu
下一篇: 两年前实习时的文档——MMC学习总结
野-百-合
博客等级 码龄17年 308粉丝 118原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值