Nuttx系统启动是由ardupilot/mk/PX4/ROMFS/init.d里的rcS和rc.APM完成的。笔者阅读了rcS和rc.APM,该脚本类似C语言,并做了相关注释。主要是一些设备自检,启动各模块,最后启动进入ArduPilot_main,开始运行程序。本节只介绍启动脚本,程序的启动与整体运行下节再分析。

rcS

rcS
#!nsh由nsh进行解析的脚本
#
# PX4FMU startup script.
#
# This script is responsible for:这个脚本是为了回应
#
# - mounting the microSD card (if present)安装SD卡
# - running the user startup script from the microSDcard (if present)从SD卡中运行用户启动脚本
# - detecting the configuration of the systemand picking a suitable查找系统配置并选择一个合适的启动脚
#  startup script to continue with                                      本继续运行
#
# Note: DO NOT add configuration-specificcommands to this script;
#      add them to the per-configuration scripts instead.
##
# Default to auto-start mode.  An initscript on the microSD card
# can change this to prevent automatic startupof the flight script.
#
set MODE autostart  模式设置为自动开始   MODE跟USB应该是环境变量
set USB autoconnect  USB自动连接        在Linux中也是用set去给一个环境变量赋值的##if rgbled start  亮灯的设置,有就亮白灯
thenset HAVE_RGBLED 1#show startup white rgbled rgb 16 16 16
elseset HAVE_RGBLED 0
fi#
# Try to mount the microSD card.尝试挂载SD卡
#
echo "[init]looking for microSD..."echo是打印的命令
if mount -t vfat/dev/mmcsd0 /fs/microsdmount [-t vfstype] [-ooptions] device dir.
then                                   -t vfstype指定文件系统的类型,通常不必指定,fat32文件系统:vfatecho"[init] card mounted at /fs/microsd"      /dev/mmcsd0指SD卡  /fs/microsd指挂载目录set HAVE_MICROSD 1# Startplaying the startup tune    产生启动语调,表示启动成功tone_alarm1
elseset HAVE_MICROSD 0echo"Trying format of microSD"tone_alarm MBAGPifmkfatfs /dev/mmcsd0     格式化SD卡thenecho "microSD card formatted"if mount -t vfat /dev/mmcsd0 /fs/microsd    挂载SD卡thenecho "formatsucceeded"set HAVE_MICROSD 1tone_alarm 1elseecho "mountfailed"tone_alarm MNBG          挂载失败的语调if [ $HAVE_RGBLED == 1]thenrgbled rgb 16 0 0     挂载失败的灯fifielse                      格式化失败echo"format failed"tone_alarm MNBGG    挂载失败的语调if [ $HAVE_RGBLED == 1 ]thenrgbled rgb 16 0 0  挂载失败的灯fifi
fi#
# Look for an initscript on the microSD card.    寻找初始化脚本
#
# To prevent automatic startup in the currentflight mode,为了避免自动启动当前飞行模式,脚本应该设置成
# the script should set MODE to some othervalue.          其他值
#
if [ -f /fs/microsd/etc/rc ]      查找/fs/microsd/etc/rc这个路径的rc文件
thenecho"[init] reading /fs/microsd/etc/rc"sh /fs/microsd/etc/rc         执行rc文件   sh是用来执行nsh脚本的一个命令
fi
# Also consider rc.txt files
if [ -f /fs/microsd/etc/rc.txt ]查找/fs/microsd/etc/rc.txt这个路径的rc文件
thenecho"[init] reading /fs/microsd/etc/rc.txt"sh /fs/microsd/etc/rc.txt 执行rc.txt文件
fi#
# Check for USB host
#
if [ $USB != autoconnect]    判断USB不是自动连接
thenecho"[init] not connecting USB"
elseif sercon     初始化USB串口thenecho"[init] USB interface connected"elseecho"[init] No USB connected"fi
fiif [ $HAVE_MICROSD == 0 ]    判断是否有SD卡
thenifusb_connectedthenecho "Opening USB nsh"elseecho "booting with no microSD"set HAVE_MICROSD 1fi
fi# if this is an APM build then there will be arc.APM script如果这是APM build,那么会有rc.APM脚本文件
# from an EXTERNAL_SCRIPTS build option        rc.APM脚本文件来自EXTERNAL_SCRIPTS(外部脚本)build选项中
if [ -f /etc/init.d/rc.APM -a $HAVE_MICROSD == 1-a ! -f /fs/microsd/APM/nostart ]
thenechoRunning rc.APM# ifAPM startup is successful then nsh will exitsh /etc/init.d/rc.APM          执行/etc/init.d/rc.APM文件
elsenshterm /dev/ttyACM0&
fi

