内核移植

半导体厂商会从 Linux内核官网下载某个版本,将其移植到自己的 CPU上,测试成功后就会将其开放给该半导体厂商的 CPU开发者。开发者下载其提供的 Linux内核,然后将其移植到自己的产品上。

本文使用 NXP提供的 Linux内核源码进行移植,文件名为:linux-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2

1. NXP官方开发板Linux内核编译测试

编译内核之前需要先在ubuntu上安装lzop库,另外,图形化配置工具还需要ncurses库支持,安装命令为:

sudo apt-get install lzop
sudo apt-get install build-essential
sudo apt-get install libncurses5-dev

在Ubuntu中新建一个文件夹,然后将linux内核压缩包拷贝到文件夹中并解压,解压命令为:

tar -vxf linux-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2
1.1 配置并编译Linux内核

编译Linux内核之前要先配置Linux内核。每个板子都有其对应的默认配置文件,这些配置文件保存在“arch/arm/configs”目录中。imx_v7_defconfigimx_v7_mfg_defconfig都可以作为NXP官方开发板IMX6ULL EVK的默认配置文件,但是一般都使用后者,因为后者编译出来的zImage可以通过NXP官方提供的MfgTool工具进行烧写

进入到Ubuntu中的Linux源码根目录下,执行如下命令:

#编译之前先清理
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
#配置Linux内核
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v7_mfg_defconfig
#编译Linux内核
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16

编译完成后,我们会得到两个重要文件:

  • Linux内核镜像文件:存放路径为 arch/arm/boot/zImage
  • IMX6ULL EVK开发板对应的设备树文件:存放路径为 arch/arm/boot/dts/imx6ull-14x14-evk.dtb
1.2 Linux内核启动测试

将上一节中生成的zImage和imx6ull-14x14-evk.dtb这两个文件下载到IMX6U-ALPHA开发板上进行测试。

⏩ 首先检查uboot中的环境变量bootargs

console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw

⏩ 然后拷贝zImage和imx6ull-14x14-evk.dtb这两个文件到Ubuntu的tftp目录下

cp arch/arm/boot/zImage /home/andyxi/linux/tftp
cp arch/arm/boot/dts/imx6ull-14x14-evk.dtb /home/andyxi/linux/tftp

⏩ 最后启动开发板,进入uboot命令行模式,输入如下命令以上两个文件下载到开发板中并启动

tftp 80800000 zImage
tftp 83000000 imx6ull-14x14-evk.dtb
bootz 80800000 - 83000000

⏩ 内核启动后,如果EMMC中存在根文件系统,就可以进入到Linux系统里使用命令进行操作,如下图示

1.3 根文件系统缺失错误

Linux内核启动以后是需要根文件系统的,根文件系统存在哪里由uboot的bootargs环境变量决定的,bootargs会传递给Linux内核作为命令行参数,比如上一节的bootargs环境变量值为:

console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw

其中“root=/dev/mmcblk1p2”表示根文件系统存储在/dev/mmcblk1p2中(即EMMC的分区2),由于IMX6UL-ALPHA开发板在出厂时已经将根文件系统烧写到了EMMC的分区2中

如果不设置文件系统路径或者路径设置错误,开发板从网络启动后会提示内核崩溃,VFS(虚拟文件系统)不能挂在文件系统。下图中为不设置文件系统路径以及后续出现的报错信息

2. 在Linux中添加自已的开发板

2.1 添加开发板默认配置文件

⏩ 将arch/arm/configs目录下的imx_v7_mfg_defconfig文件重新复制一份并命名为imx_andyxi_emmc_defconfig,此后该文件就是自已开发板的默认配置文件了

cd arch/arm/configs
cp imx_v7_mfg_defconfig imx_andyxi_emmc_defconfig
2.2 添加开发板对应的设备树文件

