基于openwrt创建应用程序教程

背景

        之前在做路由器工作时,搞过一段时间openwrt,最近看到之前写的笔记。整理一下,希望能帮助一些朋友入坑。

熟悉openwrt

        openwrt之前并没有接触过,其目录结构和linux也有所不同。先大致了解一下openwrt文件系统中各个目录的作用;

原始目录

  • scripts

        存放了一些脚本,使用了bash,Python,perf等多种脚本语言,编译过程中,用于第三方软件包管理的feeds文件也是在这个目录中当中,在编译过程中,使用的脚本也统一放在这个目录中。

  • tools

        编译是,主机需要使用一些工具软件,tools里面包含了获取和编译这些工具的命令,软件包里面有Makefile文件,有的还包含了patch,每个Makefile当中都有一句$(eval $(call HostBuild)),这表明编译这个工具是为了在主机上使用的

  • config

        存放着整个系统的配置文件,其中包括Config-build.in  Config-devel.in  Config-images.in  Config-kernel.in

  • docs

        包含了整个宿主机的文件源码的介绍, 里面还有Makefile为目标系统生成docs.使用make -C docs/可以为目标系统生成文档

  • toolchain

        包含了 kernel 头文件,C库,binutils, debugger等。

  • target

        openwrt的源码可以编译出各个平台适用的二进制文件,个平台在这个目录里面定义了firmware和Kernel的编译过程。

  • package

        存放了openwrt系统中适用的软件包,包含针对各个软件包的Makefile。openwrt定义了一套Makefile模板.各软件参照这个模板定义了自己的信息,如软件包的版本、下载地址、编译方式、安装地址等。在二次开发过程中,这个文件夹我们会经常打交道.

事实上,通过

./scripts/feed update -a

./scripts/feed install -a的软件包也会存放在这个目录之中.

  • include

        openwrt的Makefile都存放在这里。文件名为 *.mk 。这里的文件上是在Makefile里被include的,类似于库文件.这些文件定义了编译过程.

  • 其他

        主要目录就是前面提及的8个,剩下的是单个文件。

Makefile在顶层目录执行make命令的入口文件

rules.mk定义了Makefile中使用的一些通用变量和函数

Config.in在include/toplevel.mk中我们可以看到,这是和make menuconfig相关联的文件.

feeds.conf.default是下载第三方一些软件包时所使用的地址

LICENSE & README即软件许可证和软件基本说明.其中README描述了编译软件的基本过程和依赖文件.

        以上大致就是openwrt的原始目录,其中需要我们关注的就是package目录,我们添加应用时,就需要在里面修改。

生成目录

  • feeds

        openwrt的附加软件包管理器的扩展包索引目录.有点绕,简单来说就是下载管理软件包的.默认的feeds下载有packages、management、luci、routing、telephony。如要下载其他的软件包,需打开源码根目录下面的feeds.conf.default文件,去掉相应软件包前面的#号,然后更新源:

./scripts/feeds update -a

安装下载好的包:

./scripts/feeds install -a

  • build_dir

        在前面的原始目录中,我们提到了host工具,toolchain工具还有目标文件.openwrt将在这个目录中展开各个软件包,进行编译.所以这个文件夹中包含3个子文件夹:

  • host

        在该文件夹中编译主机使用的工具软件

  • toolchain-XXX

        在该文件夹中编译交叉工具链

  • target-XXX

        在此编译目标平台的目标文件,包括各个软件包和内核文件.

  • bin

        保存编译完成后的二进制文件,包括:完整的bin文件,所有的ipk文件.

  • dl

        在编译过程中使用的很多软件,刚开始下载源码并没有包含,而是在编译过程中从其他服务器下载的,这里是统一的保存目录

  • staging_dir

        用于保存在build_dir目录中编译完成的软件.所以这里也和build_dir有同样的子目录结构。比如,在target-XXX文件夹中保存了目标平台编译好的头文件,库文件.在我们开发自己的ipk文件时,编译过程中,预处理头文件,链接动态库,静态库都是到这个子文件夹中。

  • tmp

        从名字来看,是临时文件夹.在编译过程中,有大量中间临时文件需要保存,都是在这里.

  • logs

        这个文件夹,有时可以看到,有时没有.这是因为这个文件夹保存的是,编译过程中出错的信息,只有当编译出错了才会出现.我们可以从这里获取信息,从而分析我们的软件编译为什么没有完成.

