嵌入式Linux 文件系统制作,使其支持中文

前言:

本文涉及到制作嵌入式Linux文件系统,也涉及到编码种类

继续完善中,待更……

参考链接

UTF、GBK等编码以及嵌入式linux支持中文显示:
https://blog.csdn.net/weixin_43369409/article/details/90380100

说明1:

Windows的编码方式为GB2312
验证方式:cmd中输入“chcp”,返回值为“活动代码页:936”,如下图所示
查看Windows的编码方式

说明2:

虚拟机装的Ubuntu的编码方式为UTF-8
验证方式:在终端中输入“locale”,返回的都是“UTF-8”的编码,如下图所示
查看Ubuntu的编码方式

说明3:

嵌入式Linux开发板的编码方式尽量设置为GB2312,当然也可以为UTF-8.
可以在内核配置中配置的。

说明4:

板子与Windows的编码方式要一致,才能完成在板子上的文件与Windows下的文件通用不乱码。
不要将虚拟机Ubuntu带有中文的文件直接拷贝到板子上,会导致乱码,只允许拷贝ASCII编码的文件(即 纯英文)。

1. Linux内核部分

在虚拟机中切换到内核目录,打开图形化配置界面(在Xshell中打开无法修改Default codepage/iocharset/NLS的编码值)

File systems ---> DOS/FAT/NT Filesystems ---> 
	(437) Default codepage for FAT
	(cp936) Default iocharset for FAT 修改
	
File systems ---> Native language support --->
	(GB2312) Default NLS Option
	Codepage 437 (United States, Canada) 选中
	Simplified Chinese charset (CP936, GB2312) 选中(简体中文编码)
	NLS ISO 8859-1 (Latin 1; Western European Languages) 选中
	NLS UTF-8 选中(通用码,选中但不用)

2. 开发板中挂载的命令

后面在开发板上挂载外设存储设备的命令需要修改:

# GB2312格式挂载:
mount -t vfat -o iocharset=cp936 /dev/sda1 /mnt/udisk

# UTF-8格式挂载:
mount -t vfat -o iocharset=utf8 /dev/sda1 /mnt/udisk

3. BusyBox

3.1 BusyBox目录:
# 进入生成的目录
cd /XXX/busybox/
3.2 修改BusyBox源码,使显示突破ASCII码0x7F:

源码修改部分:
busybox/libbb/printable_string.c 的 FAST_FUNC printable_string 函数
busybox/libbb/unicode.c 的 FAST_FUNC unicode_conv_to_printable2 函数