⏩ 将arch/arm/boot/dts目录下的imx6ull-14x14-evk.dts文件重新复制一份并命名为imx6ull-andyxi-emmc.dts,.dts是设备树源码文件,编译Linux的时候会将其编译成.dtb文件

cd arch/arm/boot/dts
cp imx6ull-14x14-evk.dts imx6ull-andyxi-emmc.dts

⏩ 修改arch/arm/boot/dts/Makefile文件,添加开发板设备树文件

########## arch/arm/boot/dts/Makefile代码段 ##########
dtb-$(CONFIG_SOC_IMX6ULL) +=          \imx6ull-14x14-ddr3-arm2.dtb            \imx6ull-14x14-ddr3-arm2-adc.dtb        \............imx6ull-14x14-evk-usb-certi.dtb        \imx6ull-andyxi-emmc.dtb            \............
2.3 编译测试

⏩ 添加完IMX6UL-ALPHA EMMC开发板后,可以创建一个编译脚本imx6ull_andyxi_emmc.sh

#!/bin/sh
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_andyxi_emmc_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16

⏩ 执行 shell 脚本 imx6ull_andyxi_emmc.sh 编译 Linux 内核, 命令如下:

chmod 777 imx6ull_andyxi_emmc.sh     #给予可执行权限
./imx6ull_andyxi_emmc.sh             #执行shell脚本编译内核

⏩ 编译完成后,将zImage和imx6ull-andyxi-emmc.dtb文件拷贝至tftp目录下,然后重启开发板,在uboot命令模式中使用tftp命令下载这两个文件并启动开发板

tftp 80800000 zImage
tftp 83000000 imx6ull-andyxi-emmc.dtb
bootz 80800000 – 83000000

⏩ 出现如下图示内容就表示Linux内核启动成功

3. CPU主频和网络驱动修改

3.1 CPU主频修改

确保根文件系统可用,重启开发板后进入终端,输入如下命令查看CPU信息

cat /proc/cpuinfo

结果如下图示

上图中的"BogoMIPS"是衡量处理器运行速度的一个参数,处理器性能越强,主频越高,BogoMIPS值就越大

BogoMIPS值只能粗略的计算CPU性能,可以通过以下目录中的文件来查看CPU工作频率相关的信息:

cd /sys/devices/system/cpu/cpu0/cpufreq

上述目录里的文件如下图示,可以通过"cat"命令开查看各文件里的内容

上述目录中的文件含义如下

  • cpuinfo_cur_freq
  • cpuinfo_max_freq
  • cpuinfo_min_freq
  • cpuinfo_transition_latency
  • scaling_available_frequencies
  • scaling_available_governors
  • scaling_cur_freq
  • scaling_driver
  • scaling_governors
  • scaling_max_freq
  • scaling_min_freq

下面介绍如何修改调频策略:配置Linux内核,将调频策略选择为performance,从而让CPU一直工作在792MHz

  • 方法一:修改imx_andyxi_emmc_defconfig文件来实现
#CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y   #屏蔽此处的默认调频策略(ondemand)
CONFIG_CPU_FREQ_GOV_POWERSAVE=y          #使能powersave策略
CONFIG_CPU_FREQ_GOV_USERSPACE=y        #使能userspace策略
CONFIG_CPU_FREQ_GOV_INTERACTIVE=y      #使能interactive策略
CONFIG_CPU_FREQ_GOV_ONDEMAND=y         #使能ondemand策略

修改完后,重新编译内核之前,需要先清理工程

  • 方法二:通过图形化界面配置调频策略,输入"make menuconfig"打开界面

修改完后,重新编译内核之前,不能清理工程

3.2 使能8线EMMC驱动

IMX6UL-ALPHA EMMC开发板上的EMMC采用8位数据线,而Linux内核里的EMMC默认是4线模式的,可以通过修改为8线模式来提高运行速度


修改方法:直接修改设备树源码文件imx6ull-andyxi-emmc.dts,修改完成后使用make dtbs重新编译设备树即可

