pixhawk启动脚本分析

2023-05-16

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  亮灯的设置,有就亮白灯
then
       set HAVE_RGBLED 1
        #show startup white 
        rgbled rgb 16 16 16
else
       set 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文件系统:vfat
    echo"[init] card mounted at /fs/microsd"      /dev/mmcsd0指SD卡  /fs/microsd指挂载目录
       set HAVE_MICROSD 1
    # Startplaying the startup tune    产生启动语调,表示启动成功
    tone_alarm1
else
       set HAVE_MICROSD 0
    echo"Trying format of microSD"
       tone_alarm MBAGP
        ifmkfatfs /dev/mmcsd0     格式化SD卡
       then
        echo "microSD card formatted"
               if mount -t vfat /dev/mmcsd0 /fs/microsd    挂载SD卡
               then
                        echo "formatsucceeded"
                        set HAVE_MICROSD 1
                        tone_alarm 1
               else
                        echo "mountfailed"
                        tone_alarm MNBG          挂载失败的语调
                        if [ $HAVE_RGBLED == 1]
                        then
                           rgbled rgb 16 0 0     挂载失败的灯
                        fi
               fi
       else                      格式化失败
             echo"format failed"
               tone_alarm MNBGG    挂载失败的语调
               if [ $HAVE_RGBLED == 1 ]
               then
                        rgbled rgb 16 0 0  挂载失败的灯
               fi
            fi
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文件
then
    echo"[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文件
then
    echo"[init] reading /fs/microsd/etc/rc.txt"
    sh /fs/microsd/etc/rc.txt 执行rc.txt文件
fi
 
#
# Check for USB host
#
if [ $USB != autoconnect]    判断USB不是自动连接
then
    echo"[init] not connecting USB"
else
    if sercon     初始化USB串口
    then
        echo"[init] USB interface connected"
    else
        echo"[init] No USB connected"
    fi
fi
 
if [ $HAVE_MICROSD == 0 ]    判断是否有SD卡
then
        ifusb_connected
       then
               echo "Opening USB nsh"
       else
               echo "booting with no microSD"
               set HAVE_MICROSD 1
        fi
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 ]
then
    echoRunning rc.APM
    # ifAPM startup is successful then nsh will exit
    sh /etc/init.d/rc.APM          执行/etc/init.d/rc.APM文件
else
        nshterm /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.enfile
 
set 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 ]
then
   echo"APM file found - renaming"
   mv /fs/microsd/APM /fs/microsd/APM.old   将/fs/microsd/APM命名为/fs/microsd/APM.old
fi
 
if [ -f /fs/microsd/APM/nostart]是否找到/fs/microsd/APM/nostart文件
then
   echo"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文件                                       用程序
then
    echo"binfs already mounted"
else
    echo"Mounting binfs"
        ifmount -t binfs /dev/null/bin   将binfs挂载到/bin目录下
       then
               echo "binfs mounted OK"
       else
               sh /etc/init.d/rc.error    执行/etc/init.d/rc.error
        fi
fi
 
set sketch NONE            设置环境变量sketch为NONE
if rm /fs/microsd/APM/boot.log    删除(remove)/fs/microsd/APM/boot.log
then
   echo"removed old boot.log"
fi
set logfile /fs/microsd/APM/BOOT.LOG  将logfile文件设置成/fs/microsd/APM/BOOT.LOG文件
 
if [ ! -f /bin/ArduPilot ]           查找/bin/ArduPilot文件
then
   echo"/bin/ardupilot not found"
   sh /etc/init.d/rc.error
fi
 
if mkdir /fs/microsd/APM >/dev/null    生成/fs/microsd/APM/dev/null目录(猜测)
then
     echo"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文件
then
  if [ -f/bin/lsm303d ]   查找/bin/lsm303d
  then
     echo"Detected FMUv2 board"
     setBOARD FMUv2           将BOARD设置成FMUv2
  else
     echo"Detected FMUv1 board"
     setBOARD FMUv1            将BOARD设置成FMUv1
  fi
else
  echo"Detected FMUv4 board"
  setBOARD FMUv4              将BOARD设置成FMUv4