OpenWrt添加模块(package)

        OpenWrt是一个比较完善的嵌入式Linux开发平台,在无线路由器应用上已有100多个软件包。人们可以在其基础上增加软件包,以扩大其应用范围。

        OpenWrt在增加软件方面极其方便,按照OpenWrt的约定就可以很简单完成。加入的软件包可以是网上下载的开源软件或自行开发的软件。加入软件包需要在package目录下创建一个目录。然后创建一个MakefileOpenWrt建立联系,Makefile需要遵循OpenWrt的约定。另外可以创建一个patchs目录保存patch文件,对下载的源代码进行修改。

  1. 创建Makefile

        由于本文所建立的模块是基于luci的,所以在OpenWrt的“package/feeds/luci”目录下建立“szloogson”目录,并创建Makefile文件。该文件的如下

#
# Copyright (C) 2010-2014 Davied Huang Wich <apple_guet@126.com>
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-szloogson
PKG_VERSION=1.0
PKG_RELEASE:=1
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/luci-app-szloogson
    SECTION:=luci
    CATEGORY:=LuCI
    SUBMENU:=3. Applications
    TITLE:=shenzhou loogson for LuCI
    PKGARCH:=all
endef
define Package/luci-app-njitclient/description
    This package contains LuCI configuration pages for shenzhou loogson.