########## 修改后的imx6ull-andyxi-emmc.dts代码段 ##########
&usdhc2 {pinctrl-names = "default", "state_100mhz", "state_200mhz";pinctrl-0 = <&pinctrl_usdhc2_8bit>;pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;bus-width = <8>;non-removable;status = "okay";
};
3.3 修改网络驱动

IMX6UL-ALPHA EMMC开发板的网络和NXP官方开发板的网络硬件不同,网络PHY芯片由KSZ8081换为了LAN8720A,两个网络PHY芯片的复位IO也不同,所以Linux内核自带的网络驱动无法驱动IMX6UL-ALPHA EMMC开发板的网络,需要做如下更改
⏩ 修改LAN8720的复位引脚驱动:ENET1复位引脚ENET1_RST连接在IMX6ULL的SNVS_TAMPER7引脚上;ENET2复位引脚ENET_RST连接在IMX6ULL的SNVS_TAMPER8引脚上

在设备树源码文件中找到如下代码段,此处SNVS_TAMPER7/8两个引脚被初始化为了SPI4的IO,所以需要删除

########## imx6ull-andyxi-emmc.dts 代码段 ##########
pinctrl_spi4: spi4grp {fsl,pins = <MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10 0x70a1MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11 0x70a1#    MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x70a1      #删除此行#  MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x80000000  #删除此行>;
};

在设备树源码文件中找到如下代码段,此处SNVS_TAMPER7/8两个引脚被设置为了SPI4的功能IO,所以需要删除

########## imx6ull-andyxi-emmc.dts 代码段 ##########
spi4 {compatible = "spi-gpio";pinctrl-names = "default";pinctrl-0 = <&pinctrl_spi4>;
#   pinctrl-assert-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;   #删除此行
......
......# cs-gpios = <&gpio5 7 0>;                          #删除此行
};

在设备树源码文件中找到名为“iomuxc_snvs”节点,在里面添加网络复位引脚配置信息

########## imx6ull-andyxi-emmc.dts 代码段 ##########
&iomuxc_snvs {pinctrl-names = "default_snvs";pinctrl-0 = <&pinctrl_hog_2>;imx6ul-evk {...... ......# enet1 复位配置pinctrl_enet1_reset: enet1resetgrp {fsl,pins = <# used for enet1 reset #MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x10B0>;};#enet2 复位配置pinctrl_enet2_reset: enet2resetgrp {fsl,pins = <# used for enet2 reset #MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x10B0>;};};
};

⏩ 修改LAN8720的网络时钟引脚驱动

在设备树源码文件中找到如下代码段,将ENET1和ENET2的网络时钟引脚的电气属性值由0x4001b031(默认值)改为0x4001b009

########## imx6ull-andyxi-emmc.dts 代码段 ##########
pinctrl_enet1: enet1grp {fsl,pins = <MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN 0x1b0b0MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER 0x1b0b0MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN 0x1b0b0MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b009 #默认值为0x4001b031>;
};pinctrl_enet2: enet2grp {fsl,pins = <MX6UL_PAD_GPIO1_IO07__ENET2_MDC 0x1b0b0MX6UL_PAD_GPIO1_IO06__ENET2_MDIO 0x1b0b0MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN 0x1b0b0MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER 0x1b0b0MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00 0x1b0b0MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01 0x1b0b0MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN 0x1b0b0MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00 0x1b0b0MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01 0x1b0b0MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b009 #默认值为0x4001b031>;
};

⏩ 修改fec1和fec2节点的pinctrl1-0属性

在设备树源码文件中找到“fec1”和“fec2”这两个节点,修改其中的“pinctrl-0”属性值,修改后的代码如下示

########## imx6ull-andyxi-emmc.dts 代码段 ##########
&fec1 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_enet1&pinctrl_enet1_reset>;phy-mode = "rmii";......status = "okay";
};&fec2 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_enet2&pinctrl_enet2_reset>;phy-mode = "rmii";......
};