fi
 
if [ $BOARD == FMUv1 ]      从这开始是对deviceC和D的设置
then
   setdeviceC /dev/ttyS2
   if [ -f/fs/microsd/APM/AUXPWM.en]
   then           To enablePWM on FMUv1 on ttyS1 add a /fs/microsd/APM/AUXPWM.en file
      setdeviceD /dev/null
   else
      setdeviceD /dev/ttyS1
   fi
else
   setdeviceC /dev/ttyS1
   setdeviceD /dev/ttyS2
fi
 
if uorb start         uorb是否被设置为start
then
    echo"uorb started OK"
else
    sh /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]
then
    echo"Setting up mkblctrl driver"
    echo"Setting up mkblctrl driver">> $logfile          写入logfile
    mkblctrl -d /dev/pwm_output
fi
 
if [ -f /fs/microsd/APM/mkblctrl_+ ]
then                     Toenable mkblctrl_+ startup add a /fs/microsd/APM/mkblctrl_+ file
    echo"Setting up mkblctrl driver +"
    echo"Setting up mkblctrl driver +">> $logfile
    mkblctrl -mkmode +-d /dev/pwm_output
fi
 
if [ -f /fs/microsd/APM/mkblctrl_x ]
then                      Toenable mkblctrl_x startup add a /fs/microsd/APM/mkblctrl_x file
    echo"Setting up mkblctrl driver x"
    echo"Setting up mkblctrl driver x">> $logfile
    mkblctrl -mkmode x-d /dev/pwm_output
fi
这一段我想应该是比较好理解的,就算我们不去看这个命令,因为这里是在设置机型。
 
if [ -f /bin/px4io ]
then
  echo"Trying PX4IO board"
 
  # trythe px4io start twice. Some FMUv2 board don't再次启动px4io,因为有些FMUv2板第一次启动会不成功
  # comeup the first time
  setHAVE_PX4IO false
  if px4iostart norc     px4是否启动正常
  then
    setHAVE_PX4IO true    将HAVE_PX4IO设置为true
  else
    # 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.bin
    then
    echo"upgraded PX4IO firmware OK"
       tone_alarm MSPAA                  发出MSPAA的提示语调
    else
    echo"Failed to upgrade PX4IO firmware"
       tone_alarm MNGGG                  发出MNGGG的提示语调
    fi
    sleep1
    ifpx4io start norc  px4是否启动正常
    then
       set HAVE_PX4IO true   将HAVE_PX4IO设置为true
        #play happy tune again
    tone_alarm1             发出1号提示语调
    fi
  fi
else          找不到/bin/px4io
    setHAVE_PX4IO false
    echo"No PX4IO support"
fi
 
if [ $HAVE_PX4IO == true ]
then
    echo"PX4IO board OK"
    ifpx4io checkcrc /etc/px4io/px4io.bin   校验/etc/px4io/px4io.bin通过CRC校验判断是否需要更新的
    then
       echo "PX4IO CRC OK"
    else
       echo "PX4IO CRC failure"
       echo "PX4IO CRC failure" >> $logfile   
       tone_alarm MBABGP            发出MBABGP的提示语调
 
        ifpx4io safety_on      
       then
           echo "PX4IO disarm OK"
       else
           echo "PX4IO disarm failed"
        fi
 
       sleep 1
 
        ifpx4io forceupdate 14662 /etc/px4io/px4io.bin        强制跟新/etc/px4io/px4io.bin
       then
              sleep 1
              if px4io start norc       px4是否启动正常
              then
                 echo "PX4IO restart OK"
                 echo "PX4IO restart OK" >> $logfile    写入logfile
                 tone_alarm MSPAA
              else
                 echo "PX4IO restart failed"
                 echo "PX4IO restart failed" >> $logfile   
                 tone_alarm MNGGG
                 sh /etc/init.d/rc.error          执行/etc/init.d/rc.error
              fi
       else
              echo "PX4IO update failed"
              echo "PX4IO update failed" >> $logfile   
              tone_alarm MNGGG
        fi
    fi
