openwrt学习指南

2023-10-27

路由器的硬件构成

路由器的软件构成

路由器固件开发的一般流程

Openwrt常用命令

1.文件、目录类命令:cd cat rm touch mkdir Is mv grep
2.文本编辑器命令:ⅵ
3.权限类命令:chmod
4.模块命令:rmmod insmod modprobe Ismod
5.进程管理命令:ps top kill killall
6.文件下载上传工具:scp wget tftp
7.系统命令:mount dmesg reboot chpasswd data time du df
8.网络类命令:ifconfig arp route iptables netstat
9.OpenWrt专用命令:sysupgrade opkg

Makefile入门教程-基本方法

目标(target):依赖1 依赖2 依赖3 。。。依赖n(prerequisites)

        命令(command)

Makefile入门教程-特殊宏

 

Makefile四个动作 config、compile、install、clean 

common.mak 是Makefile的缩写

 all:libnvram.so libnvram.a nvram 定义了一个all 产生了libnvram.so、 libnvram.a 、nvram等三个文件 all在这里相当于隐含的compile

#
# This software is licensed under the Public Domain.
#

include $(TOPDIR)/rules.mk

PKG_NAME:=example1
PKG_VERSION:=0.1
PKG_RELEASE:=1
//这些是make menuconfig的配置 是必须的

PKG_MAINTAINER:=John Doe <john.doe@example.com>
PKG_LICENSE:=CC0-1.0
//这一部分可以直接放到src目录中去

include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk

define Package/example1
	SECTION:=utils
	# Select package by default
	#DEFAULT:=y
	CATEGORY:=Utilities
	TITLE:=Some different dummy application.
	URL:=https://www.example.com
endef
//这些是make menuconfig中能看到的信息

define Package/example1/description
	This is some dummy application.
endef
//这些是make menuconfig中能看到的信息(description描述)

//define Build/Configure 编译配置

define Build/Prepare
	mkdir -p $(PKG_BUILD_DIR)
	$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
//编译前

//define Build/Compile 编译
//有几个不是必须的,如果 不写 就是用默认的

define Package/example1/install
	$(CP) ./files/* $(1)/

	$(INSTALL_DIR) $(1)/usr/bin
	$(INSTALL_BIN) $(PKG_BUILD_DIR)/example1 $(1)/usr/bin/
endef
//安装

$(eval $(call BuildPackage,example1))

如何创建package

拿了一个别人的demo - otrx文件

 改第一层Makefile

在进行编译之前 可以先在修改的那个文件夹make一下查看是否报错 

src文件夹中的各项文件也需要修改

openwrt如何逆向解析包-百度

openwrt如何创建开机自启动

 开机启动一共涉及两个文件夹

/etc/init.d

/etc/rc.d

但实际上只会执行/etc/rc.d中的文件

openwrt中opkg应用实例

1 安装app时保留上一次的文件(升级时保留配置文件),通过preinst和 postinst 实现

1)在Makefile中加入preinst和 postinst //记得更新版本号

 

preinst 将 etc文件中的config 考入tmp目录中

postinst 将 tmp文件中的config 再考回到etc目录中 完成覆盖, 从而保证config文件的一致性

2)上传package 

scp myapp_4_mipsel_24kc.ipk root@192.168.1.1:/tmp

3) opkg高版本文件

opkg intall myapp_4_mipsel_24kc.ipk

2 升级后保留配置文件

注意点:一定要用sysupgrade升级 而不能用uboot升级 

1)创建config文件

2)在Makefile中加入 //相当于声明,则升级时会自动保留这个配置文件

define Package/myaoo/conffies

        /etc/config/myapp

        /etc/myapp.conf

endef

3)编译 make package/example/compile V=99

4) 让路由器和电脑虚拟机保持同一频段,然后上传package,上传至tmp目录

scp myapp_2_mipsel_24kc.ipk root@192.168.1.1:/tmp

5)在路由中修改配置,并用uci commit保存 

查看机型:cat /proc/cpuinfo  /  ubus call system board

6)使用sysupgrade 进行升级,查看文件是否保留

上传bin文件 scp openwrt-ramips-mt7620-psg1218b-squashfs-sysupgrade.bin root@192.168.1.1:/tmp

 升级:sysupgrade openwrt-ramips-mt7620-psg1218b-squashfs-sysupgrad //用串口能看到过程

openwrt Cron定时任务

1 每天晚上0点 重启路由

几分?几时?几日?几月?周几?

0        0        *        *        *

 

 

 

 设置定时任务 //测试时要熟练掌握 date 命令

2 每天晚上11:00~早上8:00 关闭LED灯/无线

3 周一~周五 关闭WIFI

 openwrt GPIO框架及其应用

GPIO:General-purpose input/output 输入/输出的接口

应用

1)LED灯 (USB WiFi)

软连接 使用GPIO控制 0 1 变化 会导致 CPU消耗

硬连接 引脚直接连接

2)复位键

3)WPS键

GPIO有几种访问方式

1)sysfs 文件形式

优点)不需要用c、可用Lua、Python

缺点)文件,所以速度慢,一般用于低速IO访问

2)ioctl 系统调用

优点)速度快

缺点)需要用c/c++

3)mmap 内存

用c语言、速度最快、跨平台

GPIO实验 output实验 蜂鸣器

电路连接图

1 进入路由控制台

2 进入 gpio目录 cd /sys/class/gpio

3 使能 42 号引脚 echo "42" > export

4 设置gpio口为推挽输出模式 echo "out" > direction

5 拉高电平:蜂鸣器响 echo "1" > value

 mmap实验

实验之前打开 make menuconfig

打开

 MediaTech(MTK) MT7628 MT7688 Linux 下使用mmap实现用户态 GPIO 驱动

/* forgotfun.org 佐须之男 */

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


