本帖最后由 51hei单片 于 2016-3-12 23:48 编辑  
 
 
 
  
 
随笔记:为了尽快熟悉 OpenWRT,手里没有详细的系统的学习资料,只能从网上查阅相关资料,这里看一下,那里看一下。 
 
        随手记录这些基础的知识点,有些我自己也不太明白,先记下。 
 
  
 
一、OpenWRT 开机流程(这部分有些地方衔接不上,所以写的比较乱,只能大体知道流程。) 
 
 ----------------------------------------------------------------- 
 
 openwrt\package\boot\uboot-sun5i\env.cfg 
 
 ----------------------------------------------------------------- 
 
 init=/etc/preinit 
 
 root@TinaLinux:/# cat /proc/cmdline 
 
 cat /proc/cmdline 
 
 console=ttyS3,115200 root=/dev/nandd rootwait init=/etc/preinit ion_cma_512m=32m ion_cma_1g=176m ion_carveout_512m=32m ion_carveout_1g=150m coherent_pool=4m loglevel=8 partitions=boot-res@nanda:env@nandb:boot@nandc:rootfs@nandd:rootfs_data@nande:private@nandf:UDISK@nandg 
 
 ----------------------------------------------------------------- 
 
 /package/base-files/files/etc/preinit 
 
 /etc/preinit 
 
 preinit:是一系列脚本的入口 
 
 -----------------------------------------------------------------  
 
  #!/bin/sh 
 
  # Copyright (C) 2006 OpenWrt.org 
 
  # Copyright (C) 2010 Vertical Communications 
 
  [ -z "$PREINIT" ] && exec /sbin/init 
 
  export PATH=/bin:/sbin:/usr/bin:/usr/sbin 
 
  pi_ifname= 
 
  pi_ip=192.168.1.1 
 
  pi_broadcast=192.168.1.255 
 
  pi_netmask=255.255.255.0 
 
  fs_failsafe_ifname= 
 
  fs_failsafe_ip=192.168.1.1 
 
  fs_failsafe_broadcast=192.168.1.255 
 
  fs_failsafe_netmask=255.255.255.0 
 
  fs_failsafe_wait_timeout=2 
 
  pi_suppress_stderr="y" 
 
  pi_init_suppress_stderr="y" 
 
  pi_init_path="/bin:/sbin:/usr/bin:/usr/sbin" 
 
  pi_init_cmd="/sbin/init" 
 
  // 执行以下脚本,这样以下之后的函数函数才可以使用 
 
  . /lib/functions.sh 
 
  . /lib/functions/preinit.sh 
 
  . /lib/functions/system.sh 
 
  // 初始化5个函数队列,相当于5种类型的脚本, boot_hook_init 在 preinit.sh 实现 
 
  boot_hook_init preinit_essential   
 
  boot_hook_init preinit_main 
 
  boot_hook_init failsafe 
 
  boot_hook_init initramfs 
 
  boot_hook_init preinit_mount_root 
 
  // 循环执行 /lib/preinit 目录下面的脚本 
 
  for pi_source_file in /lib/preinit/*; do 
 
   . $pi_source_file 
 
  done 
 
   
 
  /* 暂且不知道是什么意思  这些脚本全都是在往函数队列里面添加已经实现的函数 
 
   // 以文件开头数字的顺序执行 
 
   /lib/preinit/02_default_set_state 
 
    boot_hook_add preinit_main define_default_set_state 
 
   /lib/preinit/10_indicate_failsafe 
 
    boot_hook_add failsafe indicate_failsafe 
 
   /lib/preinit/10_indicate_preinit 
 
    boot_hook_add preinit_main preinit_ip 
 
    boot_hook_add preinit_main pi_indicate_preinit 
 
   /lib/preinit/30_failsafe_wait  
 
    boot_hook_add preinit_main failsafe_wait 
 
   /lib/preinit/40_run_failsafe_hook 
 
    boot_hook_add preinit_main run_failsafe_hook 
 
   /lib/preinit/50_indicate_regular_preinit 
 
    boot_hook_add preinit_main indicate_regular_preinit 
 
   /lib/preinit/70_initramfs_test 
 
    boot_hook_add preinit_main initramfs_test 
 
   /lib/preinit/79_format_partition 
 
    [ "$INITRAMFS" = "1" ] || boot_hook_add preinit_main do_format_filesystem 
 
   /lib/preinit/80_mount_root  
 
    [ "$INITRAMFS" = "1" ] || boot_hook_add preinit_main do_mount_root 
 
   /lib/preinit/99_10_failsafe_login 
 
    boot_hook_add failsafe failsafe_netlogin 
 
    boot_hook_add failsafe failsafe_shell 
 
   /lib/preinit/99_10_run_init 
 
    boot_hook_add preinit_main run_init 
 
  */ 
 
  // 运行 preinit_essential 函数队列  
 
  boot_run_hook preinit_essential 
 
  pi_mount_skip_next=false 
 
  pi_jffs2_mount_success=false 
 
  pi_failsafe_net_message=false 
 
  // 运行 preinit_main 函数队列 
 
  boot_run_hook preinit_main 
 
 ----------------------------------------------------------------- 
 
 ----------------------------------------------------------------- 
 
 openwrt\package\base-files\files\etc\inittab 
 
 /etc/inittab  : 由 busybox 的 init 程序分析 (/sbin/init) 
 
 inittab 为 linux 初始化文件系统时 init 初始化程序用到的配置文件。 这个文件负责 
 
 设置 init 初始化程序初始化脚本在哪里;每个运行级初始化时运行的命令; 开机、关机、重 
 
 启对应的命令;各运行级登陆时所运行的命令。 
 
 如果存在/etc/inittab 文件,Busybox init 程序解析它,然后按照它的指示创建各种 
 
 子进程,否则使用默认的配置创建子进程。 /etc/inittab 文件中每个条目用来定义一个子进 
 
 程,并确定它的启动方法,格式如下: 
 
 <id> : <runlevels> : <action> : <process> 
 
 1、 id :表示这个子进程要使用的控制台,如果省略,则使用与 init 进程一样的控制台. 
 
 2、 runlevels:这个字段没有意义,可以省略。在 linux 有意义. 
 
 3、 action:表示 init 进程如何控制这个子进程,具体取值见下表. 
 
 4、 process:要执行的程序,它可以是可执行程序,也可以是脚本.如果 process 字段前 
 
  有“ -”字符,这个程序被称为“交互的”  
 
   
 
 【 attention】 action 取值 
 
 ---------------------------------------- 
 
 sysinit 系统启动后最先执行: 
 
  指定初始化脚本路径,只执行一次,init 进程等待它结束才继续执行其它动作 
 
   
 
 wait 系统执行完 sysinit 进程后: 
 
  只执行一次,init 进程等待它结束才继续执行其它动作 
 
   
 
 once 系统执行完 wait 进程后 
 
  只执行一次,init 进程不等待它结束 
 
   
 
 respawn 启动完 once 进程后 
 
  init 进程监测发现子进程退出时,重新启动它,永不结束.如 Shell 命令解释器 
 
   
 
 askfirst 启动完 respawn 进程后  
 
  与 respawn 类似,不过init 进程先输出“ Pleasepress Enter toactivate this 
 
  console”,等用户输入回车后才启动子进程 
 
   
 
 shutdown 当系统关机时  
 
  即重启、关闭系统时执行的程序 
 
   
 
 restart 系统重启时  
 
  init 进程重启时执行的程序,通常是 init 程序本身先重新读取、解析/etc/inittab 
 
  文件,再执行 restart 程序 
 
   
 
 ctrl+alt+del 按 下 Ctrl+Alt+Del 键时  
 
  按 Ctrl+Alt+Del 组合键时执行的程序 
 
 ----------------------------------------------------------------- 
 
 // sysinit 系统初始化运行 /etc/init.d/rcS S boot 
 
 ::sysinit:/etc/init.d/rcS S boot 
 
 // shutdown 系统重启或者关机运行的脚本 
 
 ::shutdown:/etc/init.d/rcS K shutdown 
 
 // 登录串口的时候 
 
 ::askconsole:/bin/ash --login 
 
 从上面的分析可以看出它在开机启动的时候执行/etc/init.d/rcS 脚本,以前是有 
 
 /etc/init.d/rcS 脚本的,现在的 openwrt 已经去掉了这个脚本文件,只要有 rcS S boot 
 
 这几个参数就可以,但是功能是有的就是按顺序执行/etc/rc.d 下面的各个脚本,以 S 开 
 
 头代表启动的时候执行的脚本,与命令行中的 S 对应,以 K 开头的代表关机的时候需要 
 
 执行的脚本,与命令行中的 K 对应 
 
 /etc/rc.d 里面的脚本是在 install 时拷贝到 /etc/init.d 下,然后通过 /etc/rc.common 脚本 
 
 将 init.d 的脚本链接到 /etc/rc.d 目录,并且根据这些脚本中的 START 和 STOP 的关键字,添加 
 
 K${STOP} 和 S${START} 的前缀,这样就决定了脚本的先后的运行次序。 
 
 openwrt\staging_dir\target-arm_cortex-a8+neon_uClibc-0.9.33.2_eabi\root-sun5i\etc\init.d 
 
 root@TinaLinux:/etc/rc.d# ll 
 
 ll 
 
 drwxr-xr-x    2 root     root           306 Dec 23  2015 . 
 
 drwxr-xr-x    1 root     root          1024 Jan  1  1970 .. 
 
 lrwxrwxrwx    1 root     root            13 Dec 23  2015 K89log -> ../init.d/log 
 
 lrwxrwxrwx    1 root     root            17 Dec 23  2015 K90network -> ../init.d/network 
 
 lrwxrwxrwx    1 root     root            14 Dec 23  2015 K98boot -> ../init.d/boot 
 
 lrwxrwxrwx    1 root     root            14 Dec 23  2015 K99adbd -> ../init.d/adbd 
 
 lrwxrwxrwx    1 root     root            16 Dec 23  2015 K99umount -> ../init.d/umount 
 
 lrwxrwxrwx    1 root     root            20 Dec 23  2015 S00sysfixtime -> ../init.d/sysfixtime 
 
 lrwxrwxrwx    1 root     root            14 Dec 23  2015 S10boot -> ../init.d/boot 
 
 lrwxrwxrwx    1 root     root            16 Dec 23  2015 S10system -> ../init.d/system 
 
 lrwxrwxrwx    1 root     root            16 Dec 23  2015 S11sysctl -> ../init.d/sysctl 
 
 lrwxrwxrwx    1 root     root            13 Dec 23  2015 S12log -> ../init.d/log 
 
 lrwxrwxrwx    1 root     root            17 Dec 23  2015 S20network -> ../init.d/network 
 
 lrwxrwxrwx    1 root     root            15 Dec 23  2015 S40fstab -> ../init.d/fstab 
 
 lrwxrwxrwx    1 root     root            14 Dec 23  2015 S50cron -> ../init.d/cron 
 
 lrwxrwxrwx    1 root     root            16 Dec 23  2015 S50telnet -> ../init.d/telnet 
 
 lrwxrwxrwx    1 root     root            14 Dec 23  2015 S95done -> ../init.d/done 
 
 lrwxrwxrwx    1 root     root            13 Dec 23  2015 S96led -> ../init.d/led 
 
 lrwxrwxrwx    1 root     root            17 Dec 23  2015 S98sysntpd -> ../init.d/sysntpd 
 
 lrwxrwxrwx    1 root     root            14 Dec 23  2015 S99adbd -> ../init.d/adbd 
 
 preinit 主要是完成系统的初始化(如文件系统的准备、模块的加载) 
 
 rcS 主要是依次启动各个模块 
 