else     HAVE_PX4IO=false
    echo"No PX4IO board found"
    echo "No PX4IO board found">> $logfile
 
    if [$BOARD == FMUv2 ] FMUv4不需要PX4IO,通过/bin/lsm303d传感器文件,判断是FMUv2还是FMUv1
    then
       sh/etc/init.d/rc.error
    fi
fi

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

 

if [ $BOARD == FMUv1 -a $deviceD == /dev/ttyS1 ]   判断板子是否是FMUV1,deviceD是否对应/dev/ttyS1
then
       echo "Setting FMU mode_serial"
       fmu mode_serial     将fmu设置为串口模式
else
        iffmu mode_pwm4    将fmu设置为pwm模式
       then
               echo "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子目录中
else
    echo"failed to start mtd driver"
    echo"failed to start mtd driver" >> $logfile
    sh/etc/init.d/rc.error          
fi
 
if mtd readtest /fs/mtd
then
    echo"mtd readtest OK"           读mtd测试
else
    echo"failed to read mtd"
    echo"failed to read mtd" >> $logfile
    sh/etc/init.d/rc.error          
fi
 
if [ $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 having
  if mtdrwtest /fs/mtd    mtd读写测试
  then
    echo"mtd rwtest OK"
  else
    echo"failed to test mtd"
    echo"failed to test mtd" >> $logfile
    sh/etc/init.d/rc.error          
  fi
fi

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

 

echo "Starting APM sensors"
 
if ms5611 start启动ms5611
then
   echo"ms5611 started OK"
else
   echo"no ms5611 found"
   echo"No ms5611 found" >> $logfile
   sh/etc/init.d/rc.error
fi
 
if adc start 启动adc
then
   echo"adc started OK"
else
   echo"No adc" >> $logfile
   sh/etc/init.d/rc.error
fi
 
if [ $BOARD == FMUv1 ]         板子为FMUv1
then
    echo"Starting FMUv1 sensors"
    ifhmc5883 -C -T -X start         启动hmc5883
    then
       echo "Have external hmc5883"
    else
       echo "No external hmc5883"
    fi
    ifhmc5883 -C -T -I  start
    then
       echo "Have internal hmc5883"
    else
       echo "No internal hmc5883"
    fi
    ifmpu6000 start           启动mpu6000
    then
      echo "mpu6000  startedOK"
    else
       sh/etc/init.d/rc.error
    fi
    ifl3gd20 start              启动l3gd20
    then
      echo "l3gd20 started OK"
    else
      echo "No l3gd20"
      echo "No l3gd20" >> $logfile
    fi
fi
 
if [ $BOARD == FMUv2 ]      板子为FMUv2
then
    echo"Starting FMUv2 sensors"
    ifhmc5883 -C -T -X start
    then
       echo "Have external hmc5883"
    else
       echo "No external hmc5883"
    fi
    ifhmc5883 -C -T -I -R 4 start
    then
        echo "Have internal hmc5883"
    else
       echo "No internal hmc5883"
    fi
 
    #external MPU6000 is rotated YAW_180 from standard
    ifmpu6000 -X -R 4 start
    then
      echo "Found MPU6000 external"
       setHAVE_FMUV3 true
    else
       ifmpu9250 -X -R 4 start
      then
          echo "Found MPU9250 external"
          set HAVE_FMUV3 true
      else
          echo "No MPU6000 or MPU9250 external"
          set HAVE_FMUV3 false
       fi
    fi
    if [$HAVE_FMUV3 == true ]
    then
        #external L3GD20 is rotated YAW_180 from standard
        ifl3gd20 -X -R 4 start
       then
              echo "l3gd20 external started OK"
       else
              echo "No l3gd20"
              sh /etc/init.d/rc.error
        fi
        #external LSM303D is rotated YAW_270 from standard
        iflsm303d -a 16 -X -R 6 start
       then
              echo "lsm303d external started OK"
       else
              echo "No lsm303d"
              sh /etc/init.d/rc.error
        fi
        #internal MPU6000 is rotated ROLL_180_YAW_270 from standard
        ifmpu6000 -R 14 start
       then
              echo "Found MPU6000 internal"
       else
          if mpu9250 -R 14 start
          then
              echo "Found MPU9250 internal"
          else
              echo "No MPU6000 or MPU9250"
              echo "No MPU6000 or MPU9250" >> $logfile
              sh /etc/init.d/rc.error
          fi
        fi
        ifhmc5883 -C -T -S -R 8 start
       then
              echo "Found SPI hmc5883"
        fi
    else
        ifmpu6000 start
       then
              echo "Found MPU6000"
       else
              if mpu9250 start
              then
                   echo "FoundMPU9250"
              else
                   echo "No MPU6000 orMPU9250"
                   echo "No MPU9250">> $logfile
              fi
        fi
        ifl3gd20 start
       then
              echo "l3gd20 started OK"
       else
              sh /etc/init.d/rc.error
        fi
        iflsm303d -a 16 start
       then
              echo "lsm303d started OK"
       else
              sh /etc/init.d/rc.error
        fi
    fi
fi
 
 
if [ $BOARD == FMUv4 ]         板子为FMUv4
then
    echo"Starting FMUv4 sensors"
    ifhmc5883 -C -T -X start
    then
       echo "Have external hmc5883"
    else
       echo "No external hmc5883"
    fi
    ifhmc5883 -C -T -S -R 2 start
    then
       echo "Have SPI hmc5883"
    else
       echo "No SPI hmc5883"
    fi
 
    ifmpu6000 -R 2 -T 20608 start
    then
      echo "Found ICM-20608 internal"
    fi
 
    ifmpu9250 -R 2 start
    then
      echo "Found mpu9250 internal"
    fi
fi

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

 

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

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


rc.error

echo "Error in startup"
 
tone_alarm MNCC
 
if [ $HAVE_RGBLED == 1 ]
then
        rgbled rgb16 0 0
fi
 
nshterm/dev/ttyACM0 &     启动/dev/ttyACM0
sleep 1
nshterm/dev/ttyS0 &       启动/dev/ttyS0
sleep 1
exit


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


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

pixhawk启动脚本分析 的相关文章

随机推荐

  • 当面试官问 promise 的时候,他们希望听到什么(一)

    基础知识 1 同步回调和异步回调的区别 同步回调 理解 立即执行 完全执行完了才结束 不会放入回调队列中 例子 数组遍历相关的回调函数 Promise 的 executor 执行器函数 异步回调 理解 不会立即执行 会放入回调队列中将来执行
  • 当面试官问 promise 的时候,他们希望听到什么(二)

    目录 前言 一 前提知识 1 JS 单线程机制 2 JS 任务队列与事件循环 3 Promise 回顾 二 题目实战 1 开头提到的题目 2 稍有难度 3 挑战升级 前言 上一篇文章 xff0c 当面试官问 promise 的时候 xff0
  • JS 防抖与节流的原理分析和代码手写

    目录 前言 作用 防抖 使用场景 分析原理 手写代码 节流 使用场景 原理分析 手写代码 小补充 前言 前一段时间 xff0c 我学习了 JS 的防抖与节流 xff0c 自认为掌握住了它们 xff0c 当我在做面试题的时候 xff0c 遇到
  • ELK-日志收集系统在Centos上环境安装

    ELK 日志收集系统在Centos上环境安装 文章目录 ELK 日志收集系统在Centos上环境安装 前言安装elastcsearch6 5 4安装准备学习资料启动创建新用户取掉只能本机访问的配置配置跨域访问启动命令测试 安装分词ik安装e
  • Linux环境下下载pydicom

    Linux中只要使用命令即可 sudo pip install pydicom 如果出现sudo xff1a pip xff1a command not found 把sudo去掉 xff0c 再操作一次 因为在执行Linux命令时 xff
  • C语言编程实现汉诺塔问题

    C语言编程实现汉诺塔问题 1 首先解释一下 xff0c 汉诺塔问题 xff1a 古代梵塔内有A B C3个座 xff0c 开始时A座上面有64个盘子 xff0c 盘子大小不等 xff0c 大的在下 xff0c 小的在上 一个老和尚想把64个
  • ORA-28000: the account is locked

    原因 xff1a Oracle账户多次以错误密码登录 xff0c 导致数据库服务器宕机 xff0c 账户被锁定 以系统账户sys 登录Oracle xff0c 查看sql SELECT FROM DBA PROFILES WHERE RES
  • Docker镜像编译方式

    1 普通Dockerfile的缺点 我们通常情况下要编译Spring Boot的Docker镜像 xff0c 一般会写一个下面这样的Dockerfile FROM openjdk span class token operator span
  • Python入门第一章笔记 从安装到编写hello world

    1 下载Python安装包 xff1b 可以到官网下载 xff1a https www python org 但是如果没有翻墙的话 xff0c 下载会很慢 25M安装包 xff0c 需要1个小时以上 如果没有耐心等可以在csdn进行下载 x
  • 养老产业政策链接

    江西省养老政策文件 xff1a 江西省养老服务条例 http mzw ganzhou gov cn gzsmzjy c103172 202201 d238525b35bb47b49b3de312c9b63a60 shtml 南昌市养老服务体
  • 我多变的2013

    我多变的2013 第一篇 xff1a 回顾 回顾工作 首先简单的做个自我介绍吧 xff0c 我是87年的 xff0c 北漂已经是第5个年头了 xff0c 一直都从事java开发工作 前后只换过一家公司 xff0c 第一家待了近两年 xff0
  • 我花1200大洋所学的“元学习课”究竟学了些什么?

    我花1200大洋所学的 元学习课 究竟学了些什么 xff1f 讲课的是台湾的一位大牛名叫Xdite xff0c 以及亿万富豪李笑来 能够跟牛人学习怎么学习我想应该不会有错吧 xff0c 对我来说这次做的应该是一次正确的决定 xff0c 所谓
  • 成长记录-开启我的新生 (2016-12-06)

    真的是很惊险 xff0c 我差一点就错过了 获得新生 的机会 xff0c 我在蜻蜓音频中听到了逻辑思维 xff0c 从逻辑思维中了解到了 得到 xff0c 从 得到 中订阅了吴军博士的 硅谷来信 xff0c 却在过去的好几个月里 xff0c
  • 最新Java电子书

    最新Java电子书 JAVA参考大全 J2SE 5EDITION 世界级程序设计大师作品 Thinking in Java第三版 43 第四版 xff08 中文版 43 习题答案 xff09 Java数据库高级编程宝典 Java核心技术第八
  • ELK-ElasticSearch权威指南笔记

    ELK ElasticSearch笔记 文章目录 ELK ElasticSearch笔记 前言测试工具 语法索引 xff0c 文档和类型文档元数据检索索引里文档数据查看当前节点的所有 Index查看所有index的mapping 映射 查看
  • 关于JAVA中内存溢出的解决办法

    关于JAVA中内存溢出的解决办法 J2ee应用系统是运行在J2EE应用服务器上的 xff0c 而j2ee应用服务器又是运行在JVM上的 xff0c 生成环境中JVM参数的优化和设置对于J2EE应用系统性能有着决定性的作用 要优化系统 xff
  • ireport的使用总结

    ireport的使用总结 截图居然都没显示出来 xff0c 如有需要可以到 xff08 http download csdn net detail czp0608 4140640 xff09 下载 相信很多java程序员们 xff0c 在开
  • 卡尔曼滤波C代码分析

    文章下载地址 xff1a http wenku baidu com view 3c42b7733186bceb18e8bb29
  • 作为一个新人,怎样学习嵌入式Linux?

    作为一个新人 xff0c 怎样学习嵌入式Linux xff1f 被问过太多次 xff0c 特写这篇文章来回答一下 在学习嵌入式Linux之前 xff0c 肯定要有C语言基础 汇编基础有没有无所谓 就那么几条汇编指令 xff0c 用到了一看就
  • pixhawk启动脚本分析

    Nuttx系统启动是由ardupilot mk PX4 ROMFS init d里的rcS和rc APM完成的 笔者阅读了rcS和rc APM xff0c 该脚本类似C语言 xff0c 并做了相关注释 主要是一些设备自检 xff0c 启动各