⏩ 修改LAN8720的PHY地址

在设备树源码文件中找到如下代码段,设置ENET1的LAN8720A地址(0x0),设置ENET2的LAN8720A地址(0x1),以及其他相关设置,修改后的代码如下示

########## imx6ull-andyxi-emmc.dts 代码段 ##########
&fec1 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_enet1&pinctrl_enet1_reset>;phy-mode = "rmii";phy-handle = <&ethphy0>;phy-reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>;    #添加了ENET1复位引脚,低电平有效phy-reset-duration = <200>;                        #复位低电平持续时间为200msstatus = "okay";
};&fec2 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_enet2&pinctrl_enet2_reset>;phy-mode = "rmii";phy-handle = <&ethphy1>;phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;  #添加了ENET2复位引脚,低电平有效phy-reset-duration = <200>;                        #复位低电平持续时间为200msstatus = "okay";mdio {#address-cells = <1>;#size-cells = <0>;ethphy0: ethernet-phy@0 {    #ethernet-phy@后面的数字式PHY的地址compatible = "ethernet-phy-ieee802.3-c22";#表明PHY芯片是SMSC公司的,Linux内核会找到SMSC的PHY芯片驱动来驱动LAN8720Asmsc,disable-energy-detect;    reg = <0>;   #也表示PHY地址};ethphy1: ethernet-phy@1 {   #ethernet-phy@后面的数字式PHY的地址compatible = "ethernet-phy-ieee802.3-c22";#表明PHY芯片是SMSC公司的,Linux内核会找到SMSC的PHY芯片驱动来驱动LAN8720Asmsc,disable-energy-detect;reg = <1>;};};
};

⏩ 修改fec_main.c文件

要 在 I.MX6ULL 上 使 用 LAN8720A , 需 要 修 改 一 下 Linux 内 核 源 码 , 打 开
drivers/net/ethernet/freescale/fec_main.c,找到函数 fec_probe,在 fec_probe 中加入如下代码

static int fec_probe(struct platform_device *pdev)
{struct fec_enet_private *fep;struct fec_platform_data *pdata;struct net_device *ndev;int i, irq, ret = 0;struct resource *r;const struct of_device_id *of_id;static int dev_id;struct device_node *np = pdev->dev.of_node, *phy_node;int num_tx_qs;int num_rx_qs;/* 设置 MX6UL_PAD_ENET1_TX_CLK 和 MX6UL_PAD_ENET2_TX_CLK* 这两个 IO 的复用寄存器的 SION 位为 1,以下为添加的代码 */void __iomem *IMX6U_ENET1_TX_CLK;void __iomem *IMX6U_ENET2_TX_CLK;IMX6U_ENET1_TX_CLK = ioremap(0X020E00DC, 4);writel(0X14, IMX6U_ENET1_TX_CLK);IMX6U_ENET2_TX_CLK = ioremap(0X020E00FC, 4);writel(0X14, IMX6U_ENET2_TX_CLK);......return ret;
}

⏩ 配置Linux内核,使能LAN8720驱动

输入“make menuconfig”,打开图形化配置解密,选择使能LAN8720A的驱动,路径如下
-> Device Drivers -> Network device support -> PHY Device support and infrastructure -> Drivers for SMSC PHYs

⏩ 修改smsc.c文件

在 Linux 中对 LAN8720A 进行一次软复位,找到LAN8720A的驱动文件 “drivers/net/phy/smsc.c”,在函数“smsc_phy_reset”中添加LAN8720A复位代码,修改后的代码如下