其实我们完全把它当作一个 Linux脚本来阅读就可以了。
    MODE跟 USB应该是环境变量,在Linux中也是用 set去给一个环境变量赋值的。然后去启动 “rgbled”,这是由 “Firmware”提供的。我们很容易猜到这是用来控制那个高亮的 LED灯的。然后才是挂载 SD卡,文件系统为 vfat,挂载目录为 /fs/microsd。 SD卡挂载上来之后就去执行 SD卡中的脚本 “/fs/microsd/etc/rc”,所以我们就知道 sh是用来执行 nsh脚本的一个命令。应该来说 “/fs/microsd/etc/rc.txt”也是一个脚本,要不然也不会使用 sh命令了。 sercon你需要去看下源码才知道这是用来初始化 USB串口的。而最后则是通过调用 /etc/init.d/rc.APM脚本来真正初始化飞控。

rc.APM

#!nsh  由nsh进行解析的脚本# APM startup script for NuttX on PX4    APM的Nuttx系统启动脚本# To disable APM startup add a /fs/microsd/APM/nostart file
# To enable mkblctrlstartup add a /fs/microsd/APM/mkblctrl file
# To enable mkblctrl_+ startup add a /fs/microsd/APM/mkblctrl_+file
# To enable mkblctrl_x startup add a /fs/microsd/APM/mkblctrl_xfile
# To enable PWM on FMUv1 on ttyS1 add a /fs/microsd/APM/AUXPWM.enfileset deviceA /dev/ttyACM0# check for an old file called APM, caused by 核查一个叫APM旧的文件
# a bug in an earlier firmware release         它由firmware发布,为了应对之前的一个bug
if [ -f /fs/microsd/APM ]
thenecho"APM file found - renaming"mv /fs/microsd/APM /fs/microsd/APM.old   将/fs/microsd/APM命名为/fs/microsd/APM.old
fiif [ -f /fs/microsd/APM/nostart]是否找到/fs/microsd/APM/nostart文件
thenecho"APM/nostart found - skipping APMstartup"sh /etc/init.d/rc.error    执行/etc/init.d/rc.error
fi# mount binfsso we can find the built-in apps挂载binfs(built_in_files)文件,这样就可以找到built-in应
if [ -f /bin/reboot ]         查找/bin/reboot文件                                       用程序
thenecho"binfs already mounted"
elseecho"Mounting binfs"ifmount -t binfs /dev/null/bin   将binfs挂载到/bin目录下thenecho "binfs mounted OK"elsesh /etc/init.d/rc.error    执行/etc/init.d/rc.errorfi
fiset sketch NONE            设置环境变量sketch为NONE
if rm /fs/microsd/APM/boot.log    删除(remove)/fs/microsd/APM/boot.log
thenecho"removed old boot.log"
fi
set logfile /fs/microsd/APM/BOOT.LOG  将logfile文件设置成/fs/microsd/APM/BOOT.LOG文件if [ ! -f /bin/ArduPilot ]           查找/bin/ArduPilot文件
thenecho"/bin/ardupilot not found"sh /etc/init.d/rc.error
fiif mkdir /fs/microsd/APM >/dev/null    生成/fs/microsd/APM/dev/null目录(猜测)
thenecho"Created APM directory"
fi

