打印

OpenWRT(Tina) 相关资料介绍 开机流程等等

[复制链接]
167|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
丑帅丑帅的|  楼主 | 2018-10-4 10:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 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(" -->[%s] Fun:%s, Line:%05d, "format" <--\n",strrchr(__FILE__,'/') ? strrchr(__FILE__,'/') : __FILE__ ,__func__ , __LINE__,##__VA_ARGS__)

   #else

   #define dprintf(format,...)

   #endif

   int main(void)

   {

    dprintf("zhc_test app ~~~~~");

    system("echo 12 > temp_file_zhc");

    dprintf("zxxxxxx ~~~~~");

    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

   

   # 应用程序编译包以 "Package/" 开头,然后接着软件名(可以与软件包名不一样)

   # 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="$(TARGET_CC)" \

     CFLAGS="$(TARGET_CFLAGS)" -Wall \

     LDFLAGS="$(TARGET_LDFLAGS)" \

     LIBS="-lpthread" \

     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 即可执行该程序。

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

741

主题

742

帖子

0

粉丝