static int smsc_phy_reset(struct phy_device *phydev){int err, phy_reset;int msec = 1;struct device_node *np;int timeout = 50000;if(phydev->addr == 0) /* 获取FEC1网卡对应的设备节点 */ {np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000");if(np == NULL) {return -EINVAL;}}if(phydev->addr == 1) /* 获取FEC2网卡对应的设备节点 */ {np = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000");if(np == NULL) {return -EINVAL;}}//从设备树中获取复位时间err = of_property_read_u32(np, "phy-reset-duration", &msec);/* A sane reset duration should not be longer than 1s */if (!err && msec > 1000)msec = 1;//从设备树中获取复位IOphy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);if (!gpio_is_valid(phy_reset))return;//设置PHY的复位IO,复位LAN8720Agpio_direction_output(phy_reset, 0);gpio_set_value(phy_reset, 0);msleep(msec);gpio_set_value(phy_reset, 1);int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);if (rc < 0)return rc;/* If the SMSC PHY is in power down mode, then set it* in all capable mode before using it.*/if ((rc & MII_LAN83C185_MODE_MASK) ==MII_LAN83C185_MODE_POWERDOWN) {/* set "all capable" mode and reset the phy */rc |= MII_LAN83C185_MODE_ALL;phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc);}//未修改之前在上面的函数里面,只有Powerdown模式时才会软复位LAN8720A//此处将其移出来,这样每次调用smsc_phy_reset函数,LAN8720A都会被软复位phy_write(phydev, MII_BMCR, BMCR_RESET);/* wait end of reset (max 500 ms) */do {udelay(10);if (timeout-- == 0)return -1;rc = phy_read(phydev, MII_BMCR);} while (rc & BMCR_RESET);return 0;
}

因为smsc_phy_reset函数中用到了gpio_direction_output和gpio_set_value函数,所以需要在“smsc.c”中添加如下头文件

#include <linux/of_gpio.h>
#include <linux/io.h>

⏩ 网络驱动测试:修改好设备树和内核后重新编译,下载并启动开发板后,使用如下步骤进行测试

输入"ifconfig -a"来查看开发板中存在的网卡

输入"ifconfig eth0 up"和"ifconfig eth1 up"命令,打开eth0(ENET2)和eth1(ENET1)

使用"ifconfig eth0 192.168.10.51"和"ifconfig eth0 192.168.10.52"命令,配置网卡IP地址。配置成功后,ping以下Ubuntu主机(192.168.10.100),ping成功说明网络驱动修改成功

4. 内核移植总结

Linux内核移植的步骤总结如下:

  • 一般情况下,设计自已的硬件时都会参考半导体厂商官方的开发板
  • 在半导体厂商维护的Linux内核中查找可以参考的板子(半导体厂商官方开发板)
  • 编译出参考板子对应的zImage和.dtb文件,尝试在自已的板子上启动
  • 大部分情况下会启动起来,如果不能的话就需要调试Linux内核
  • 修改相应的驱动,NAND/EMMC/SD卡等,内核已经提供,重点是网络驱动,需要根据自已的外设PHY芯片设置复位引脚、地址信息等
  • Linux内核启动以后需要根文件系统,如果没有的话系统会崩溃