这部分是我划出来的第一部分。先设置串口,然后一堆跟SD卡相关的命令。其实我们将一张空的SD卡放进去也是可以正常工作的。可能这里最让人感兴趣的就是“ArduPilot”了,因为APM工程就叫“ArduPilot”。在 g_builtins数组中也有这样一行信息:

{"ArduPilot",SCHED_PRIORITY_DEFAULT, 4096, ArduPilot_main},
也就是说 PX4将 APM原来的主程序设计成了 Nuttx中的一个命令。但其实我们在使用 Linux系统的时候,可执行文件其实就等同命令。这个命令跟其他命令还是有很大不同的,这个我们后面再讨论。

if [ -f /bin/px4io ]   查找/bin/px4io文件
thenif [ -f/bin/lsm303d ]   查找/bin/lsm303dthenecho"Detected FMUv2 board"setBOARD FMUv2           将BOARD设置成FMUv2elseecho"Detected FMUv1 board"setBOARD FMUv1            将BOARD设置成FMUv1fi
elseecho"Detected FMUv4 board"setBOARD FMUv4              将BOARD设置成FMUv4
fiif [ $BOARD == FMUv1 ]      从这开始是对deviceC和D的设置
thensetdeviceC /dev/ttyS2if [ -f/fs/microsd/APM/AUXPWM.en]then           To enablePWM on FMUv1 on ttyS1 add a /fs/microsd/APM/AUXPWM.en filesetdeviceD /dev/nullelsesetdeviceD /dev/ttyS1fi
elsesetdeviceC /dev/ttyS1setdeviceD /dev/ttyS2
fiif uorb start         uorb是否被设置为start
thenecho"uorb started OK"
elsesh /etc/init.d/rc.error
fi

从这里我们可以看到FMUv1跟 FMUv2的差别在于 lsm303d这颗传感器。通过这颗传感器我们可以用肉眼进行区分。当然它们所使用的串口不同这个可能就无法直接看到了。

我看了下 uorb的源码,源码中有这样一条注释:“Start/load the driver”,我没太搞懂这里 “driver”是什么,只是它用到了一个变量:PX4IO *g_dev = nullptr;,由此也只能确定这是跟 IO板相关的,更具体的就不知道了。