笔者使用预处理指令(#if 0 & #else & #endif)屏蔽掉的代码为修改部分

// 修改1 printable_string.c 的 printable_string函数:
        while (1) {
                unsigned char c = *s;
                if (c == '\0') {
                        /* 99+% of inputs do not need conversion */
                        if (stats) {
                                stats->byte_count = (s - str);
                                stats->unicode_count = (s - str);
                                stats->unicode_width = (s - str);
                        }
                        return str;
                }
                if (c < ' ')
                        break;
#if 0
                if (c >= 0x7f)
                        break;
#endif
                s++;
        }

// 修改2 printable_string.c 的 printable_string函数:
#if ENABLE_UNICODE_SUPPORT
        dst = unicode_conv_to_printable(stats, str);
#else
        {
                char *d = dst = xstrdup(str);
                while (1) {
                        unsigned char c = *d;
                        if (c == '\0')
                                break;
#if 0
                        if (c < ' ' || c >= 0x7f)
                                *d = '?';
#else
                        if (c < ' ')
                                *d = '?';
#endif
                        d++;
                }
                if (stats) {
                        stats->byte_count = (d - dst);
                        stats->unicode_count = (d - dst);
                        stats->unicode_width = (d - dst);
                }
        }
#endif

// 修改3 unicode.c 的 unicode_conv_to_printable2函数:
        if (unicode_status != UNICODE_ON) {
                char *d;
                if (flags & UNI_FLAG_PAD) {
                        d = dst = xmalloc(width + 1);
                        while ((int)--width >= 0) {
                                unsigned char c = *src;
                                if (c == '\0') {
                                        do
                                                *d++ = ' ';
                                        while ((int)--width >= 0);
                                        break;
                                }
#if 0
                                *d++ = (c >= ' ' && c < 0x7f) ? c : '?';
#else
                                *d++ = (c >= ' ') ? c : '?';
#endif
                                src++;
                        }
                        *d = '\0';
                } else {
                        d = dst = xstrndup(src, width);
                        while (*d) {
                                unsigned char c = *d;
#if 0
                                if (c < ' ' || c >= 0x7f)
                                        *d = '?';
#else
                                if (c < ' ')
                                        *d = '?';
#endif
                                d++;
                        }
                }
                if (stats) {
                        stats->byte_count = (d - dst);
                        stats->unicode_count = (d - dst);
                        stats->unicode_width = (d - dst);
                }
                return dst;
        }
3.3 修改顶级Makefile:
# 使用vim定位 CROSS_COMPILE 和 ARCH
CROSS_COMPILE ?= arm-linux-gnueabihf-
ARCH ?= arm
3.4 配置BusyBox:
# 运行命令:
make ARCH=arm menuconfig

Busybox Settings --->
	Build BusyBox as a static binary (no shared libs) 勾上(把busybox编译成静态链接的可执行文件,不用依赖其他库运行.)
	()Cross Compiler prefix(添加交叉编译器arm-linux-gnueabihf-)
	(./_install) BusyBox installation prefix (自定义BusyBox的安装路径为当前路径下的_install目录之下)
Busybox Library Tuning --->
	vi-style line editing commands
	Check $LC_ALL, $LC_CTYPE and $LANG environment variables(检查环境变量LANG选择unicode_status = UNICODE_ON)勾上
	(63) Character code to substitute unprintable characters with (替换不可打印的字符)
	(767) Range of supported Unicode characters(支持的Unicode字符范围) 改为195101(即2FA1D)
	Allow wide Unicode characters on output(中文需要宽字的支持) 勾上
Coreutils ---> ls --->
	Allow use of color to identify file types 勾上 --->
		Produce colored ls output by default 勾上
Editors ---> vi --->
	(4096) Maximum screen width(显示宽度的最大值)
	Allow to display 8-bit chars (otherwise shows dots)(vi的中文显示)勾上


# 注:login是用于保护系统,设置登录用户和用户密码
# 使开发板支持login

Login/Password Management Utilities ---> 
	Support shadow password 选上
	Use internal password and group functions rather than system functions 选上
	addgroup 选上
		Enable long options
		Support adding users to groups
	login 选上
		Support login scripts
		Support /etc/nologin
		Support /etc/securetty
	passwd 选上
		Check new passwords for weakness

# 笔者给开发板设置过好多次login,但都失败了,进入去根文件系统
3.5 编译BusyBox并生成BusyBox工具:
# 编译BusyBox
make

# 生成BusyBox工具
make install
3.6 进入生成的目录:
# 进入生成的目录
cd _install/

# 查看生成的目录
ls

4. 文件系统的制作

4.1 创建所需目录:
mkdir bin etc dev home lib mnt opt
mkdir proc root sbin sys tmp usr var

mkdir -p mnt/nfs/
mkdir -p mnt/sdcard/
mkdir -p mnt/udisk/
4.2 根文件系统的dev目录:
cd dev/

# mknod的标准格式为:mknod DEVNAME {b | c}  MAJOR  MINOR
# 1. DEVNAME是要创建的设备文件名,如果想将设备文件放在一个特定的文件夹下,就需要先用mkdir在dev目录下新建一个目录;
# 2. b和c分别表示块设备和字符设备:
#    b表示系统从块设备中读取数据的时候,直接从内存的buffer中读取数据,而不经过磁盘;
#    c表示字符设备文件与设备传送数据的时候是以字符的形式传送,一次传送一个字符,比如打印机、终端都是以字符的形式传送数据;
# 3. MAJOR和MINOR分别表示主设备号和次设备号
# console 为Linux控制台,null 为Linux的无底洞

sudo mknod console c 5 1
sudo mknod full c 1 7
sudo mknod kmem c 1 2
sudo mknod mem c 1 1
sudo mknod null c 1 3
sudo mknod port c 1 4
sudo mknod random c 1 8
sudo mknod urandom c 1 9
sudo mknod zero c 1 5
4.3 根文件系统的etc目录:
4.3.1 进入根文件系统的etc目录
cd ../etc/
4.3.2 将BusyBox的etc参考范本目录下的文件拷贝到根文件系统的etc目录下,包含文件/目录:fstab init.d inittab profile。
cp -rf /XXX/busybox/examples/bootfloppy/etc/* ./
4.3.3 创建文件
touch passwd group shadow
4.3.4 将下面内容导进passwd文件
root:x:0:0:root:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
messagebus:x:106:110::/var/run/dbus:/bin/false
uuidd:x:107:111::/run/uuidd:/bin/false
lightdm:x:108:114:Light Display Manager:/var/lib/lightdm:/bin/false
whoopsie:x:109:117::/nonexistent:/bin/false
avahi-autoipd:x:110:119:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false
avahi:x:111:120:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false
dnsmasq:x:112:65534:dnsmasq,,,:/var/lib/misc:/bin/false
colord:x:113:123:colord colour management daemon,,,:/var/lib/colord:/bin/false
speech-dispatcher:x:114:29:Speech Dispatcher,,,:/var/run/speech-dispatcher:/bin/false
hplip:x:115:7:HPLIP system user,,,:/var/run/hplip:/bin/false
kernoops:x:116:65534:Kernel Oops Tracking Daemon,,,:/:/bin/false
pulse:x:117:124:PulseAudio daemon,,,:/var/run/pulse:/bin/false
rtkit:x:118:126:RealtimeKit,,,:/proc:/bin/false
saned:x:119:127::/var/lib/saned:/bin/false
usbmux:x:120:46:usbmux daemon,,,:/var/lib/usbmux:/bin/false
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
4.3.5 将下面内容导进group文件
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
lp:x:7:
mail:x:8:
news:x:9:
uucp:x:10:
man:x:12:
proxy:x:13:
kmem:x:15:
dialout:x:20:
fax:x:21:
voice:x:22:
cdrom:x:24:
floppy:x:25:
tape:x:26:
sudo:x:27:
audio:x:29:
dip:x:30:
www-data:x:33:
backup:x:34:
operator:x:37:
list:x:38:
irc:x:39:
src:x:40:
gnats:x:41:
shadow:x:42:
utmp:x:43:
video:x:44:
sasl:x:45:
plugdev:x:46:
staff:x:50:
games:x:60:
users:x:100:
nogroup:x:65534:
sshd:x:999:
4.3.6 将下面内容导进shadow文件
root::16092:0:99999:7:::
daemon:*:16092:0:99999:7:::
bin:*:16092:0:99999:7:::
sys:*:16092:0:99999:7:::
sync:*:16092:0:99999:7:::
games:*:16092:0:99999:7:::
man:*:16092:0:99999:7:::
lp:*:16092:0:99999:7:::
mail:*:16092:0:99999:7:::
news:*:16092:0:99999:7:::
uucp:*:16092:0:99999:7:::
proxy:*:16092:0:99999:7:::
www-data:*:16092:0:99999:7:::
backup:*:16092:0:99999:7:::
list:*:16092:0:99999:7:::
irc:*:16092:0:99999:7:::
gnats:*:16092:0:99999:7:::
nobody:*:16092:0:99999:7:::
sshd:!:16092::::::
4.3.7 清空inittab文件,将下面内容导进inittab文件
# first:run the system script file
console::sysinit:/etc/init.d/rcS
#::respawn:-/bin/sh
ttyS0::respawn:-/bin/sh
#ttyS1::respawn:-/bin/sh
::once:/usr/sbin/telnetd -l /bin/login
::ctrlaltdel:/bin/umount -a -r
# 注:
# login的操作1:在/etc/inittab中添加“::sysinit:-/bin/login”
# 结果1:不管怎么输入账号和密码,过了3次就可以进入。
# login的操作2:在/etc/inittab中添加“::respawn:-/bin/login”
# 结果2:不管怎么输入账号和密码,就是进不去文件系统。

# 笔者也很懵逼,看了许多资料并且实际操作后,都不知道该怎么操作login实现
# 正确的进入板子,输入账号与密码
4.3.7 清空fstab文件,将下面内容导进fstab文件,分隔符为[tab]键
proc    /proc   proc    defaults 0 0
tmpfs   /tmp    tmpfs   defaults 0 0
sysfs   /sys    sysfs   defaults 0 0
tmpfs   /dev    tmpfs   defaults 0 0
var     /dev    tmpfs   defaults 0 0
4.3.8 清空init.d/rcS文件,将下面内容导进init.d/rcS文件(系统最先执行的,也可称为初始化脚本)
#!/bin/sh

PATH=/bin:/sbin:/usr/bin:/usr/sbin

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib/

runlevel=S
prevlevel=N

# 创建文件/目录的默认权限掩码为022,真实权限为(7-0 7-2 7-2)= 755
umask 022

export PATH runlevel prevlevel

/bin/mount -a
/bin/mkdir /dev/pts
/bin/mount -t devpts devpts /dev/pts

# 使用mdev机制的热插拔
/bin/echo "/sbin/mdev" > /proc/sys/kernel/hotplug
/sbin/mdev -s
/bin/mkdir -p /var/lock

# 主机名
/bin/hostname -F /etc/sysconfig/HOSTNAME

# 同步系统时钟为RTC将时钟
/sbin/hwclock -s

# 设置网口IP
/sbin/ifconfig eth0 192.XXX.XXX.XXX > /dev/null 2>&1
4.3.9 情况profile文件,将下面内容导进profile文件
# /etc/profile: system-wide .profile file for the Bourne shells

echo
echo -n "Processing /etc/profile... "

# 程序运行时连接动态库的路径
export LD_LIBRARY_PATH=$PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib/
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:

# 运行SSH,SSH需要移植
/XXXX/bin/sshd

# 设置
USE=R"'id-un'"
LOGNAME=$USER
PS1='[\u@\h \W]# '
PATH=$PATH
HOSTNAME='/bin/hostname'
echo "Processing /etc/profile..."

export USER LOGNAME PS1 PATH


echo "Done"
echo
4.3.10 在sysconfig/HOSTNAME文件添加主机名
# 在init.d/rcS脚本中
# /bin/hostname -F /etc/sysconfig/HOSTNAME,指定到/etc/sysconfig/HOSTNAME
# 中找到主机名。所以在/etc下新建sysconfig文件夹,在里面新建HOSTNAME文件,内
# 容为“UsrName”,该主机名可以随意取

mkdir sysconfig
echo "UsrName" > sysconfig/HOSTNAME
4.3.11 将下面内容导进udhcpd.conf文件
# Sample udhcpd configuration file (/etc/udhcpd.conf)
# Values shown are defaults

# The start and end of the IP lease block
start		192.168.0.20
end		192.168.0.254

# The interface that udhcpd will use
#interface	eth0
interface	wlan0

# The maximum number of leases (includes addresses reserved
# by OFFER's, DECLINE's, and ARP conflicts). Will be corrected
# if it's bigger than IP lease block, but it ok to make it
# smaller than lease block.
#max_leases	254
max_leases	16

# The amount of time that an IP will be reserved (leased to nobody)
# if a DHCP decline message is received (seconds)
#decline_time	3600

# The amount of time that an IP will be reserved
# if an ARP conflict occurs (seconds)
#conflict_time	3600

# How long an offered address is reserved (seconds)
#offer_time	60

# If client asks for lease below this value, it will be rounded up
# to this value (seconds)
#min_lease	60

# The location of the pid file
#pidfile	/var/run/udhcpd.pid

# The location of the leases file
#lease_file	/var/lib/misc/udhcpd.leases

# The time period at which udhcpd will write out leases file.
# If this is 0, udhcpd will never automatically write leases file.
# Specified in seconds.
#auto_time	7200

# Every time udhcpd writes a leases file, the below script will be called
#notify_file			# default: no script
#notify_file	dumpleases	# useful for debugging

# The following are bootp specific options
# next server to use in bootstrap
#siaddr		192.168.0.22	# default: 0.0.0.0 (none)
# tftp server name
#sname		zorak		# default: none
# tftp file to download (e.g. kernel image)
#boot_file	/var/nfs_root	# default: none

# Static leases map
#static_lease 00:60:08:11:CE:4E 192.168.0.54
#static_lease 00:60:08:11:CE:3E 192.168.0.44

# The remainder of options are DHCP options and can be specified with the
# keyword 'opt' or 'option'. If an option can take multiple items, such
# as the dns option, they can be listed on the same line, or multiple
# lines.
# Examples:
#opt	dns	192.168.10.2 192.168.10.10
opt	dns	8.8.8.8
option	subnet	255.255.255.0
#opt	router	192.168.10.2
opt	router	192.168.44.1
opt	wins	192.168.10.10
#option	dns	129.219.13.81	# appended to above DNS servers for a total of 3
option  dns 114.114.114.114
option	domain	local
option	lease	864000		# default: 10 days
option	msstaticroutes	10.0.0.0/8 10.127.0.1		# single static route
option	staticroutes	10.0.0.0/8 10.127.0.1, 10.11.12.0/24 10.11.12.1
# Arbitrary option in hex form:
option	0x08	01020304	# option 8: "cookie server IP addr: 1.2.3.4"

# Currently supported options (for more info, see options.c):
#opt lease      NUM
#opt subnet     IP
#opt broadcast  IP
#opt router     IP_LIST
#opt ipttl      NUM
#opt mtu        NUM
#opt hostname   STRING		# client's hostname
#opt domain     STRING		# client's domain suffix
#opt search     STRING_LIST	# search domains
#opt nisdomain  STRING
#opt timezone   NUM		# (localtime - UTC_time) in seconds. signed
#opt tftp       STRING		# tftp server name
#opt bootfile   STRING		# tftp file to download (e.g. kernel image)
#opt bootsize   NUM		# size of that file
#opt rootpath   STRING		# (NFS) path to mount as root fs
#opt wpad       STRING
#opt serverid   IP		# default: server's IP
#opt message    STRING		# error message (udhcpd sends it on success too)
#opt vlanid     NUM		# 802.1P VLAN ID
#opt vlanpriority NUM		# 802.1Q VLAN priority
# Options specifying server(s)
#opt dns        IP_LIST
#opt wins       IP_LIST
#opt nissrv     IP_LIST
#opt ntpsrv     IP_LIST
#opt lprsrv     IP_LIST
#opt swapsrv    IP
# Options specifying routes
#opt routes     IP_PAIR_LIST
#opt staticroutes   STATIC_ROUTES # RFC 3442 classless static route option
#opt msstaticroutes STATIC_ROUTES # same, using MS option number
# Obsolete options, no longer supported
#opt logsrv     IP_LIST	# 704/UDP log server (not syslog!)
#opt namesrv    IP_LIST	# IEN 116 name server, obsolete (August 1979!!!)
#opt cookiesrv  IP_LIST	# RFC 865 "quote of the day" server, rarely (never?) used
#opt timesrv    IP_LIST	# RFC 868 time server, rarely (never?) used
# TODO: in development
#opt userclass  STRING		# RFC 3004. set of LASCII strings. "I am a printer" etc
#opt sipserv    STRING LIST	# RFC 3361. flag byte, then: 0: domain names, 1: IP addrs
4.4 交叉编译器的lib文件
# 笔者注:arm-linux-gnueabi 和 arm-linux-gnueabihf 的含义与区别

# 交叉编译工具链的命名规则为:arch [-vendor] [-os] [-(gnu)eabi]
# arch – 体系架构,如ARM,MIPS
# vendor – 工具链提供商
# os – 目标操作系统
# eabi – 嵌入式应用二进制接口(Embedded Application Binary Interface)
根据对操作系统的支持与否,ARM GCC可分为支持和不支持操作系统,如

# arm-linux-gnueabi 和 arm-linux-gnueabihf 的含义:
# arm:基于ARM架构的CPU
# linux:Linux系统
# gnu:GNU计划
# eabi:嵌入式应用二进制接口(Embedded Application Binary Interface)
# hf:支持硬件浮点(hard float)

# ARM处理器有 软件浮点、硬件浮点
# 硬件浮点:编译器将代码直接编译成硬件浮点协处理器(浮点运算单元FPU)能识别的指令,
#   这些指令在执行的时候ARM核直接把它转给协处理器执行。FPU 通常有一套额外的寄存器
#   来完成浮点参数传递和运算。使用实际的硬件浮点运算单元(FPU)会带来性能的提升。
# 软件浮点:编译器把浮点运算转成浮点运算的函数调用和库函数调用,没有FPU的指令调用,
#   也没有浮点寄存器的参数传递。浮点参数的传递也是通过ARM寄存器或者堆栈完成。现在
#   的Linux系统默认编译选择使用hard-float,如果系统没有任何浮点处理器单元,这就
#   会产生非法指令和异常。因而一般的系统镜像都采用软浮点以兼容没有VFP的处理器。
# 总结为:
# 软浮点是通过浮点库去实现浮点运算的,效率低;
# 硬浮点是通过浮点运算单元(FPU)来完成的,效率高。


# 切换目录到交叉编译器的核心部分
$ cd /xxx/cc-linaro-arm-linux-gnueabihf-4.7/arm-linux-gnueabihf/

# 查看交叉编译器的lib目录
$ ls lib/lib*.so*
lib/libgcc_s.so           lib/libitm.so            lib/libmudflapth.so.0.0.0
lib/libgcc_s.so.1         lib/libitm.so.1          lib/libssp.so
lib/libgfortran.so        lib/libitm.so.1.0.0      lib/libssp.so.0
lib/libgfortran.so.3      lib/libmudflap.so        lib/libssp.so.0.0.0
lib/libgfortran.so.3.0.0  lib/libmudflap.so.0      lib/libstdc++.so
lib/libgomp.so            lib/libmudflap.so.0.0.0  lib/libstdc++.so.6
lib/libgomp.so.1          lib/libmudflapth.so      lib/libstdc++.so.6.0.17
lib/libgomp.so.1.0.0      lib/libmudflapth.so.0    lib/libstdc++.so.6.0.17-gdb.py
# 拷贝到根文件系统的lib目录下
cp -rf lib/lib*.so* /XXX/busybox/_install/lib/

# 查看交叉编译器的libc/lib目录
$ ls libc/lib/*
libc/lib/ld-linux-armhf.so.3  libc/lib/ld-linux.so.3

libc/lib/arm-linux-gnueabi:
ld-2.15.so               libc.so.6              libnss_dns.so.2         libpthread.so.0
ld-linux.so.3            libdl-2.15.so          libnss_files-2.15.so    libresolv-2.15.so
libanl-2.15.so           libdl.so.2             libnss_files.so.2       libresolv.so.2
libanl.so.1              libm-2.15.so           libnss_hesiod-2.15.so   librt-2.15.so
libBrokenLocale-2.15.so  libmemusage.so         libnss_hesiod.so.2      librt.so.1
libBrokenLocale.so.1     libm.so.6              libnss_nis-2.15.so      libSegFault.so
libc-2.15.so             libnsl-2.15.so         libnss_nisplus-2.15.so  libthread_db-1.0.so
libcidn-2.15.so          libnsl.so.1            libnss_nisplus.so.2     libthread_db.so.1
libcidn.so.1             libnss_compat-2.15.so  libnss_nis.so.2         libutil-2.15.so
libcrypt-2.15.so         libnss_compat.so.2     libpcprofile.so         libutil.so.1
libcrypt.so.1            libnss_dns-2.15.so     libpthread-2.15.so

libc/lib/arm-linux-gnueabihf:
ld-2.15.so               libcidn-2.15.so   libnss_compat-2.15.so   libpcprofile.so
ld-linux-armhf.so.3      libcidn.so.1      libnss_compat.so.2      libpthread-2.15.so
ld-linux.so.3            libcrypt-2.15.so  libnss_dns-2.15.so      libpthread.so.0
libacl.so.1              libcrypt.so.1     libnss_dns.so.2         libresolv-2.15.so
libacl.so.1.1.0          libc.so.6         libnss_files-2.15.so    libresolv.so.2
libanl-2.15.so           libdl-2.15.so     libnss_files.so.2       librt-2.15.so
libanl.so.1              libdl.so.2        libnss_hesiod-2.15.so   librt.so.1
libattr.so.1             libm-2.15.so      libnss_hesiod.so.2      libSegFault.so
libattr.so.1.1.0         libmemusage.so    libnss_nis-2.15.so      libthread_db-1.0.so
libBrokenLocale-2.15.so  libm.so.6         libnss_nisplus-2.15.so  libthread_db.so.1
libBrokenLocale.so.1     libnsl-2.15.so    libnss_nisplus.so.2     libutil-2.15.so
libc-2.15.so             libnsl.so.1       libnss_nis.so.2         libutil.so.1

# 拷贝到根文件系统的lib目录下
# 笔者注:可以只拷贝带硬件浮点运算的协议库(arm-linux-gnueabihf 和 ld-linux-armhf.so.3)
cp -rf libc/lib/* /XXX/busybox/_install/lib/
4.5 OpenSSH的移植
向嵌入式linux开发板移植openSSH:
https://blog.csdn.net/SiberiaBear/article/details/52249218?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~first_rank_v2~rank_v25-1-52249218.nonecase
4.6 Bash的移植
移植 bash到ARM开发板:
https://blog.csdn.net/mengdeguodu_/article/details/103674029
4.7 根文件系统的home目录
cd /XXX/busybox/_install/

# 创建连接nfs的Shell脚本
touch home/nfs.sh
chmod 777 home/nfs.sh

# 将下面内容导入nfs.sh脚本内
#!/bin/sh

# busybox mount -t nfs -o nolock 192.168.xxx.xxx:/home/xxx/nfs/ /mnt/
4.8 根文件系统的usr目录
4.8.1 创建相应的文件
# 笔者注:usr目录下需要好多目录和文件,但笔者只弄了一个UDHCP的脚本
# 后续待更……

cd /XXX/busybox/_install/usr/

# 创建usr相应的目录与文件
mkdir lib
mkdir local
mkdir -p share/udhcpc/
touch share/udhcpc/default.script
4.8.2 将下面内容导进share/udhcpc/default.script文件
#!/bin/sh
# udhcpc script edited by Tim Riker <Tim@Rikers.org>

RESOLV_CONF="/etc/resolv.conf"

[ -n "$1" ] || { echo "Error: should be called from udhcpc"; exit 1; }

NETMASK=""
[ -n "$subnet" ] && NETMASK="netmask $subnet"
BROADCAST="broadcast +"
[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"

case "$1" in
	deconfig)
		echo "Setting IP address 0.0.0.0 on $interface"
		ifconfig $interface 0.0.0.0
		;;

	renew|bound)
		echo "Setting IP address $ip on $interface"
		ifconfig $interface $ip $NETMASK $BROADCAST

		if [ -n "$router" ] ; then
			echo "Deleting routers"
			while route del default gw 0.0.0.0 dev $interface ; do
				:
			done

			metric=0
			for i in $router ; do
				echo "Adding router $i"
				if [ "$subnet" = "255.255.255.255" ]; then
	# special case for /32 subnets:
	# /32 instructs kernel to always use routing for all outgoing packets
	# (they can never be sent to local subnet - there is no local subnet for /32).
	# Used in datacenters, avoids the need for private ip-addresses between two hops.
					ip route add $i dev $interface
				fi
				route add default gw $i dev $interface metric $((metric++))
			done
		fi

		echo "Recreating $RESOLV_CONF"
		# If the file is a symlink somewhere (like /etc/resolv.conf
		# pointing to /run/resolv.conf), make sure things work.
		realconf=$(readlink -f "$RESOLV_CONF" 2>/dev/null || echo "$RESOLV_CONF")
		tmpfile="$realconf-$$"
		> "$tmpfile"
		[ -n "$domain" ] && echo "search $domain" >> "$tmpfile"
		for i in $dns ; do
			echo " Adding DNS server $i"
			echo "nameserver $i" >> "$tmpfile"
		done
		mv "$tmpfile" "$realconf"
		;;
esac

exit 0
4.8.3 将下面内容导进XXXX文件,待更
4.8.4 将下面内容导进XXXX文件,待更
4.8.5 将下面内容导进XXXX文件,待更
4.9 生成JFFS2文件系统镜像文件
4.9.1 生成镜像文件前的准备
# 安装mkfs.jffs2(mtd-utils)工具
sudo apt-get install mtd-utils

# 生成镜像文件过程中提示安装ncurses-doc
sudo apt-get install libncurses5-dev
4.9.2 生成文件系统镜像文件
cd /XXX/busybox/

# 安装mkfs.jffs2工具
sudo apt-get install mtd-utils

# 经计算,本块NandFlash的 EraseSize = 262144b(十进制) = 0x40000(十六进制)
# 生成文件系统的命令为:
sudo mkfs.jffs2 -r ./_install/ --pagesize=0x1000 --eraseblock=0x40000 -n --output=./rootfs.jffs2

注: 根目录etc下的文件格式

文件/目录包含:fstab init.d inittab passwd shadow group rc#.d( #:1/2/3/4/5/6/S/s )
/etc/init.d/下的 sshd syslog networking lighttpd
/etc/init.d/command options
command包含:networking、samba、apache2、ftpd、sshd、dovecot、mysql、……
options包含:start、stop、reload、restart、force-reload
/etc/rc#.d( #:1/2/3/4/5/6/S/s ) 下的脚本的命名形式“1位字母+2位数字+程序名”:
1位字母:S代表Start,K代表Kill,以“K”开头的脚本运行在以“S”开头的脚本之前。
2位数字:数字表示处理顺序,越小越早处理,如果数字相同,就按照字母顺序进行启动。

5.1 passwd文件格式
标准格式:
root : x : 0 : 0 : root : /home/root : /bin/sh

第1段 登录用户名。
第2段 用户的密码原来直接存储在第二字段,但为了安全存储在/etc/shadow文件,默认用x替代。
第3段 当前用户的UID( User ID ),一般情况下Root的UID为0,1-499默认为系统账号。
第4段 当前用户的GID( Group ID )。
第5段 登录名的全名,不是很重要,可以表示该用户的地址等。
第6段 默认登录后所在目录。
第7段 登录后执行的脚本。arm Linux中是/bin/sh而不是/bin/bash。
5.2 shadow文件格式
标准格式:
root : : 16092 : 0 : 99999 : 7 : : :

第1段 登录用户名。
第2段 用户的密码加密字段。
第3段 密码已经使用的日期 ( Unix时间戳 )。
第4段 密码最少多少天之后可以修改 ( 0 代表0天 )。
第5段 密码多少天之后必须修改 ( 若为 99999 则表示一直不用改密码 )。
第6段 密码修改之前几天提醒修改 ( 7 代表7天 )。
第7段 失效期后到完全禁用的天数。
第8段 账号失效期 ( 空代表帐号永久可用 )。
第9段 保留字段,目前无含义。
5.3 inittab文件格式

inittab文件在系统中的使用情况
图片是很久之前在网上看到觉得有用就保存下来,若侵权请提醒笔者删除

标准格式:
identifier : runlevels : action : process

第1段 Identifier登记项标识符,最多为4个字符。用于惟一地标识 /etc/inittab 文件中的每一个登记项。
	id:用来定义缺省的init运行的级别。
	si:是系统初始化的进程。
	ln:其中的n从1-6,指明该进程可以使用的runlevel的级别。
	ud:是升级进程。
	ca:指明当按下Ctrl+Alt+Del时运行的进程。
	pf:指当UPS表明断电时运行的进程。
	pr:是在系统真正关闭之前,UPS发出电源恢复的信号时需要运行的进程。
	x:是将系统转入X终端时需要运行的进程。
	runlevel字段指定runlevel的级别。可以指定多个runlevel级别,也可以不为runlevel字段指定特定的值。

第2段 Runlevels系统运行级,用于指定相应的登记项在哪一个运行级中被处理。如果该字段为空,那么相应的登记项将适用于所有的运行级。在该字段中,可以同时指定一个或多个运行级,其中各运行级分别以数字或字母0、1、2、3、4、5、6、S、s表示,且无需对其进行分隔。
	0、1、6运行级别被系统保留:其中0作为shutdown动作,1作为重启至单用户模式,6为重启;S和s意义相同,表示单用户模式,且无需inittab文件,因此也不在inittab中出现,实际上,进入单用户模式时,init直接在控制台(/dev/console)上运行/sbin/sulogin。在一般的系统实现中,都使用了2、3、4、5几个级别,在Redhat系统中,2表示无NFS支持的多用户模式,3表示完全多用户模式(也是最常用的级别),4保留给用户自定义,5表示XDM图形登录方式。7-9级别也是可以使用的,传统的Unix系统没有定义这几个级别。runlevel可以是并列的多个值,以匹配多个运行级别,对大多数action来说,仅当runlevel与当前运行级别匹配成功才会执行。
	0:让init关闭所有进程并终止系统。
	1:用来将系统转到单用户模式,单用户模式只能有系统管理员进入,在该模式下处理那些在有登录用户的情况下不能进行更改的文件,改Runlevel的编号“1”可以用“S”代替。
	2:允许系统进入多用户的模式,但并不支持文件共享,这种模式很少应用。
	3:最常用的运行模式,用来提供真正的多用户模式,也是多数服务器的缺省模式。
	4:一般不被系统使用,用户可以设计自己的系统状态并将其应用到Runlevel。
	5:将系统初始化为专用的X Window终端。对功能强大的Linux系统来说,这并不是好的选择,但用户如果需要这样,也可以通过在Runlevel启动来实现该方案。
	6:关闭所有运行的进程并重新启动系统。

第3段 Action字段描述其后的Process的运行方式。
	respawn:init应该监视这个进程,即使其结束也会被重新启动,永不结束。
	wait:init应该运行这个进程一次,并等待其结束后再进行下一步操作。
	once:init只运行一次该进程。
	boot:系统启动时运行该进程,忽略runlevel。
	bootwait:在系统启动时运行,init等待进程完成,忽略runlevel。
	ctrlaltdel:当Ctrl+Alt+Del三个键同时按下时运行,把SIGINT信号发送给init,忽略runlevel。
	sysinit:在运行Boot或Bootwait进程之前运行。
	powerfail:当init收到SIGPWR信号时运行。
	powerokwait:当收到SIGPWD信号且 /etc/ 文件中的电源状态包含OK时运行。
	powerwait:当收到SIGPWD信号,并且init等待进程结束时运行。
	askfirst:启动完respawn进程后,与respawn类似,不过init进程先输出“Please press Enter to activate this console”,等用户输入回车后才启动子进程。
	shutdown:当系统关机时,即重启、关闭系统时执行的程序。
	restart:系统重启时init 进程重启时执行的程序,通常是Init程序本身先重新读取、解析 /etc/inittab 文件,再执行 restart 程序。
	ondemand:当系统指定特定的运行级别A、B、C时运行。
	initdefault:不要执行这个进程,它用于设置默认runlevel。
	kbrequest:当init从键盘中收到信号时运行。这里要求键盘组合符合KeyBoardSigral(参见/usr/share/doc/kbd-*关于键盘组合的文档)。
	off:禁止进入,因此该进程不运行。

第4段 Process字段,表示所要执行的Shell命令。任何合法的Shell语法均适用于该字段。
5.4 group文件格式
标准格式:
group_name : passwd : GID : user_list

第1段 用户组名称。
第2段 用户组密码,这个段一般为空,或者是“x”( 表示没有设置密码 )。
第3段 GID。
第4段 用户列表,每个用户之间用“,”号分割,本段可以为空;如果字段为空表示用户组为GID的用户名。
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值