#define MMAP_PATH    "/dev/mem"


#define RALINK_GPIO_DIR_IN        0
#define RALINK_GPIO_DIR_OUT        1

#define RALINK_REG_PIOINT        0x690
#define RALINK_REG_PIOEDGE        0x6A0
#define RALINK_REG_PIORENA        0x650
#define RALINK_REG_PIOFENA        0x660
#define RALINK_REG_PIODATA        0x620
#define RALINK_REG_PIODIR        0x600
#define RALINK_REG_PIOSET        0x630
#define RALINK_REG_PIORESET        0x640

#define RALINK_REG_PIO6332INT        0x694
#define RALINK_REG_PIO6332EDGE        0x6A4
#define RALINK_REG_PIO6332RENA        0x654
#define RALINK_REG_PIO6332FENA        0x664
#define RALINK_REG_PIO6332DATA        0x624
#define RALINK_REG_PIO6332DIR        0x604
#define RALINK_REG_PIO6332SET        0x634
#define RALINK_REG_PIO6332RESET        0x644

#define RALINK_REG_PIO9564INT        0x698
#define RALINK_REG_PIO9564EDGE        0x6A8
#define RALINK_REG_PIO9564RENA        0x658
#define RALINK_REG_PIO9564FENA        0x668
#define RALINK_REG_PIO9564DATA        0x628
#define RALINK_REG_PIO9564DIR        0x608
#define RALINK_REG_PIO9564SET        0x638
#define RALINK_REG_PIO9564RESET        0x648


static uint8_t* gpio_mmap_reg = NULL;
static int gpio_mmap_fd = 0;

static int gpio_mmap(void)
{
    if ((gpio_mmap_fd = open(MMAP_PATH, O_RDWR)) < 0) {
        fprintf(stderr, "unable to open mmap file");
        return -1;
    }

    gpio_mmap_reg = (uint8_t*) mmap(NULL, 1024, PROT_READ | PROT_WRITE,
        MAP_FILE | MAP_SHARED, gpio_mmap_fd, 0x10000000);
    if (gpio_mmap_reg == MAP_FAILED) {
        perror("foo");
        fprintf(stderr, "failed to mmap");
        gpio_mmap_reg = NULL;
        close(gpio_mmap_fd);
        return -1;
    }

    return 0;
}

int mt76x8_gpio_get_pin(int pin)
{
    uint32_t tmp = 0;

    /* MT7621, MT7628 */
    if (pin <= 31) {
        tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIODATA);
        tmp = (tmp >> pin) & 1u;
    } else if (pin <= 63) {
        tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO6332DATA);
        tmp = (tmp >> (pin-32)) & 1u;
    } else if (pin <= 95) {
        tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO9564DATA);
        tmp = (tmp >> (pin-64)) & 1u;
        tmp = (tmp >> (pin-24)) & 1u;
    }
    return tmp;

}