# start mkblctrldriver if configured   启动mkblctrl驱动,如果mkblctrl被配置了
if [ -f /fs/microsd/APM/mkblctrl]
thenecho"Setting up mkblctrl driver"echo"Setting up mkblctrl driver">> $logfile          写入logfilemkblctrl -d /dev/pwm_output
fiif [ -f /fs/microsd/APM/mkblctrl_+ ]
then                     Toenable mkblctrl_+ startup add a /fs/microsd/APM/mkblctrl_+ fileecho"Setting up mkblctrl driver +"echo"Setting up mkblctrl driver +">> $logfilemkblctrl -mkmode +-d /dev/pwm_output
fiif [ -f /fs/microsd/APM/mkblctrl_x ]
then                      Toenable mkblctrl_x startup add a /fs/microsd/APM/mkblctrl_x fileecho"Setting up mkblctrl driver x"echo"Setting up mkblctrl driver x">> $logfilemkblctrl -mkmode x-d /dev/pwm_output
fi
这一段我想应该是比较好理解的,就算我们不去看这个命令,因为这里是在设置机型。if [ -f /bin/px4io ]
thenecho"Trying PX4IO board"# trythe px4io start twice. Some FMUv2 board don't再次启动px4io,因为有些FMUv2板第一次启动会不成功# comeup the first timesetHAVE_PX4IO falseif px4iostart norc     px4是否启动正常thensetHAVE_PX4IO true    将HAVE_PX4IO设置为trueelse# itmay be in bootloader mode      此时应该在bootloader模式echoLoading /etc/px4io/px4io.bin   下载/etc/px4io/px4io.bin文件到板中tone_alarm MBABGP                    发出MBABGP的提示语调ifpx4io update /etc/px4io/px4io.bin   判断px4是否跟新成/etc/px4io/px4io.binthenecho"upgraded PX4IO firmware OK"tone_alarm MSPAA                  发出MSPAA的提示语调elseecho"Failed to upgrade PX4IO firmware"tone_alarm MNGGG                  发出MNGGG的提示语调fisleep1ifpx4io start norc  px4是否启动正常thenset HAVE_PX4IO true   将HAVE_PX4IO设置为true#play happy tune againtone_alarm1             发出1号提示语调fifi
else          找不到/bin/px4iosetHAVE_PX4IO falseecho"No PX4IO support"
fiif [ $HAVE_PX4IO == true ]
thenecho"PX4IO board OK"ifpx4io checkcrc /etc/px4io/px4io.bin   校验/etc/px4io/px4io.bin通过CRC校验判断是否需要更新的thenecho "PX4IO CRC OK"elseecho "PX4IO CRC failure"echo "PX4IO CRC failure" >> $logfile   tone_alarm MBABGP            发出MBABGP的提示语调ifpx4io safety_on      thenecho "PX4IO disarm OK"elseecho "PX4IO disarm failed"fisleep 1ifpx4io forceupdate 14662 /etc/px4io/px4io.bin        强制跟新/etc/px4io/px4io.binthensleep 1if px4io start norc       px4是否启动正常thenecho "PX4IO restart OK"echo "PX4IO restart OK" >> $logfile    写入logfiletone_alarm MSPAAelseecho "PX4IO restart failed"echo "PX4IO restart failed" >> $logfile   tone_alarm MNGGGsh /etc/init.d/rc.error          执行/etc/init.d/rc.errorfielseecho "PX4IO update failed"echo "PX4IO update failed" >> $logfile   tone_alarm MNGGGfifi
else     HAVE_PX4IO=falseecho"No PX4IO board found"echo "No PX4IO board found">> $logfileif [$BOARD == FMUv2 ] FMUv4不需要PX4IO,通过/bin/lsm303d传感器文件,判断是FMUv2还是FMUv1thensh/etc/init.d/rc.errorfi
fi

这里看似很长的一段脚本,其实质做了一件事情:更新IO板的固件。这么长的脚本处理了两种情况:一、IO板没有固件;二,IO板有固件但不是最新的。更新固件是通过 px4io命令来完成的,如果我们想知道固件是如何更新的可以去阅读该命令的源码。固件更新其实我们在分析 IO板的启动的时候已经知道是通过 CRC校验判断是否需要更新的。

if [ $BOARD == FMUv1 -a $deviceD == /dev/ttyS1 ]   判断板子是否是FMUV1,deviceD是否对应/dev/ttyS1
thenecho "Setting FMU mode_serial"fmu mode_serial     将fmu设置为串口模式
elseiffmu mode_pwm4    将fmu设置为pwm模式thenecho "Set FMU mode_pwm4"fi
fi

我粗略看了下 fmu的源码,没看明白这一段是干嘛的。

if mtd start /fs/mtd MTD(memory technology device内存技术设备)用于访问memory设备(ROM,Flash)的子系统
then   linux中MTD的主要目的是为了使新的memory设备的驱动更加简单,为此它在硬件和上层之间提供了一个echo"started mtd driver OK"            抽象的接口,MTD的所有源代码在/driver/mtd子目录中
elseecho"failed to start mtd driver"echo"failed to start mtd driver" >> $logfilesh/etc/init.d/rc.error
fiif mtd readtest /fs/mtd
thenecho"mtd readtest OK"           读mtd测试
elseecho"failed to read mtd"echo"failed to read mtd" >> $logfilesh/etc/init.d/rc.error
fiif [ $BOARD == FMUv2 -o $BOARD == FMUv4 ]
then# theramtron on FMUv2 is very fast and can handle trillions of 之前有个设备读写失败了,所以进行读#writes. This full rw test on each boot ensures it is working    写测试,确保读写没问题#properly. We have one board that failed this, so# thetest is arguably worth havingif mtdrwtest /fs/mtd    mtd读写测试thenecho"mtd rwtest OK"elseecho"failed to test mtd"echo"failed to test mtd" >> $logfilesh/etc/init.d/rc.error          fi
fi