Linux 内核移植相关推荐

  1. linux移植会话层层协议,Linux内核移植-南京林业大学毕业设计.DOC

    Linux内核移植-南京林业大学毕业设计 南京林业大学 本科毕业设计(论文) 题 目:嵌入式LINUX在ARM9系统中的移植 院 (系) 信息与科学技术学院 专 业 计算机科学与技术 学 生 谢监荣 ...

  2. 6410 linux内核移植

    linux内核移植(6410) linux内核移植一,硬件环境:友善之臂 tiny6410 开发板开发主机Linux系统:fedora 10 编译器:arm-linux-gcc-4.5.1 二,内核实 ...

  3. linux 内核移植和根文件系统的制作【转载】

    原文地址:http://www.cnblogs.com/hnrainll/archive/2011/06/09/2076214.html 1.1 Linux内核基础知识 在动手进行Linux内核移植之 ...

  4. linux 内核 网卡驱动 移植,Linux内核移植步骤_添加DM9000网卡驱动(设备树).docx

    Linux内核移植步骤_添加DM9000网卡驱动(设备树) Linux内核移植步骤2015年05月13日星期三上午 11:05往设备树中添加网卡驱动:1.选平台,指定交叉编译工具链:(1).在Make ...

  5. linux 内核 网卡驱动 移植,linux内核移植步骤添加dm9000网卡驱动(设备树).docx

    linux内核移植步骤添加dm9000网卡驱动(设备树).docx LINUX内核移植步骤2015年05月13日星期三上午1105往设备树中添加网卡驱动1.选平台,指定交叉编译工具链1.在MAKEFI ...

  6. Linux内核移植漫谈——你不是第一个想移植Linux内核的人

    Jack:在读大学的时候我想过移植Linux操作系统. 我:现在呢? Jack:我还是想移植Linux操作系统.你教我移植吧. 我:你知道什么是"Linux内核移植"吗? Jack ...

  7. 嵌入式linux内核移植

    获取linux内核 移植linux内核首先我们需要先获内核源码,可以从linux官网下载:https://www.kernel.org,但是一般做法是 根据cpu类型从它们的半导体厂商网站获取,因为半 ...

  8. 支持v4l2 linux内核选项 s3c2440,linux内核移植-移植2.6.35.4内核到s3c2440

    原标题:linux内核移植-移植2.6.35.4内核到s3c2440 硬件平台:FL2440 主机平台:Ubuntu 11.04 交叉编译器: - -gcc 4.3.2 原创作品,转载请标明出处htt ...

  9. 【正点原子Linux连载】第三十七章 Linux内核移植 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...

  10. Linux内核移植和根文件系统制作(详细步骤精讲)

    第一章移植内核 1.1 Linux内核基础知识 1.1.1 Linux版本 1.1.2 什么是标准内核 1.1.3 Linux操作系统的分类 1.1.4 linux内核的选择 1.2 Linux内核启 ...

最新文章

  1. python ssh模块_windows下python SSH的使用——paramiko模块
  2. 链接多个数据库的方法
  3. Java代理模式/静态代理/动态代理
  4. POJ 1651 Multiplication Puzzle(类似矩阵连乘 区间dp)
  5. LeetCode 1111. 有效括号的嵌套深度(奇偶分离)
  6. Tensorflow 相关概念
  7. java 企业级应用设计规范_一步一步理解Java 企业级应用的可扩展性
  8. ubuntu16.04安装驱动
  9. Linux创建文本文件【Ubuntu】
  10. vue前端UI框架收集
  11. 苍天有眼,我终于搞定了win7使用建行华大智宝U盾的问题了!
  12. linux选was清除缓存,Linux清除缓存操作
  13. 猫耳FM导出音频转换为音频格式(m4a/mp3)
  14. 室内眩光测量UGR测试系统
  15. Android之原始的QQ好友分组实现
  16. c语言什么事结构体,C语言结构体定义是什么
  17. MTBD 电影市场分析
  18. HQChart--uniApp v3 中使用 render.js
  19. 简单的一些网络流问题
  20. 【BZOJ5020】[THUWC 2017]在美妙的数学王国中畅游 泰勒展开+LCT

热门文章

  1. vue.js之定义组件和子父组件数据传递及函数的相互调用
  2. Sequelize 学习
  3. 百度、GOOGLE地图纠偏及基站查询相关说明
  4. Kubespray v2.22.1 在线部署 kubernetes v1.26.5 集群
  5. Sui主网正式上线!
  6. Error: invalid constant after fixup
  7. 名帖309 成亲王 行书《南北朝诗五首》
  8. 文件批量改名工具,教你如何将图片文件名以顺序编号来进行命名
  9. 面试 -> 使用一个循环合并两个有序数组为1个有序数组
  10. 《计算机网络 自顶向下方法》读书笔记 第7章 无线网络和移动网络