void mt76x8_gpio_set_pin_direction(int pin, int is_output)
{
    uint32_t tmp;

    /* MT7621, MT7628 */
    if (pin <= 31) {
        tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIODIR);
        if (is_output)
            tmp |=  (1u << pin);
        else
            tmp &= ~(1u << pin);
        *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIODIR) = tmp;
    } else if (pin <= 63) {
        tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO6332DIR);
        if (is_output)
            tmp |=  (1u << (pin-32));
        else
            tmp &= ~(1u << (pin-32));
        *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO6332DIR) = tmp;
    } else if (pin <= 95) {
        tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO9564DIR);
        if (is_output)
            tmp |=  (1u << (pin-64));
        else
            tmp &= ~(1u << (pin-64));
        *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO9564DIR) = tmp;
    }
}

void mt76x8_gpio_set_pin_value(int pin, int value)
{
    uint32_t tmp;

    /* MT7621, MT7628 */
    if (pin <= 31) {
        tmp = (1u << pin);
        if (value)
            *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIOSET) = tmp;
        else
            *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIORESET) = tmp;
    } else if (pin <= 63) {
        tmp = (1u << (pin-32));
        if (value)
            *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO6332SET) = tmp;
        else
            *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO6332RESET) = tmp;
    } else if (pin <= 95) {
        tmp = (1u << (pin-64));
        if (value)
            *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO9564SET) = tmp;
        else
            *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO9564RESET) = tmp;
    }
}

int main(int argc, char **argv)
{
    int ret = -1;

    if (gpio_mmap())
        return -1;

    printf("get pin 39 input %d\n", mt76x8_gpio_get_pin(39));
    printf("get pin 40 input %d\n", mt76x8_gpio_get_pin(40));
    printf("get pin 41 input %d\n", mt76x8_gpio_get_pin(41));
    printf("get pin 42 input %d\n", mt76x8_gpio_get_pin(42));

    
    printf("set pin 39 output 1\n");
    mt76x8_gpio_set_pin_direction(39, 1);
    mt76x8_gpio_set_pin_value(39, 1);
    printf("set pin 40 output 0\n");
    mt76x8_gpio_set_pin_direction(40, 1);
    mt76x8_gpio_set_pin_value(40, 0);
    printf("set pin 41 output 1\n");
    mt76x8_gpio_set_pin_direction(41, 1);
    mt76x8_gpio_set_pin_value(41, 1);
    printf("set pin 42 output 0\n");
    mt76x8_gpio_set_pin_direction(42, 1);
    mt76x8_gpio_set_pin_value(42, 0);

    while (1)
    {
        mt76x8_gpio_set_pin_value(42, 0);
        mt76x8_gpio_set_pin_value(42, 1);
    }
    close(gpio_mmap_fd);

    return ret;
}

 OpenWrt 基于GPIO、Hotplug、DTS 的按键实验

DTS是Device Tree Source的缩写,用来描述设备的硬件细节。在过去的ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码,相当多数的代码只是在描述板级细节,而这些板级细节对于内核来讲,不过是垃圾,如板上的platform设备、resource、i2c_board_info、spi_board_info以及各种硬件的platform_data。为了去掉这些垃圾代码,Linux采用DTS这种新的数据结构来描述硬件设备。采用Device Tree后,许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码。

.dtsi文件 都属于公共文件 ,能被其他文件依赖的

按键实验

选择GPIO1 偏移量6 则代表 GPIO口为32+6=38

GPIO_ACTIVE_LOW 代表低电平触发

KEY_WPS_BUTTON 定义了一个宏 代表了wps键

你现在要修改一个属于自己DTS ,先找到openwrt文件系统中的DTS源文件

 OpenWrt vlan、switch、bridge、wans、lan、wlan、wifi等相关概念解析

 

 

OpenWrt基于DTS适配RAM、Flash、复位键、波特率、端口布局实验 

openwrt软件移植

先从github上,下拉压缩包至本地,然后解压缩,config(下载以后会出现configure.in 我们需要autoconf,然后就会生成configure)、make。这样就可以查看软件所依赖的各类库(动态、静态)。

在自己的例子目录中新建wificat文件夹,并新建Makefile和src

 回到下载的软件包 make distclean 清空编译的文件

然后复制粘贴到src文件夹下, make menuconfig选择文件夹,编译,上传,运行软件包

openwrt静态库和动态库

动态库:.so文件 运行时才加载,程序小,通常情况release下动态库