对mtd进行读写测试,确保这方面没问题。这部分脚本是对mtd的操作,根据对Linux的了解,我觉得这里应该跟存储设备相关。虽然没有mount操作,但我仍然觉得这里可能是挂载存储设备,具体的仍然要到源码中去找寻答案。

echo "Starting APM sensors"if ms5611 start启动ms5611
thenecho"ms5611 started OK"
elseecho"no ms5611 found"echo"No ms5611 found" >> $logfilesh/etc/init.d/rc.error
fiif adc start 启动adc
thenecho"adc started OK"
elseecho"No adc" >> $logfilesh/etc/init.d/rc.error
fiif [ $BOARD == FMUv1 ]         板子为FMUv1
thenecho"Starting FMUv1 sensors"ifhmc5883 -C -T -X start         启动hmc5883thenecho "Have external hmc5883"elseecho "No external hmc5883"fiifhmc5883 -C -T -I  startthenecho "Have internal hmc5883"elseecho "No internal hmc5883"fiifmpu6000 start           启动mpu6000thenecho "mpu6000  startedOK"elsesh/etc/init.d/rc.errorfiifl3gd20 start              启动l3gd20thenecho "l3gd20 started OK"elseecho "No l3gd20"echo "No l3gd20" >> $logfilefi
fiif [ $BOARD == FMUv2 ]      板子为FMUv2
thenecho"Starting FMUv2 sensors"ifhmc5883 -C -T -X startthenecho "Have external hmc5883"elseecho "No external hmc5883"fiifhmc5883 -C -T -I -R 4 startthenecho "Have internal hmc5883"elseecho "No internal hmc5883"fi#external MPU6000 is rotated YAW_180 from standardifmpu6000 -X -R 4 startthenecho "Found MPU6000 external"setHAVE_FMUV3 trueelseifmpu9250 -X -R 4 startthenecho "Found MPU9250 external"set HAVE_FMUV3 trueelseecho "No MPU6000 or MPU9250 external"set HAVE_FMUV3 falsefifiif [$HAVE_FMUV3 == true ]then#external L3GD20 is rotated YAW_180 from standardifl3gd20 -X -R 4 startthenecho "l3gd20 external started OK"elseecho "No l3gd20"sh /etc/init.d/rc.errorfi#external LSM303D is rotated YAW_270 from standardiflsm303d -a 16 -X -R 6 startthenecho "lsm303d external started OK"elseecho "No lsm303d"sh /etc/init.d/rc.errorfi#internal MPU6000 is rotated ROLL_180_YAW_270 from standardifmpu6000 -R 14 startthenecho "Found MPU6000 internal"elseif mpu9250 -R 14 startthenecho "Found MPU9250 internal"elseecho "No MPU6000 or MPU9250"echo "No MPU6000 or MPU9250" >> $logfilesh /etc/init.d/rc.errorfifiifhmc5883 -C -T -S -R 8 startthenecho "Found SPI hmc5883"fielseifmpu6000 startthenecho "Found MPU6000"elseif mpu9250 startthenecho "FoundMPU9250"elseecho "No MPU6000 orMPU9250"echo "No MPU9250">> $logfilefifiifl3gd20 startthenecho "l3gd20 started OK"elsesh /etc/init.d/rc.errorfiiflsm303d -a 16 startthenecho "lsm303d started OK"elsesh /etc/init.d/rc.errorfifi
fiif [ $BOARD == FMUv4 ]         板子为FMUv4
thenecho"Starting FMUv4 sensors"ifhmc5883 -C -T -X startthenecho "Have external hmc5883"elseecho "No external hmc5883"fiifhmc5883 -C -T -S -R 2 startthenecho "Have SPI hmc5883"elseecho "No SPI hmc5883"fiifmpu6000 -R 2 -T 20608 startthenecho "Found ICM-20608 internal"fiifmpu9250 -R 2 startthenecho "Found mpu9250 internal"fi
fi