二、 应用程序\Makefile\开机自启动 
 
  
 
 1、实现一个简单的应用程序,开机自启动,实现在根目录建立一个名为 temp_file_zhc 的文件 
 
  步骤1:在openwrt\package 建立zhc_application\zhc_test\src 
 
  步骤2:在 zhc_test\src中建立 main.c 源文件,内容如下 
 
   ------------------------------------------------------ 
 
   #include <stdlib.h> 
 
   #include <stdio.h> 
 
   #define __ISDEBUG__ 
 
   #ifdef __ISDEBUG__ 
 
   #define dprintf(format,...) printf(&quot; -->[%s] Fun:%s, Line:%05d, &quot;format&quot; <--\n&quot;,strrchr(__FILE__,'/') ? strrchr(__FILE__,'/') : __FILE__ ,__func__ , __LINE__,##__VA_ARGS__) 
 
   #else 
 
   #define dprintf(format,...) 
 
   #endif 
 
   int main(void) 
 
   { 
 
    dprintf(&quot;zhc_test app ~~~~~&quot;); 
 
    system(&quot;echo 12 > temp_file_zhc&quot;); 
 
    dprintf(&quot;zxxxxxx ~~~~~&quot;); 
 
    return 0; 
 
   } 
 
   ------------------------------------------------------ 
 
  步骤3:在 zhc_test\src中建立 makefile 文件,内容如下 
 
   ------------------------------------------------------  
 
   TARGET          = zhc_test 
 
   INCLUDES        += -I. -Icommon/ 
 
   LIBS            += -lpthread -lm -lrt 
 
   SRCS    = main.c  
 
   OBJS    = $(SRCS:.c=.o) 
 
   %.o: %.c 
 
    $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 
 
   $(TARGET): $(OBJS) 
 
    $(CC) -o $@ $(OBJS) $(LIBS) $(LDFLAGS) 
 
     
 
   all:$(TARGET) 
 
   clean: 
 
    rm -rf $(TARGET) *.o *.a *~ 
 
    cd common && rm -f *.o *.a *.bak *~ .depend 
 
   ------------------------------------------------------ 
 
    
 
  步骤4:在 zhc_test 建立 makefile 文件,内容如下 
 
   ------------------------------------------------------ 
 
   # 这些 makefile 字文件确立软件包加入 OpenWrt 的方式和方法 
 
   include $(TOPDIR)/rules.mk 
 
   # PKG_NAME   : 包名 
 
   # PKG_VERSION : 软件包版本号 
 
   # PKG_RELEASE : Makefile 的版本号 
 
   PKG_NAME:=zhc_test 
 
   PKG_VERSION:=0.0.1 
 
   PKG_RELEASE:=1 
 
 
 
   # 软件包编译目录  
 
   # 它的父目录为$(BUILD_DIR)。如果不指定 
 
   # 默认为$(BUILD_DIR)/$( PKG_NAME)/$( PKG_VERSION) 
 
   PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) 
 
   # 一般在软包的基本信息完成后再引入 
 
   include $(INCLUDE_DIR)/package.mk 
 
     
 
   # 应用程序编译包以 &quot;Package/&quot; 开头,然后接着软件名(可以与软件包名不一样) 
 
   # SECTION  : 包的类型 
 
   # CATEGORY : 包的分类,在 make menuconfig 的菜单显示的名字 
 
   # TITLE  : 用于在 make menuconfig 对该软件包的简述 
 
   # DEPENDS : 表示依赖其他软件。即如编译或安装需要其他软件时需要说明。如果 
 
   #     存在多个依赖,则每个依赖需要用空格分开。依赖前使用+号表示默认 
 
   #     为显示,即对象沒有选中时也会显示,使用@则默认为不显示,即当依 
 
   #     赖对象选中后才显示。 
 
   define Package/zhc_test 
 
     SECTION:=utils 
 
     CATEGORY:=Zhc_Bin 
 
     TITLE:=is zhc test bin file 
 
     DEPENDS:=+libpthread 
 
   endef 
 
   # 软件包的详细描述 
 
   define Package/zhc_test/description 
 
    is 11111111111111111111111111 
 
   endef 
 
   # 编译准备方法 
 
   # 对于网上下载的软件包不需要再描述 
 
   # 对于非网上下载或自行开发的软件包必须说明编译准备方法 
 
   # 以下为一般的编译准备方法,按 OpenWrt 的习惯,一般把自己设计的程序全部放在 src 目录下 
 
   define Build/Prepare 
 
    mkdir -p $(PKG_BUILD_DIR) 
 
    $(CP) ./src/* $(PKG_BUILD_DIR)/ 
 
   endef 
 
   # 编译方法,如果不定义将使用默认的编译方法 Build/Compile/Default 
 
   # 自行开发的软件考虑使用下面的定义 
 
   define Build/Compile 
 
    $(MAKE) -C $(PKG_BUILD_DIR) \ 
 
     CC=&quot;$(TARGET_CC)&quot; \ 
 
     CFLAGS=&quot;$(TARGET_CFLAGS)&quot; -Wall \ 
 
     LDFLAGS=&quot;$(TARGET_LDFLAGS)&quot; \ 
 
     LIBS=&quot;-lpthread&quot; \ 
 
     all 
 
   endef 
 
   # 软件包的安装方法 
 
   # 包括一系列拷贝编译好的文件到指定位置。 
 
   # 调用时会带一个参数,就是嵌入系统的镜像文件系统目录 
 
   # 因此 $(1) 表示嵌入系统的镜像目录。一般可以采用下面的方法 
 
   # INSTALL_DIR\INSTALL_BIN : 在 $(TOPDIR)/rules.mk 定义 
 
   # INSTALL_DIR : INSTALL_DIR :=install -d -m0755 意思是创建所属用户可读写 
 
   #      其他用户可读可执行的目录 
 
   # INSTALL_BIN : INSTALL_BIN :=install -m0755 意思是编译好的文件存放到镜像文件目录 
 
   define Package/zhc_test/install 
 
    $(INSTALL_DIR) $(1)/bin 
 
    $(INSTALL_BIN) $(PKG_BUILD_DIR)/zhc_test $(1)/bin/ 
 
   endef 
 
   # PDF 文档描述,在 boot 阶段启动 (未验证) 
 
   #define Package/zhc_test/install 
 
   # $(INCLUDE_DIR) $(1)/sbin/ $(1)/etc/config/ $(1)/etc/init.d/ 
 
   # $(INSTALL_BIN) $(PKG_BUILD_DIR)/zhc_test $(1)/sbin/ 
 
   # $(INCLUDE_DIR) ./files/zhc_test.config $(1)/etc/config/zhc_test 
 
   # $(INSTALL_BIN) ./files/zhc_test.init $(1)/etc/init.d/zhc_test 
 
   #endef 
 
 
 
   # 完成前面定义后,必须使用 eval 函数实现各种定义(感觉就像是这句才是真正执行上面的动作) 
 
   $(eval $(call BuildPackage,zhc_test))  
 
   ------------------------------------------------------ 
 
  【注意】以上步骤可以在 sdk 中编译出来,但是在源码目录中编译会出现如下提示: 
 
   make[1]: Entering directory `/home/zhangfuliang/work/r8_tina/openwrt' 
 
   make[2]: Entering directory `/home/zhangfuliang/work/r8_tina/openwrt/package/zhc_application/zhc_test' 
 
   WARNING: skipping zhc_test -- package not selected 
 
   make[2]: Leaving directory `/home/zhangfuliang/work/r8_tina/openwrt/package/zhc_application/zhc_test' 
 
   make[1]: Leaving directory `/home/zhangfuliang/work/r8_tina/openwrt' 
 
  步骤5: 编译进固件 此步骤是为了将该应用程序编译进固件 
 
   在 openwrt 根目录执行 make menuconfig  
 
   将 ZHC_BIN--> []zhc_test 修改为 ZHC_BIN-->zhc_test 
 
    
 
  步骤6: 修改 rc.local 实现开机自启动(可以添加各种 linux 命令) 
 
   文件在: openwrt/package/base-files/files/etc 
 
   ------------------------------------------------------ 
 
   # Put your custom commands here that should be executed once 
 
   # the system init finished. By default this file does nothing. 
 
   ./bin/zhc_test & 
 
   exit 0 
 
   ------------------------------------------------------ 
 
  步骤7: make V=s 编译即可 
 
  
 
 2、实现一个简单的应用程序,编译一个独立于固件的应用程序 
 
  
 
  步骤1:参照上述 步骤1~步骤4 
 
   
 
  步骤2:编译进固件 此步骤是为了将该应用程序编译进固件 
 
   在 openwrt 根目录执行 make menuconfig  
 
   将 ZHC_BIN--> []zhc_test 修改为 ZHC_BIN--> [M]zhc_test 
 
    
 
  步骤3:导入脚本命令,仅第一次进入终端时需要 
 
   . scripts/setenv.sh 
 
   
 
  步骤4:两种方式编译 
 
   方法1:在源码根目录下编译指定的应用程序 
 
     minstall 路径/my_bin 
 
   方法2: 
 
     进入到需要编译的源码目录 -> mm 
 
      
 
   编译出来的文件放在:openwrt/bin/sun5i/packages/base/zhc_test_0.0.1-1_sun5i.ipk 
 
  
 
  步骤5:将文件通过 adb push 到板子中并安装 
 
   opkg install zhc_test_0.0.1-1_sun5i.ipk 
 
   然后无论在哪个路径下,可以直接通过敲 zhc_test 即可执行该程序。 |   
     
  
 |