1)SDK
编译OpenWrt模块,需要用和img相一致的SDK。
在用源代码生成img的时候,将SDK也选上。这样在生成的img的路径下,就有一个名字中有SDK字样的压缩包,解压即可得到SDK。
2)代码
https://github.com/antkillerfarm/antkillerfarm_crazy/tree/master/hiOpenWRT
从上面的地址下载代码,然后将hiOpenWRT文件夹,放到package文件夹下。
3)编译
将路径设为SDK的根目录,然后运行以下命令:
make package/hiOpenWRT/compile V=s
4)编译结果
在bin/x86_64/packages/base下可以找到hiOpenWRT_1_x86_64.ipk。
4)模块安装
opkg install xyz.ipk
参考文献:
http://blog.chinaunix.net/uid-29418452-id-4071751.html
OpenWRT之HelloWorld
1)参考文献
http://www.cnblogs.com/sammei/p/3968916.html
这篇文章描述了OpenWrt makefile的框架
http://www.ccs.neu.edu/home/noubir/Courses/CS6710/S12/material/OpenWrt_Dev_Tutorial.pdf
这是美国东北大学(不是中国东北大学)的学生写的开发入门。
2)编译内核模块
编译内核模块的大体步骤与编译应用模块并无太大差异。其主要不同在于内核模块需要使用linux内核的那一套makefile机制,而应用模块的编译就简单的多了,简单的配一下gcc的参数就行了。
这里我偷了个懒,直接将OpenWrt源代码中的package/kernel/gpio-button-hotplug复制到SDK的package文件夹下,岂料编译之后什么也没有生成。
网上查了一下也没有找到什么办法,有的网页甚至说SDK不能用于编译内核模块。这一点让我很疑惑,因为普通的linux内核模块只需要linux-header就可以编译了,并不需要linux源代码。
最后我尝试运行了一下make menuconfig
,终于找到了问题的症结。不同于编译源代码时候的选项,这里的选项很少,碰巧找到了gpio-button-hotplug,然后选中该项,再次编译。这一下终于在bin/x86_64/packages/base下找到了需要的ipk文件。
undefined reference to '__stack_chk_fail_local'
网上查了一下,答案是将链接命令由ld,换成gcc即可。
但这只是针对普通代码包的编译而言,OpenWrt由于使用的是交叉编译工具链,单纯的修改源代码中的链接命令,根本起不到丝毫作用。
那么如何修改交叉编译工具链中使用的链接命令呢?
以luasocket为例,在feeds中的makefile中有如下片段:
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR)/ \
LIBDIR="$(TARGET_LDFLAGS)" \
CC="$(TARGET_CC) $(TARGET_CFLAGS) $(TARGET_CPPFLAGS) -std=gnu99" \
LD="$(TARGET_CROSS)ld -shared" \
all
endef
将其中的ld,改为gcc即可。
undefined reference to '__sync_fetch_and_add_8'
这个函数和上面的__stack_chk_fail_local函数一样都是编译器隐含函数。它既不同于自己代码实现的函数,也不同于那些显式调用的库函数,通常是针对某个语法规则或编译选项而链接的函数。因此这类错误,实际上并非代码写的不对,而是编译上的配置不对。
__sync_fetch_and_add_8实际上是和CPU原子操作有关的函数,在PC上目前不支持x86指令集,而只支持x86_64指令集。将目标平台改为x86_64即可。
最近使用某平台的工具链编译OpenWrt,然后执行as命令时,出现如下错误:
libz.so.1: cannot open shared object file: No such file or directory
找了一下,发现libz.so.1在zlib-bin包中,岂料安装zlib-bin之后,问题依旧。
最后才发现这个工具链是32位的程序,相应的libz.so.1实际上在lib32z1-dev包中。因此遇到类似的问题时,可以先注意一下程序的位数是否匹配。
ip命令是linux网络管理方面的命令,它的代码在iproute2包中。
1)首先要确定ncurses库是否已经正确安装。在debian, Ubuntu上,可以用dpkg -l | grep ncurses
查看ncurses库是否已安装。
2)如果ncurses已经安装了,需要查看TERM, TERMINFO两个环境变量是否已经设置正确。如果没有设置正确,需要设置为正确的值。
$ echo $TERM
xterm
$ echo $TERMINFO
/lib/terminfo/
procd是OpenWrt中很重要的一个守护进程。它的作用主要有:
1)初始化系统。相当于普通linux的init。
2)硬件热插拔事件处理、看门狗。相当于普通linux的udev和watchdog。
3)日志系统。相当于普通linux的rsyslog。
https://blog.csdn.net/bingqingsuimeng/article/details/7924625
linux热插拔之udev的使用方法
https://www.cnblogs.com/xuyh/p/4212575.html
openwrt实现hotplug-button
init/main.c: start_kernel –Linux的启动入口
init/main.c: rest_init
init/main.c: kenrel_init
执行/etc/preinit脚本
/sbin/init – 该程序的源代码在procd包中。
initd/init.c: main – /sbin/init的主函数
initd/preinit.c: preinit
这个函数中有以下代码片段:
char *plug[] = { "/sbin/procd", "-h", "/etc/hotplug-preinit.json", NULL };
再之后,就开始procd的执行了。
参考文献:
http://m.blog.csdn.net/blog/wwx0715/41725917
http://blog.chinaunix.net/uid-26598889-id-3060545.html
procd本身已经有很多debug信息,只是一般不打印而已。启动时,终端会提示你输入procd的debug level,取值范围0~4。0表示不输出,数字越大,输出的信息越多。
1)/etc/hotplug.json
这个文件的格式,大致如下:
[
[ "case", "ACTION", {
"add": [
[ "if",
[ "has", "FIRMWARE" ],
[
[ "exec", "/sbin/hotplug-call", "%SUBSYSTEM%" ],
[ "load-firmware", "/lib/firmware" ],
[ "return" ]
]
],
],
"remove" : [
[ "if",
[ "and",
[ "has", "DEVNAME" ],
[ "has", "MAJOR" ],
[ "has", "MINOR" ],
],
[ "rm", "/dev/%DEVNAME%" ]
]
]
} ],
[ "if",
[ "and",
[ "eq", "SUBSYSTEM", "usb-serial" ],
[ "regex", "DEVNAME",
[ "^ttyUSB", "^ttyACM" ]
],
],
[ "exec", "/sbin/hotplug-call", "tty" ]
],
]
从代码可以看出,这个文件是个披着json外皮的程序文件,其关键字和C语言类似,而结构风格则类似Lisp语言:在表达式的组合上,广泛使用了逆波兰表达式。
这里的两个ACTION:add和remove,分别对应硬件设备的插消息和拔消息。简单的消息处理命令,可以直接写在这个文件中。复杂的需要交给/sbin/hotplug-call来处理。
以下面的代码片段为例:
[ "exec", "/sbin/hotplug-call", "tty" ]
hotplug-call会遍历/etc/hotplug.d/tty文件夹。该文件夹中的脚本,一般以NN_XXX的方式命名。其中的NN为数字。hotplug-call会按照NN的大小,从小到大依次执行文件夹中的所有脚本。
U盘驱动可分为两个层次:
1.USB设备驱动。这个的配置选项在linux内核中。
2.文件系统驱动。这个的配置选项在OpenWrt中,一般选择支持VFAT和NTFS即可。
以下是U盘插入时,生成的事件的procd日志:
{"ACTION":"add","DEVPATH":"/devices/platform/rtl819x-ehci/usb1/1-1/1-1.1","SUBSYSTEM":"usb","MAJOR":"189","MINOR":"3","DEVNAME":"bus/usb/001/004","DEVTYPE":"usb_device","PRODUCT":"c76/5/100","TYPE":"0/0/0","BUSNUM":"001","DEVNUM":"004","SEQNUM":"466"}
{"ACTION":"add","DEVPATH":"/devices/platform/rtl819x-ehci/usb1/1-1/1-1.1/1-1.1:1.0","SUBSYSTEM":"usb","DEVTYPE":"usb_interface","PRODUCT":"c76/5/100","TYPE":"0/0/0","INTERFACE":"8/6/80","MODALIAS":"usb:v0C76p0005d0100dc00dsc00dp00ic08isc06ip50in00","SEQNUM":"467"}
{"ACTION":"add","DEVPATH":"/devices/platform/rtl819x-ehci/usb1/1-1/1-1.1/1-1.1:1.0/host0","SUBSYSTEM":"scsi","DEVTYPE":"scsi_host","SEQNUM":"468"}
{"ACTION":"add","DEVPATH":"/devices/platform/rtl819x-ehci/usb1/1-1/1-1.1/1-1.1:1.0/host0/scsi_host/host0","SUBSYSTEM":"scsi_host","SEQNUM":"469"}
{"ACTION":"add","DEVPATH":"/devices/platform/rtl819x-ehci/usb1/1-1/1-1.1/1-1.1:1.0/host0/target0:0:0","SUBSYSTEM":"scsi","DEVTYPE":"scsi_target","SEQNUM":
"470"}
{"ACTION":"add","DEVPATH":"/devices/platform/rtl819x-ehci/usb1/1-1/1-1.1/1-1.1:1.0/host0/target0:0:0/0:0:0:0","SUBSYSTEM":"scsi","DEVTYPE":"scsi_device","MODALIAS":"scsi:t-0x00","SEQNUM":"471"}
{"ACTION":"add","DEVPATH":"/devices/platform/rtl819x-ehci/usb1/1-1/1-1.1/1-1.1:1.0/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0","SUBSYSTEM":"scsi_disk","SEQNUM":"472"}
{"ACTION":"add","DEVPATH":"/devices/platform/rtl819x-ehci/usb1/1-1/1-1.1/1-1.1:1.0/host0/target0:0:0/0:0:0:0/scsi_device/0:0:0:0","SUBSYSTEM":"scsi_device","SEQNUM":"473"}
{"ACTION":"add","DEVPATH":"/devices/virtual/bdi/8:0","SUBSYSTEM":"bdi","SEQNUM":"474"}
{"ACTION":"add","DEVPATH":"/devices/platform/rtl819x-ehci/usb1/1-1/1-1.1/1-1.1:1.0/host0/target0:0:0/0:0:0:0/block/sda","SUBSYSTEM":"block","MAJOR":"8","MINOR":"0","DEVNAME":"sda","DEVTYPE":"disk","SEQNUM":"475"}
{"ACTION":"add","DEVPATH":"/devices/platform/rtl819x-ehci/usb1/1-1/1-1.1/1-1.1:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda1","SUBSYSTEM":"block","MAJOR":"8","MINOR":"1","DEVNAME":"sda1","DEVTYPE":"partition","SEQNUM":"476"}
从上面的内容可以看出:
1.驱动的加载是有层次的。例如U盘驱动至少包括USB->SCSI->disk->partition这几个大的阶段。
2.上面提到的脚本,可以接收诸如ACTION、DEVPATH之类的环境变量。
IP地址被改变事件示例:
[ "$INTERFACE" = "lan" ] && [ "$ACTION" = "ifup" ] && {
/etc/init.d/gmediarender restart
}
kmod-gpio-button-hotplug Simple GPIO Button Hotplug driver
kmod-button-hotplug Button Hotplug driver
这两个内核模块不在内核主线中,需要在make menuconfig
中单独勾选。
autotools和CMake是目前应用最广的两套编译配置系统。Openwrt对它们支持的代码在/include/autotools.mk和/include/cmake.mk中。
libubox是Openwrt平台的一个工具库。详见:
http://www.w2bc.com/article/91056
http://www.shuyz.com/n2n-vpn-network-introduction-and-config.html
组建N2N VPN网络实现内网设备之间的相互访问
http://blog.csdn.net/yicao821/article/details/45370669
Openwrt 3G拨号上网
您的打赏,是对我的鼓励