从 echo那一句很容易看出这里是在启动传感器。当然,我暂时是不会去研究这些传感器是干嘛用的,只以看流程为主。从这段脚本我们也可以看出 V1跟 V2的一些区别,即 V1是内置罗盘,并且上电校准。但是 V2可以使用外置罗盘,而且上电过程是不校准的。至于陀螺为什么会有内部和外部的区别这个我没想通,也没有找到相关资料,这或许就要到源码中去寻找答案了。而源码肯定是要去看的。

# optional ETS airspeed sensor  空速计
if ets_airspeed start
thenecho"Found ETS airspeed sensor"
fiif meas_airspeed start
thenecho"Found MEAS airspeed sensor"
elseifmeas_airspeed start -b 2thenecho "Found MEAS airspeed sensor (bus2)"fi
fi# optional Range Finder sensor  测距仪
if ll40ls -X start
thenecho"Found external ll40ls sensor"
fiif ll40ls -I start
thenecho"Found internal ll40ls sensor"
fiif trone start
thenecho"Found trone sensor"
fiif mb12xx start
thenecho"Found mb12xx sensor"
fi# optional PX4Flow sensor     光流
if [ -f /bin/px4flow ]
thenifpx4flow startthenecho"Found px4flow sensor"fi
fi# optional PWM input driver     pwm输入驱动
if pwm_input start
thenecho"started pwm_input driver"
fi# optional oreo leds    oled屏
if [ -f /bin/oreoled ]
theniforeoled start autoupdatethenecho "oreoledstarted OK"fi
fi# optional smbus battery monitor   电池总线监视器
if batt_smbus -b 2 start
thenecho"Found batt_smbus"
fi# optional irlock     irlock暂时不知道是什么
if irlock start
thenecho"irlock started"
fiecho Starting ArduPilot $deviceA $deviceC$deviceD
if ArduPilot -d $deviceA -d2 $deviceC -d3$deviceD start   启动deviceA、deviceC、deviceD
thenecho ArduPilot started OK
elsesh/etc/init.d/rc.error
fiecho "rc.APM finished"

最后还有一个人脚本: /etc/init.d/rc.error,在出错的时候我们经常看到这个脚本。

rc.error

echo "Error in startup"tone_alarm MNCCif [ $HAVE_RGBLED == 1 ]
thenrgbled rgb16 0 0
finshterm/dev/ttyACM0 &     启动/dev/ttyACM0
sleep 1
nshterm/dev/ttyS0 &       启动/dev/ttyS0
sleep 1
exit

如果您觉得此文对您的发展有用,请随意打赏。 
您的鼓励将是笔者书写高质量文章的最大动力^_^!!