endef
define Build/Prepare
    mkdir -p $(PKG_BUILD_DIR)
    $(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Configure
endef
define Build/Compile
    $(MAKE) -C $(PKG_BUILD_DIR) \
        CC="$(TARGET_CC)" \
        CROSS_COMPILE="$(TARGET_CROSS)" \
        ARCH="$(ARCH)"
endef
define Package/luci-app-szloogson/install
    #install shell
    $(INSTALL_DIR) $(1)/etc/init.d
    $(INSTALL_BIN) ./files/loogson.init $(1)/etc/init.d/loogson
    #install config
    $(INSTALL_DIR) $(1)/etc/config
    $(INSTALL_CONF) ./files/loogson.config $(1)/etc/config/loogson
    #install execute bin
    $(INSTALL_DIR) $(1)/usr/sbin
    $(INSTALL_BIN) $(PKG_BUILD_DIR)/gsc3280_led $(1)/usr/sbin/gsc3280_led   
    #install luci
    mkdir -p $(1)/usr/lib/lua/luci/controller/admin
    $(INSTALL_DIR) $(1)/usr/lib/lua/luci/controller
    $(INSTALL_DATA) ./src/luci/controller/admin/loogson.lua $(1)/usr/lib/lua/luci/controller/admin/loogson.lua
   
    mkdir -p $(1)/usr/lib/lua/luci/model/cbi/admin_loogson
    $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi
    $(INSTALL_DATA) ./src/luci/model/cbi/admin_loogson/* $(1)/usr/lib/lua/luci/model/cbi/admin_loogson/
endef
$(eval $(call BuildPackage,luci-app-szloogson)

说明

第8行“$(TOPDIR)/rules.mk”一般在Makefile的开头,定义一些包的基本信息。

软件包的信息均以“PKG_”开头,其意思和作用如下:
PKG_NAME:软件包名称,将在menuconfig和ipkg可以看到。
PKG_VERSION:软件版本号。
PKG_RELEASE:Makefile的版本号
PKG_SOURCE:源代码的文件名。
PKG_SOURCE_URL:源代码的下载网站位置。@SF表示在sourceforge网站,@GNU表示在GNU网站,还有@GNOME、@KERNEL。获取方式可以为:git、svn、cvs、hg、bzr等。有关下载方法可参考$(INCLUDE_DIR)/download.mk和$(SCRIPT_DIR) /download.pl。由于本文使用的是自己开发的代码,所以没有此项。
PKG_MD5SUM:源代码文件的效验码。用于核对软件包是否下载正确。
PKG_CAT:源代码文件的解压方法。包括zcat, bzcat, unzip等。
PKG_BUILD_DIR:软件包编译目录。它的父目录为$(BUILD_DIR)。如果不指定,默认为$(BUILD_DIR)/$( PKG_NAME)-$( PKG_VERSION)。
还有一些有关源代码的定义如下:
PKG_SOURCE_SUBDIR
PKG_SOURCE_PROTO
PKG_SOURCE_MIRROR
PKG_MIRROR_MD5SUM
PKG_SOURCE_VERSION 2.2.2、第17行“include $(INCLUDE_DIR)/package.mk”
“include $(INCLUDE_DIR)/package.mk”一般在软件包的基本信息完成后再引入,他定义了用户态软件包的规则。
编译包分为用户态和内核模块,用户态软件包使用Package,内核模块使用KernelPackage。“$(INCLUDE_DIR)/kernel.mk”文件对于软件包为内核时不可缺少,“$(INCLUDE_DIR)/package.mk”应用在用户态。接下来讲述用户态软件包。用户程序的编译包以“Package/”开头,然后接着软件名,在Package定义中的软件名可以与软件包名不一样,而且可以多个定义。

第19行”define Package/luci-app-szloogson,包的名称为”luci-app-szloogson“。

      接下来定义的包括:
        SECTION:包的类型,预留。
        CATEGORY:分类,在menuconfig的菜单下将可以找到。
     SUBMENU:包在make menuconfig的位置,此处即在”LuCi/3. Applications“下。
        TITLE:用于软件包的简短描述,将显示在”make menuconfig“中。
        DESCRIPTION:用于软件包的详细描述,已放弃使用。如果使用DESCRIPTION将会提示“error DESCRIPTION:= is obsolete, use Package/PKG_NAME/description”。
        URL:软件包的下载位置。
        MAINTAINER:维护者选项。
        DEPENDS:与其他软件的依赖。即如编译或安装需要其他软件时需要说明。如果存在多个依赖,则每个依赖需用空格分开。依赖前使用+号表示默认显示,即对象没有选中时也会显示,使用@则默认为不显示,即当依赖对象选中后才显示。

第27行”define Package/luci-app-szloogson/description“

        软件包的详细描述,取代前面提到的DESCRIPTION详细描述。此处定义的信息将显示在”make menuconfig“中。

第31行”define Build/Prepare“

编译准备方法,对于网上下载的软件包不需要再描述。对于非网上下载或自行开发的软件包必须说明编译准备方法。本文所用的准备方法就是首先创建软件包目录,然后将源码拷贝到刚刚创建的目录中。按OpenWrt的习惯,一般把自己设计的程序全部放在src目录下。

第36行"define Build/Configure”

        Build/Configure:在Automake中需要进行“./configure”,所以本配置方法主要针对需要配置的软件包而设计,一般自行开发的软件包可以不在这里说明。本文设计的package由自己写makefile,所以此处没有定义。

第39行”define Build/Compile“

        编译方法,没有特别说明的可以不予以定义。如果不定义将使用默认的编译方法Build/Compile/Default。
        自行开发的软件包可以考虑使用下面的定义:
点击(此处)折叠或打开

define Build/Compile
   $(MAKE) -C $(PKG_BUILD_DIR) \
     $(TARGET_CONFIGURE_OPTS) CFLAGS="$(TARGET_CFLAGS) -I$(LINUX_DIR)/include"
endef
        本文此处指定了交叉编译器和体系结构。

第46行”define Package/luci-app-szloogson/install“

软件包的安装方法,包括一系列拷贝编译好的文件到指定位置。调用时会带一个参数,就是嵌入系统的镜像文件系统目录,因此$(1)表示嵌入系统的镜像目录。一般可以采用下面的方法:
点击(此处)折叠或打开

define Package/luci-app-szloogson/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/gsc3280_led $(1)/usr/sbin/
endef
INSTALL_DIR、INSTALL_BIN在”$(TOPDIR)/rules.mk“文件中定义,所以本Makefile必须引入$(TOPDIR)/rules.mk文件。
INSTALL_DIR :=install -d -m0755:创建所属用户可读写、执行,其他用户可读可执行的目录。
INSTALL_BIN:=install -m0755:编译好的文件到镜像文件目录。
安装文件放在files子目录下,不要与源代码文件目录“src”混在一起,以提高可读性。
如果用户态软件在boot时要自动运行,则需要在安装方法说明中增加自动运行的脚本文件安装和配置文件安装方法。
例如:
点击(此处)折叠或打开

define Package/luci-app-szloogson/install
#install shell
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/loogson.init $(1)/etc/init.d/loogson
#install config
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/loogson.config $(1)/etc/config/loogson
endef
使用清晰的文件扩展名,更方便安装识别文件。
Package/$(PKG_NAME)/preinst
软件包安装前处理方法,使用脚本语言,因此定义的第一行需要下面的格式
#!/bin/sh:调用时带入的参数为嵌入式系统的镜像目录。
Package/$(PKG_NAME)/postinst:软件包安装后处理方法,使用脚本语言。
Package/$(PKG_NAME)/prerm:软件包删除前处理方法,使用脚本语言
Package/$(PKG_NAME)/postrm:软件包删除后处理方法,使用脚本语言
程序接下来安装luci文件。

第66行”$(eval $(call BuildPackage,luci-app-szloogson))“

完成前面定义后,必须使用eval函数实现各种定义。其格式为:
对于一般软件包:$(eval $(call Package,$(PKG_NAME)))
或对于内核模块:$(eval $(call KernelPackage,$(PKG_NAME)))
如果一个软件包有多个程序,例如:一个应用程序有自己的内核模块,上面使用的“PKG_NAME”需要灵活变通。eval函数可能设计多个。也可以当成多个软件包处理。

2. 内核模块包定义

     Linux分为内核态和用户态。开发者开发的内核部分可以直接加入Linux的Kernel程序,也可以生成内核模块以便需要时装入内核。OpenWrt一般希望开发者生成内核模块,在Linux启动后自动装载或手工使用insmod命令装载。内核模块使用“KernelPackage”开头,其他与一般软件包基本相同。

     在内核模块定义中增加“SUBMENU”表示子菜单位置,在“$(INCLUDE)/kernel.mk”对内核模块定义了CATEGORY为kernel modules,所以内核模块在menuconfig中的主菜单为kernel modules,然后有下一级子菜单$(SUBMENU)。在子菜单下可以看到以kmod-$( PKG_NAME)项目。
     DEFAULT表示直接编入内核或产生内核模块,y表示直接编入内核,m表示产生内核模块。
     AUTOLOAD表示自动装入内核,一般表示方法为:
     AUTOLOAD:=$(call AutoLoad, $(PRIORITY),$(AUTOLOAD_MODS))

     AutoLoad的第一个参数$(PRIORITY)为优先级,01为最优先,99为最后装载。有关自动装载可以在/etc/modules.d目录下看到,第二个参数$(AUTOLOAD_MODS)模块名,每个模块名以空格符分隔。即可同时装载多个内核模块。

     在开发过程最好不要使用自动装载,需经过严格调试后再使用,可以减轻调试的工作量。

     用户态的软件包中没有内核模块的“AUTOLOAD”参数。如果软件需要在boot时自动运行,则需要在“/etc/init.d”增加相应的脚本文件。 脚本文件需要START参数,说明在boot时的优先级,如果在boot启动后再启动,则需要STOP参数。如果STOP参数存在,其值必须大于START。由“/etc/rc.d/S10boot”知道,装载内核模块的优先级为10,需要使用自己设计的内核模块的程序其START的值必须大于10。同样由“/etc/rc.d/S40network”知道,使用网络通信的程序其START的值必须大于40。

3. 脚本文件

     脚本文件需要start()和stop()两个函数,start()是执行程序,stop()是关闭程序。关闭程序一般需要执行killall命令。

     在(一)中我们讨论了点击“应用”后执行的脚本文件在“/etc/init.d/loogson”目录下,程序如下:

点击(此处)折叠或打开

#!/bin/sh /etc/rc.common
# (C) 2014 openwrt.org
# add by Davied Huang <apple_guet@126.com>
START=50
LED_BIN="/usr/sbin/gsc3280_led"
control_board()
{
    local ledstatus, lednum;
   
    config_get_bool ledstatus $1 ledstatus
   
    config_get lednum $1 lednum
   
    echo "${lednum} ${ledstatus}"
    ${LED_BIN} ${lednum} ${ledstatus}
}
start() {
    config_load loogson
    config_foreach control_board controlboard
}
stop() {
    config_load loogson
    #config_foreach stop_instance controlboard
}

说明:

  1. 在“start”函数中,首先使用“config_load”函数加载“/etc/config/”目录下的loogson配置文件。
  2. “config_foreach”遍历"/etc/init.d/loogson"配置文件中的Section,并且执行"control_board"函数。
  3. 在"control_board"函数中,使用“config_get_bool”获得操作LED的开关状态,config_get获得操作第几个LED。
  4. "config_load"、“config_foreach”、“config_get”和“config_get_bool”等函数由其他脚本提供,可以直接使用。
  5. 最后执行可执行文件,后面加上可执行文件需要的参数。该可执行文件的源码为:

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<asm/ioctl.h>
int main(int argc,char *argv[])
{
    int fd;
    if (argc != 3) {
        printf("wrong cmd!\n");
    }
    fd = open("/dev/led", O_RDWR);
    if(fd == -1){
        printf("open led failed!\n");
    }
    ioctl(fd, argv[1], argv[2]);   
       
    close(fd);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/161868.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C运算符与表达式

跟着肯哥&#xff08;不是我&#xff09;学运算符与表达式 运算符 在C语言中&#xff0c;运算符是一种用来执行特定操作的符号或关键字。它们用于对变量、常量和表达进行计算、逻辑判断和位操作等。 定义一般都当耳旁风了 运算符分类 算术运算符 -*/%加减乘除取模&#xff0c;…

浮点数运算精度丢失,如何解决

为什么浮点数运算的时候会有精度丢失的风险&#xff1f; 浮点数运算精度丢失代码演示&#xff1a; float a 2.0f - 1.9f; float b 1.8f - 1.7f; System.out.println(a);// 0.100000024 System.out.println(b);// 0.099999905 System.out.println(a b);// false为什么会出现…

everything排除目录

everything默认搜索所有文件&#xff0c;自己把没啥必要的目录都屏蔽掉&#xff0c;记录如下

ChatGPT/GPT4丨编程助手;AI画图;数据分析;科研/项目实现;提示词工程技巧;论文写作等

ChatGPT 在论文写作与编程方面也具备强大的能力。无论是进行代码生成、错误调试还是解决编程难题&#xff0c;ChatGPT都能为您提供实用且高质量的建议和指导&#xff0c;提高编程效率和准确性。此外&#xff0c;ChatGPT是一位出色的合作伙伴&#xff0c;可以为您提供论文写作的…

【微软技术栈】使用新的C#功能减少内存分配

本文内容 通过引用传递和返回引用安全上下文安全的上下文和 ref 结构统一内存类型通过参考安全提高性能 本节中介绍的技术可提高应用于代码中的热路径时的性能。热路径是代码库中在正常操作中经常重复执行的部分。将这些技术应用于不经常执行的代码将产生最小的影响。在进行任何…

[数据结构]-AVL树

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、AVL树基…

OpenGL 绘制线(Qt)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 这里同样对OpenGL中的绘制线操作进行封装,便于后续的操作,很多形状也都是基于线来生成的,如圆形等。 二、实现代码 LineDrawable.h #ifndef LINE_DRAWABLE_H #define LINE_DRAWABLE_H#include

IBM ELM—系统工程全生命周期管理平台

产品概述 Engineering Lifecycle Management是IBM提供的工程全生命周期管理组合工具&#xff0c;帮助企业降低开发成本&#xff0c;应对开发挑战并更快地发展其流程和实践。 随着产品变得更加复杂且数字化&#xff0c;传统的工程开发不再能及时且有效地满足系统工程的复杂度&a…

【Django-DRF】多年md笔记第5篇:Django-DRF的Request、Response和视图详解

本文从分析现在流行的前后端分离Web应用模式说起&#xff0c;然后介绍如何设计REST API&#xff0c;通过使用Django来实现一个REST API为例&#xff0c;明确后端开发REST API要做的最核心工作&#xff0c;然后介绍Django REST framework能帮助我们简化开发REST API的工作。 Dj…

[点云分割] 基于最小切割的分割

效果&#xff1a; 代码&#xff1a; #include <iostream> #include <vector>#include <pcl/point_types.h> #include <pcl/io/pcd_io.h> #include <pcl/visualization/cloud_viewer.h> #include <pcl/filters/filter_indices.h> #include…

Can‘t open the append-only file: Permission denied

redis rdb aof-CSDN博客 Cant open the append-only file: Permission denied E:\Document_Redis_Windows\redis-2.4.5-win32-win64\64bit E:\Document_Redis_Windows\redis-2.4.5-win32-win64\64bit\redis.conf 还是不行&#xff0c;就要修改权限了&#xff0c;windows【完全控…

matlab 最小二乘拟合平面并与XOY平面对齐

目录 一、算法原理二、代码实现1、绕原点对齐2、绕质心对齐三、结果展示1、绕原点对齐2、绕质心对齐四、测试数据本文由CSDN点云侠原创,原文链接。爬虫网站自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、算法原理 首先,使用最小二乘拟合平面…

priority_queue简单实现(优先级队列)(c++)

priority_queue priority_queue介绍逻辑实现框架调整算法adjust_up()adjust_down() 仿函数/比较函数仿函数特性 构造函数迭代器区间构造 完整优先级队列代码 priority_queue介绍 pri_que是一个容器适配器&#xff0c;它的底层是其他容器&#xff0c;并由这些容器再封装而来。类…

C语言指针相关练习题

​ C语言指针相关练习题 文章目录 C语言指针相关练习题题目一题目二题目三题目四题目五题目六题目七 题目一 #include <stdio.h> int main() {int a[5] { 1, 2, 3, 4, 5 };int *ptr (int *)(&a 1);printf( "%d,%d", *(a 1), *(ptr - 1));return 0; }…

[Unity+OpenAI TTS] 集成openAI官方提供的语音合成服务,构建海王暖男数字人

1.简述 最近openAI官方发布了很多新功能&#xff0c;其中就包括了最新发布的TTS语音合成服务的api接口。说到这个语音合成接口&#xff0c;大家可能会比较陌生&#xff0c;但是说到chatgpt官方应用上的聊天机器人&#xff0c;那个台湾腔的海王暖男的声音&#xff0c;可能就有印…

深度合成算法的基础与原理

深度合成算法是人工智能领域中备受瞩目的研究方向之一。它的应用范围涵盖了图像合成、文本生成、音频合成等多个领域&#xff0c;为人们提供了令人惊叹的创新和娱乐体验。本文将深入探讨深度合成算法的基础原理&#xff0c;了解它们是如何工作的以及它们在不同领域的应用。算法…

轻量封装WebGPU渲染系统示例<38>- 动态构建WGSL材质Shader(源码)

实现原理: 基于宏定义和WGSL功能文件实现 当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/DynamicShaderBuilding.ts 当前示例运行效果: 此示例基于此渲染系统实现&#xff0c;当前示例TypeScript源码如下&#x…

编写bat程序 快速开启 redis 服务

一键开启redis服务 编写txt文件&#xff0c;代码如下&#xff1a;cd /d E:\Redis\Redis-x64-5.0.14.1 redis-server.exe redis.windows.conf这里的redis的安装目录记得改成自己的 将文件后缀的.txt改成.bat&#xff0c;然后双击运行就可以啦

前缀和及差分数组

前缀和 原数组x0x1x2x3x4x5前缀和数组x0x0x1x0x1x2x0x1x2x3x0x1x2x3x4x0x1x2x3x4x5前缀和数组代数形式x0’x1’x2’x3’x4’x5’ 计算原数组某区间的和 sum[x1,x2,x3] 利用前缀和计算 x3-x0 x0x1x2x3-x0 x1x2x3 差分数组 x0x1x2x3x4x5原数组x0x1x2x3x4x5差分数组x0x1-x0x…

模拟电路定理

模拟电路是指由电子元件、电路拓扑和信号处理单元等构成的电路&#xff0c;用于模拟现实世界中的信号和系统。在模拟电路中&#xff0c;有许多重要的定理和规律&#xff0c;下面列举了一些常见的定理。 1. 基尔霍夫电流定律&#xff08;Kirchhoffs Current Law&#xff09; 基…