静态库:.a 直接编译到程序中,程序大,debug时使用静态库

xx.c->xx.o-LD-xx.so

                -AR-xx.a

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

openwrt学习指南 的相关文章

  • 一个网工(网络工程师)七年的职业血泪史....

    前言 一个工作了七年的老网工 上家公司待了五年 现在这家公司也快三年了 分享一些我自己学习网络安全路上的一些经历 也算是帮大家少走些弯路 一 如何学习网络安全 1 不要试图以编程为基础去学习网络安全 不要以编程为基础再开始学习网络安全 一般
  • 网络基础面试题(二)

    11 什么是网桥 防火墙的端口防护是指什么 网桥是一种网络设备 用于连接两个或多个局域网 LAN 并转发数据包 它能够根据MAC地址来识别和转发数据 提高网络的传输效率和安全性 防火墙的端口防护是指对防火墙上的各个端口进行保护和限制 只允许
  • 这些专利知识你知道吗?

    专利作为一种重要的知识产权保护形式 专利不仅成为了企业核心竞争力的重要组成部分 也成为了国家创新发展的重要支撑 专利是指国家专利主管机关授予发明创造申请人的一种专有权 这种专有权具有独占性 排他性和法律强制性 能够为持有者带来经济利益和竞争
  • 基于成本和服务质量考虑的不确定性下,电动汽车充电网络基础设施需求预测和迭代优化的分层框架研究(Python代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Python代码 数据
  • 【信道估计】【MIMO】【FBMC】未来移动通信的滤波器组多载波调制方案(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码及文章
  • 前端必备的 web 安全知识手记

    前言 安全这种东西就是不发生则已 一发生则惊人 作为前端 平时对这方面的知识没啥研究 最近了解了下 特此沉淀 文章内容包括以下几个典型的 web 安全知识点 XSS CSRF 点击劫持 SQL 注入和上传问题等 下文以小王代指攻击者 话不多
  • WEB前端常见受攻击方式及解决办法总结

    一个网址建立后 如果不注意安全问题 就很容易被人攻击 下面讨论一下集中漏洞情况和放置攻击的方法 一 SQL注入 所谓的SQL注入 就是通过把SQL命令插入到web表单提交或输入域名或页面请求的查询字符串 最终达到欺骗服务器执行恶意的SQL命
  • 如何使用Imagewheel搭建一个简单的的私人图床无公网ip也能访问

    文章目录 1 前言 2 Imagewheel网站搭建 2 1 Imagewheel下载和安装 2 2 Imagewheel网页测试 2 3 cpolar的安装和注册 3 本地网页发布 3 1 Cpolar临时数据隧道
  • 基于java的物业管理系统设计与实现

    基于java的物业管理系统设计与实现 I 引言 A 研究背景和动机 物业管理系统是指对物业进行管理和服务的系统 该系统需要具备对物业信息 人员信息 财务信息等进行管理的能力 基于Java的物业管理系统设计与实现的研究背景和动机主要体现在以下
  • 网络安全(黑客)自学启蒙

    一 什么是网络安全 网络安全是一种综合性的概念 涵盖了保护计算机系统 网络基础设施和数据免受未经授权的访问 攻击 损害或盗窃的一系列措施和技术 经常听到的 红队 渗透测试 等就是研究攻击技术 而 蓝队 安全运营 安全运维 则研究防御技术 作
  • 网络安全基础知识面试题库

    1 基于路由器的攻击手段 1 1 源IP地址欺骗式攻击 入侵者从外部传输一个伪装成来自内部主机的数据包 数据包的IP是 内网的合法IP 对策 丢弃所有来自路由器外端口 却使用内部源地址的数据包 1 2 源路由攻击 入侵者让数据包循着一个不可
  • 国外拨号VPS指南:开启你的全球网络之旅

    在当今数字化时代 互联网已经成为了我们生活的一部分 而要在全球范围内畅通无阻地访问互联网 拥有一个可靠的国外拨号VPS是非常重要的 无论您是为了工作 学习还是娱乐 国外拨号VPS都可以为您提供更广泛的网络体验 本文将为您提供国外拨号VPS的
  • 搞懂 三次握手四次挥手

    计算机网络体系结构 在学习TCP 三次握手四次挥手之前 让我们先来看下计算机网络分层 主要分为OSI模型和TCP IP模型 OSI模型比较复杂且学术化 所以我们实际使用的TCP IP模型 以连接Mysql服务器为例理解这五层 应用层 应用层
  • 静态综合实验

    1 IP地址划分 192 168 1 0 27 用于主干拆分 192 168 1 32 27 用于用户拆分 192 168 1 64 27 用于用户拆分 192 168 1 96 27 用于用户拆分 192 168 1 128 27 用于用
  • DSCA190V 57310001-PK

    DSCA190V 57310001 PK DSCA190V 57310001 PK 具有两个可编程继电器功能 并安装在坚固的 XP 外壳中 DSCA190V 57310001 PK 即可使用 只需最少的最终用户校准 DSCA190V 573
  • “dat”协议能否有效支持视频直播?

    我希望能够通过以下方式实时流式传输视频 或任何其他大型且不断修改 附加的文件 dat Here https github com beakerbrowser webdb performance它说 dat 协议不支持文件级别的部分更新 这意
  • WCF 是否支持点对点实现?

    我正在尝试在 LAN 内实现点对点消息传递和文件共享实用程序 那么 WCF 支持 p2p 吗 有人尝试过通过 WCF 进行文件共享吗 是的 它确实 请参见如何在对等网络中设计状态共享 http msdn microsoft com en u
  • 是否可以通过互联网在两个移动设备 (iPhone) 之间连接套接字?

    是否可以通过互联网在两个移动设备 iPhone 之间连接套接字 我正在尝试发现每个设备的IP并直接连接 我知道可以使用 Bonjour 来完成 但这只适用于本地网络 我需要通过互联网在两个设备之间建立高速连接 Thanks 如果你有两个 I
  • 比特币客户端如何确定第一个连接的IP地址?

    据我所知 比特币是一种 p2p 协议P2P协议必须有一个专用的中央服务器 https stackoverflow com questions 310607 peer to peer methods of finding peers 但据说比
  • 使用 STUN 打孔

    我目前正在尝试通过 Internet 发送 UDP 消息 并且必须为端点 A 和 B 都位于 NAT 后面 设置防火墙 为此 我想使用 STUN 服务器进行打孔 当 A 创建对 STUN 服务器的请求 例如 私有 85 1 1 12 600

随机推荐

  • bootstrap知识总结

    Bootstrap框架 一 Bootstrap简介 Bootstrap是一个用于快速开发Web应用程序和网站的前端框架 Bootstrap是基于HTML CSS JavaScript的 二 Bootstrap 特点 1 跨设备 跨浏览器 可
  • Angular4之动画

    在angular里面 动画的本质 是在一定时间 由一个状态转换到另一个状态 期间的过渡效果就是显示出来就是动画 例如 import Component Input from angular core import trigger state
  • 基于MCGS与PLC的四路抢答器

    实验要求 四路抢答器每一位抢答的选手都有一个抢答按钮 1号抢答按钮为SB1 2号抢答按钮为SB2 3号抢答按钮为SB3 4号抢答按钮为SB4 以及各位抢答选手的指示灯 主持人的位置设有抢答开始按钮SB5以及清零按钮SB6 另外系统中 有一个
  • 读《影响力》西奥迪尼---笔记

    读 影响力 西奥迪尼 笔记 1 本书框架 包括互惠 承诺与一致 社会认同 喜爱 权威 稀缺六大影响力武器 2 文书意图 从原理 成因上讲述这六个影响力武器对我们的影响 以及商家或者其他想要获利的如何利用影响力武器获取利益 意图说服我们如何拒
  • dvwa靶场通关(十二)

    第十二关 Stored Cross Site Scripting XSS 存储型xss low 这一关没有任何防护 直接输入弹窗代码 弹窗成功 medium 先试试上面的代码看看 有没有什么防护 发现我们的script标签不见了 应该是被过
  • 在JSP编译的时候,服务器内部做了什么?

    在JSP第一次获得请求时 不管请求来自于客户端浏览器还是服务器上的servlet JSP文件将被JSP引擎 JSP engine 转换成为一个servlet 而这个引擎本身也是一个servlet 在JSWDK 它就是 JspServlet
  • OpenCV - Mat、滤波、卷积的实现

    1 Mat数据类型 创建图像 Mat M 2 2 CV 8UC3 Scalar 0 0 255 改变图像尺寸 M create 4 4 CV 8UC2 快速创建图像的集中方法 Mat E Mat eye 4 4 CV 64F Mat F M
  • 子网掩码详解

    IP地址 IP地址被用来给Internet上的电脑一个编号 大家日常见到的情况是每台联网的PC上都需要有IP地址 才能正常通信 我们可以把 个人电脑 比作 一台电话 那么 IP地址 就相当于 电话号码 而Internet中的路由器 就相当于
  • C++设计模式

    设计模式有 6 大设计原则 单 职责原则 就 个类 应该仅有 个引起它变化的原因 开放封闭原则 软件实体可以扩展 但是不可修改 即 对需求 对程序的改动可以通过增加代码来完成 但是不能改动现有的代码 代换原则 个软件实体如果使 的是 个基类
  • HTML和CSS实现京东登录页面(html,css代码详解)

    HTML代码 基本布局 QQ 2248557717 下载链接地址 https download csdn net download dwjdj 15807158
  • STM32 C语言使用 memset清空结构体 导致改变其他结构体数据的问题

    首先 在C语言中 清空结构体的方法 我们一般会采用 memset函数 其原型是 void memset void ptr int value size t num 函数功能 填充内存块 将ptr指向的内存块的前num个字节设置为指定值 va
  • 2021年华中杯A题(马赛克瓷砖选色问题)详细分析

    目录 一 基本介绍 1 1 题目描述 1 2 待解决问题 二 问题分析与求解 2 1 问题一分析与求解 2 2 问题二分析与求解 2 3 问题三分析与求解 三 完整代码 四 总结 一 基本介绍 1 1 题目描述 马赛克瓷砖是一种尺寸较小 常
  • 七、JDK1.7中HashMap扩容机制

    导读 前面文章一 深入理解 Java集合初篇 中我们对Java的集合体系进行一个简单的分析介绍 上两篇文章二 Jdk1 7和1 8中HashMap数据结构及源码分析 三 JDK1 7和1 8HashMap数据结构及源码分析 续 中我们分别对
  • 基于货运APP的全栈开发实践:后端用PHP,前端用Uni-app实现兼容性

    在上一篇文章中 我们介绍了货运APP如何助您提高运输效率 本文将重点介绍该货运APP的技术实现 并探讨后端和前端所使用的技术以及如何实现兼容性 后端技术实现 PHP 货运APP的后端采用PHP作为开发语言 下面是一些关键点的介绍 服务器环境
  • [MySQL]存储过程与函数

    文章目录 1 存储过程概述 1 1 含义 1 2 执行过程 1 3 好处 1 4 与视图 函数的对比 1 5 存储过程的分类 2 创建存储过程 2 1 语法 2 2 设置结束标志 2 3 创建存储过程示例 2 3 1 准备工作 2 3 2
  • 闲扯测试工程师之发展(觉得不错,拿来与大家分享)

    一 测试工程师的历史 我算是接触互联网测试工作比较早的一批人了 在2010年研二实习的时候就开始在一家加拿大的企业做测试开发工程师了 2012年毕业的时候 貌似互联网行业开始有专职的测试人员 而且不少中小型公司还没有专职的测试人员 程序的质
  • Java输入char类型的方法

    C 中可以用输入流cin轻松的完成对int char String double等等基本数据类型的输入 而JAVA中则必须使用Scanner类 头文件java util Scanner 对于其他的数据类型Scanner类提供了直接的函数使用
  • 充电器 蓝桥杯十四届模拟 python

    问题描述 小蓝有一个充电器 可以使用不同的电压和电流充电 给定充电器工作的记录 请计算在这个记录期间总共通过充电传输了多少电能 输入格式 输入第一行包含一个整数 n 表示记录的条数 接下来 n 行 每行包含一个时刻 T 和两个非负整数 U
  • 方格运动问题

    常见的一个经典问题 给定一个方格子 另左上角坐标为 0 0 右下角坐标为 M N 从左上角开始每次只能向右走或者向下走 最后达到右下角的位置 求一共有多少种不同的路径 数学的想法 对于计算这个问题的时候 可以去思考 不管怎样 从上往下从左往
  • openwrt学习指南

    路由器的硬件构成 路由器的软件构成 路由器固件开发的一般流程 Openwrt常用命令 1 文件 目录类命令 cd cat rm touch mkdir Is mv grep 2 文本编辑器命令 3 权限类命令 chmod 4 模块命令 rm