pixhawk启动脚本分析相关推荐

  1. tomcatSupplement(1)tomcat启动脚本分析(以Windows平台为例)

    [0]README 1)本文部分文字描述转自:"深入剖析tomcat",旨在学习"tomcat启动脚本分析"的相关知识: 2)for tomcat4 start ...

  2. Spark配置启动脚本分析

    2019独角兽企业重金招聘Python工程师标准>>> 今天想停止spark集群,发现执行stop-all.sh的时候spark的相关进程都无法停止.提示: no org.apach ...

  3. 第一章 Hadoop启动Shell启动脚本分析--基于hadoop-0.20.2-cdh3u1

    我的新浪微博:http://weibo.com/freshairbrucewoo. 欢迎大家相互交流,共同提高技术. 第一章 Hadoop启动Shell启动脚本分析 第一节 start-all.sh脚 ...

  4. busybox rootfs 启动脚本分析(一)

    imx6文件系统启动脚本分析.开机运行/sbin/init,读取/etc/inittab文件,进行初始化. 参考链接 http://blog.163.com/wghbeyond@126/blog/st ...

  5. v210 启动脚本分析

    1. 一般嵌入式linux系统的init进程会首先读取/etc/inittab文件,这里记录了系统在不阶段需要运行的程序与脚本文件. 其中v210的此文件里有这么一句 ::sysinit:/etc/i ...

  6. kafka之服务端启动脚本分析

    前阵子在服务器上搭了个 kafka,搭好后安装在 /usr/local/kafka 下: [root@lucas kafka]# pwd /usr/local/kafka [root@lucas ka ...

  7. Hi3516开发笔记(三):Hi3516虚拟机基础环境搭建之交叉编译环境境搭建以及开机启动脚本分析

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/121458516 长期持续项目技术分享,Shang业Di ...

  8. Spark学习之路 (十五)SparkCore的源码解读(一)启动脚本

    讨论QQ:1586558083 目录 一.启动脚本分析 1.1 start-all.sh 1.2 start-master.sh 1.3 spark-config.sh(1.2的第5步) 1.4 lo ...

  9. Hyperledger Fabric笔记3--BYFN启动流程分析

    Hyperledger Fabric笔记3--BYFN启动流程分析 BYFN--构建你的第一个网络,该方案提供了一个示例Hyperledger Fabric网络,该网络由两个组织组成,每个组织都维护两 ...

  10. Linux系统脚本分析之rc.sysinit

    Linux系统脚本分析之rc.sysinit #!/bin/bash # # /etc/rc.d/rc.sysinit - run once at boot time #  # # Rerun our ...

最新文章

  1. CS中常用转义符与@符号的作用
  2. AV1为何有信心打败H.265?
  3. mooc课程下载_如何使用十大商学院的免费课程制作MOOC“ MBA”
  4. 指北针邮件工具 v1.5.6.1
  5. Qt5制作icon图标文件和发布程序简易介绍
  6. 海量数据中找top K专题
  7. 课文电子计算机与多媒体减写,课文电子计算机与多媒体关系介绍
  8. VMware vSphere 5.1 群集深入解析(三)
  9. python logger.debug_python处理logger日志
  10. android studio for android learning (二十 )android中this、context等关键概念理解全解
  11. springboot留言板
  12. 英雄联盟官宣IG冠军皮肤原画 彩蛋是王思聪吃热狗
  13. vdbench多主机运行指导
  14. 中值滤波(Median filtering)
  15. Jzoj4699 Password
  16. JAVA面向对象编程程序设计——中国象棋
  17. android cpu负载 工具,【专家专栏】Android性能测试之CPU
  18. 计算机考试用到的英语词汇,BEC商务英语_计算机英语高级词汇·软件篇_沪江英语...
  19. Mac OSX 打开原生自带读写NTFS功能[10.11.6 work, 10.14.4不work]
  20. mac book pro touchbar 黑屏不亮的问题解决

热门文章

  1. Python学习笔记——python基础之Python实现名片管理系统
  2. 微信公众号(服务号)申请流程(仅供参考)
  3. 微信公众号消息推送服务器,微信服务号模块消息推送
  4. 微信小黄鸡php,微信表情包小黄鸡含义
  5. mongo按季度统计_三季度国内纯碱市场总结及四季度分析
  6. Maya粒子特效制作(一)
  7. 使用FFmpegFrameGrabber获取视频缩略图
  8. 深度学习-lecture1李飞飞计算机视觉
  9. php二维数组声明方式,二维数组怎么定义
  10. Chrome浏览器解决主页被劫持的问题