一、工具准備工作
要想在ARM平台上移植一套Apache+Msql+PHP的Web型服務器。
所用物理機系統: Ubuntu 14.04 LTS(64位)
交叉編譯環境: arm-linux-gnueabihf-gcc-4.7.3(32位)
gcc-4.8.4(64位)
所需源碼: Httpd-2.4.3.tar.gz
Pcre-8.31.tar.gz
Apr-1.4.6.tar.gz
Apr-util-1.4.1.tar.gz
Mysql-5-1-51.tar.gz
Ncurses-5.6.tar.gz
PHP-5.6.16.tar.gz
Libxml-2.7.2.tar.gz
Zlib-1-2-7-tar.gz
目標機器環境: AM335X(ARM)
其中:U-boot和內核是用TI的SDK工具包,然后用arm-linux-gnueabihf-交叉編譯鏈編譯出的;文件系統是用Busybox制作的最小的文件系統,當然,交叉編譯工具和內核是一樣的,必須是同一個編譯工具。這里我就栽了一個跟頭,沒有同一內核和文件系統還有應用軟件的編譯工具,導致最后編譯出來的內核或應用程序無法正常工作。所以在此強調,內核和其他應用軟件的編譯工具必須統一,從道到尾都用同一個。U-boot可以用任何交叉編譯器編譯,可以跟內核的不一樣,也能跑的起來,因為uboot只是一個引導系統啟動的一個程序,啟動后就沒他的事了,就是操作系統在管理了。但是,應用程序是在操作系統上跑的,文件系統也一樣,所以編譯應用軟件的編譯工具必須跟內核的一樣,否者這個應用程序無法在該系統上跑。
二、編譯安裝Apache
2.1、下載安裝包:
要安裝Apache,需要先下載好這四個源碼包:
httpd-2.4.3.tar.gz 、Pcre-8.3.1.tar.gz 、Apr-1.4.6.tar.gz、 Apr-util-1.4.1.tar.gz
當然並不是只有這些版本的源碼可以安裝,還有很多可以的,我嘗試了,4個版本的Apache,最后發現2.0以上的版本才能編譯通過(對於我的物理機上的交叉編譯鏈來說)。因為apache2.0以下的版本比較久,所以我下載了一個也比較過時的交叉編譯編譯工具arm-linux-gcc 4.6.3來試了一下,是可以編譯通過的,但是在我的內核上跑不起來,原因就是上面說的內核和應用程序的編譯工具不統一(內核的編譯工具是arm-linux-gnueabihf-gcc)。所以最后我選擇安裝2.0以上的版本。
2.2、 安裝開發包
假設我已經創建好了/home/ccj/works目錄下了,把下載好的安裝包都copy到該目錄下,然后解壓。會得到httpd-2.4.3、pcre-8.3.1、apr-1.4.6、apr-util-1.4.1。
2.2.1、本地編譯 (X86_64平台)
1. 安裝pcre-8.3.1
#tar –zxvf pcre-8.31.tar.gz
#cd pcre-8.31
#./configure -–prefix=/home/ccj/install/local/pcre
#make
#make install
2、安裝apr
# tar –zxvf apr-1.4.6.tar.gz
#cd apr-1.4.6
#./configure --prefix=/home/ccj/install/local/apr
#make
#make install
3、安裝apr-util
#tar –zxvf apr-util-1.4.1.tar.gz
#cd apr-util-1.4.1
#./configure --prefix=/home/ccj/install/local/apr-util --with-apr=/home/ccj/install/local/apr
#make
#make install
4、 安裝httpd
#tar –zxvf httpd-2.4.3.tar.gz
#cd httpd-2.4.3
#./configure --prefix=/home/ccj/install/apache --with-pcre=/home/ccj/install/local/pcre --with-apr=/home/ccj/install/local/apr --with-apr-util=/home/ccj/install/local/apr-util
#make
make 完之后把httpd-2.4.3改名為httpd-pc。目的是為了讓在當前的目錄下從新解壓一個httpd-2.4.2出來,這個是用來進行交叉編譯的,但是交叉編譯的時候會用到一個執行腳本,而這個腳本必須是在物理機上執行的,所以交叉編譯出來的那個不能在物理機上執行,才需要將剛剛在本地物理機上編譯完成的httpd-pc中拷貝過來,然后將它覆蓋替換掉,但是為了保證相對目錄的位置不變,所以才需要將剛剛本地編譯完的那個改名為httpd-pc,然后再在當前目錄下在解壓一個httpd-2.4.3。
好了,本地編譯到此完成!
2.2.2、交叉編譯 (ARM平台)
1、 安裝pcre
#cd pcre-8.31
#make clean
#./configure --prefix=/home/ccj/installl/pcre --host=arm-linux-gnueabihf
#make
#make install
2、安裝apr
#cd apr-1.4.6
#make clean
# ./configure --prefix=/home/ccj/installl/apr --host=arm-linux-gnueabihf ac_cv_file__dev_zero=yes ac_cv_func_setpgrp_void=yes apr_cv_tcp_nodelay_with_cork=yes ac_cv_sizeof_struct_iovec=8 --cache=arm-linux.cache
#make
#make install
這里簡要說明一下如果不添加某些選項會出現的錯誤提示及一些需要特別注意的地方(這里按照我所記錄的錯誤出現的順序說明,而不是按上面選項的順序):
①如果不添加ac_cv_file__dev_zero=yes(注意file和dev之間是兩個下划線),則會出現:
check for /dev/zero... configure:error:cannot check for file existence when cross compile 的錯誤
②如果不添加ac_cv_func_setpgrp_void=yes,則會出現:
checking whether setpgrp takes no argument... configure: error: cannot check setpgrp when cross compiling 的錯誤
③選項--cache=arm-linux.cache中,arm-linux.cache為自己建立編寫的文件(在編譯過程中內容會被修改),在建立時需要自己寫入如下內容:
④ apr_cv_process_shared_works=yes
apr_cv_mutex_robust_shared=yes
如果不寫入第一項,則會出現:
checking for working PROCESS_SHARED locks... configure:error: in `.../apr-1.4.6':
configure:error: cannot run test program while cross compiling See `config.log' for more details
如果不寫入第二項,則會出現:
checking for robust cross-process mutex support... configure: error: in `.../apr-1.4.6' configure: error: cannot run test program while cross compiling See `config.log' for more details的錯誤
在以后為開發板配置軟件包時遇到這種錯誤:configure:error:cannot run test program while cross compiling,應該都可以通過這種方法解決。但是我還有一種方法,也是我比較喜歡的方式,可以避免帶那么多的參數。因為這些錯誤產生的原因在於這里在configure運行配置的過程中要運行幾個測試程序來檢驗一些配置,但在此處指定了編譯時采用的編譯器是交叉編譯鏈,這幾個測試程序都是經過交叉編譯鏈編譯產生的,而在宿主機系統上無法運行這些程序。因此,我就在configure文件里把這些產生測試程序的地方把他們注釋掉,這樣執行./condigure的時候就不會生成測試程序了,就可以通過編譯了。
⑤如果不添加ac_cv_sizeof_struct_iovec=8選項,則會在使用make指令時出現:
./include/apr_want.h:95: error: redefinition of 'struct iovec'
make[1]: *** [passwd/apr_getpass.lo] 錯誤
在添加了ac_cv_sizeof_struct_iovec=8選項后,還需要對configure文件進行一下修改,搜索apr_ssize_t可以定位到下面一段代碼:
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which format to use for apr_ssize_t" >&5
$as_echo_n "checking which format to use for apr_ssize_t... " >&6; }
if test -n "$ssize_t_fmt"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: %$ssize_t_fmt" >&5
$as_echo "%$ssize_t_fmt" >&6; }
elif test "$ac_cv_sizeof_ssize_t" = "$ac_cv_sizeof_int"; then
ssize_t_fmt="d"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: %d" >&5
$as_echo "%d" >&6; }
elif test "$ac_cv_sizeof_ssize_t" = "$ac_cv_sizeof_long"; then
ssize_t_fmt="ld"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: %ld" >&5
$as_echo "%ld" >&6; }
else
as_fn_error $? "could not determine the proper format for apr_ssize_t" "$LINENO" 5
fi
將中間添加一段代碼(紅色標注),修改為:
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which format to use for apr_ssize_t" >&5
$as_echo_n "checking which format to use for apr_ssize_t... " >&6; }
if test -n "$ssize_t_fmt"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: %$ssize_t_fmt" >&5
$as_echo "%$ssize_t_fmt" >&6; }
elif test "$ac_cv_sizeof_ssize_t" = "$ac_cv_sizeof_int"; then
ssize_t_fmt="d"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: %d" >&5
$as_echo "%d" >&6; }
elif test "$ac_cv_sizeof_ssize_t" = "$ac_cv_sizeof_long"; then
ssize_t_fmt="ld"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: %ld" >&5
$as_echo "%ld" >&6; }
elif test "$ac_cv_sizeof_ssize_t" = "$ac_cv_sizeof_long_long";then
ssize_t_fmt="lld"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: %lld" >&5
$as_echo "%lld" >&6; }
else
as_fn_error $? "could not determine the proper format for apr_ssize_t" "$LINENO" 5
fi
搜索apr_size_t可以定位到下面一段代碼:
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which format to use for apr_size_t" >&5
$as_echo_n "checking which format to use for apr_size_t... " >&6; }
if test -n "$size_t_fmt"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: %$size_t_fmt" >&5
$as_echo "%$size_t_fmt" >&6; }
elif test "$ac_cv_sizeof_size_t" = "$ac_cv_sizeof_int"; then
size_t_fmt="d"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: %d" >&5
$as_echo "%d" >&6; }
elif test "$ac_cv_sizeof_size_t" = "$ac_cv_sizeof_long"; then
size_t_fmt="ld"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: %ld" >&5
$as_echo "%ld" >&6; }
else
as_fn_error $? "could not determine the proper format for apr_size_t" "$LINENO" 5
fi
將中間添加一段代碼(紅色標注),修改為:
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which format to use for apr_size_t" >&5
$as_echo_n "checking which format to use for apr_size_t... " >&6; }
if test -n "$size_t_fmt"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: %$size_t_fmt" >&5
$as_echo "%$size_t_fmt" >&6; }
elif test "$ac_cv_sizeof_size_t" = "$ac_cv_sizeof_int"; then
size_t_fmt="d"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: %d" >&5
$as_echo "%d" >&6; }
elif test "$ac_cv_sizeof_size_t" = "$ac_cv_sizeof_long"; then
size_t_fmt="ld"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: %ld" >&5
$as_echo "%ld" >&6; }
elif test "$ac_cv_sizeof_size_t" = "$ac_cv_sizeof_long_long"; then
size_t_fmt="lld"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: %lld" >&5
$as_echo "%lld" >&6; }
else
as_fn_error $? "could not determine the proper format for apr_size_t" "$LINENO" 5
fi
如果什么修改也不做,則會出現:
checking which format to use for apr_ssize_t... configure:error:could not determine the proper format for apr_ssize_t的錯誤
如果只做了第一個修改,則會出現:
checking which format to use for apr_size_t... configure:error:could not determine the proper format for apr_size_t的錯誤
這是apr源代碼包本身有的bug,這樣修改后,在最后編譯httpd時,會出現一些warning,大概意思是說參數類型為pid_t的地方,出現的參數類型為long long,但pid_t的類型本身就是unsigned int,因此應該是沒有問題的。
3、安裝apr-util
# cd apr-util-1.4.1
# make clean
#./configure --prefix=/home/ccj/install/apr-util --with-apr=/home/ccj/install/apr --host=arm-linux-gnueabihf
# make
# make install
4、 安裝httpd
#tar –zxvf httpd-2.4.3.tar.gz
#cd httpd-2.4.3
#./configure
--prefix=/home/ccj/install/apache --with-pcre=/home/ccj/install/pcre --with-apr=/home/ccj/install/apr --with-apr-util=/home/ccj/install/apr-util --host=arm-linux-gnueabihf ap_cv_void_ptr_lt_long=no --enable-so --enable-cgi LDFLAGS=-lpthread --with-mpm=prefork
①如果不添加ap_cv_void_ptr_lt_long=no選項,則會出現:configure: error: Size of "void *" is less than size of "long"的錯誤
②如果不添加--with-mpm=prefork選項,則在啟動httpd服務器時會出現閃退,無法正常啟動。
#make
make的時候會出現
util.c: In function 'ap_find_token':
util.c:1434: error: 'test_char_table' undeclared (first use in this function)
util.c:1434: error: (Each undeclared identifier is reported only once
util.c:1434: error: for each function it appears in.)
這樣的錯誤提示,意思就是說編譯中間生成的程序需要馬上在Ubuntu上執行,當時Ubuntu沒法運行ARM下的二進制文件,所以報錯了。解決的辦法就是到這個文件的所在文件夾下面,(如果不知道這個文件在源碼包的那個文件夾下面的話,那么對整個源碼包進行文件搜索,你想要的文件馬上就會出現在你的眼前),所以用這個方法找文件在源碼包的那個位置是很方便的,我就不累贅這些文件到底在哪個哪個文件目錄了,下面的亦然。
那么這個問題的解決方法呢!就是先把交叉編譯生成的ARM平台上運行的二進制執行文件給刪除了,然后再從我們上面通過本地編譯生成的在Ubuntu平台能運行的x86_64的同名文件給拷貝到此。但是,還沒結束,接下來才是最關鍵的,這個時候要執行這條語句:
touch -m /home/ccj/works/httpd-2.4.3/server/gen_test_char
上面的命令是改變gen_test_char的最后修改時間,這樣做的目的是告訴編譯器gen_test_char已經是最新的了,不要重新生成它,否則編譯器檢查gen_test_char和它的依賴文件的最后修改時間會發現gen_test_char比它的依賴文件更舊,就會重新交叉編譯生成它,這樣不管我們做幾次覆蓋的工作錯誤都還會再現。
#make
#make install
到此,apache成功編譯出來了。
2.2.3、移植到開發板及復制共享庫
1、將httpd-4.2.3編譯好的/home/ccj/install/apache文件夾拷貝到開發板對應的/home/ccj/install目錄下,為減少占用資源,可以將manual目錄刪掉。拷貝到開發板上相同的安裝目錄下這點很重要,否者會出現很多奇葩的錯誤,比如個別文件采用的是絕對文件目錄的話,如果你改變了他的文件路徑,它就找不着北了。
2、復制一些共享庫到開發板文件系統的/lib目錄下,否則會啟動不了httpd服務器,像以下錯誤:
①error while loading shared libraries: libpcre.so.1:cannot open shared object file:No such file for directory
解決方法:cp /home/ccj/install/pcre/lib/libpcre.so* /lib
②error while loading shared libraries: libaprutil-1.so.0:cannot openshared object file:No such file for directory 解決方法:cp /home/ccj/install/apr-util/lib/libaprutil-1.so* /lib ③error while loading shared libraries: libexpat.so.0:cannot open shared object file:No such file for directory
解決方法:cp /home/ccj/install/apr-util/lib/libexpat.so* /lib
④error while loading shared libraries: libapr-1.so.0:cannot open shared object file:No such file for directory
解決方法:cp /home/ccj/install/apr/lib/libapr-1.so* /lib
如果還有其他缺少的庫,那請就根據linux提示的錯誤信息,從物理機上用交叉編譯出來的源碼包里找到這個缺失的庫,然后copy到開發板的/lib目錄下面。
2.2.4、配置httpd.conf
1、apache拒絕使用root用戶運行。所以你需要增加一個用戶和用戶組,我們可以使用用戶名和用戶組名分別為nobody和nogroup。沒有的話,就在/etc/passwd和/etc/group兩個文件中添加。這樣我們就在httpd.conf中的用戶和組修改為nobody和nogroup,具體來說就是在ARM Linux根文件系統上立/etc/passwd和/etc/group兩個文件,它們的內容可以如下:
/etc/passwd
root::0:0:root:/:/bin/ash
nobody::65534:65533:nobody:/:/bin/ash
/etc/group
nobody::65533:
nogroup::65534:nobody
root::0:
users::100
2、修改http.conf
Listen 0.0.0.0:80
Listen 80
User nobody
Group nobody
ServerAdmin yuaf059@nenu.edu.cn
ServerName localhost:80
主要配置這幾個地方
2.2.5、疑難雜症
由於我的文件系統使用busybox制作出來的最簡單的文件系統,最簡單有個好處,就是開機速度超快,但因為文件系統太簡單了,很多功能都得自己重新加上去,比如設定固定IP地址,比如NFS文件系統,這些都需要自己手動創建,有時候因為缺少個別重要的系統文件,會導致一些應用程序跑不起來,比如這里的apache。就遇到這個問題。
當我啟動的Apache的時候,系統提示出現這樣的錯誤
[:crit] [pid 0] (2)No such file or directory: AH00141: Could not initialize random number generator
最后找了很久,發現問題出在我制作的跟文件系統下面缺少了/dev/random 和 /dev/urandom 這兩個文件,這兩個是系統級別的文件,沒有的話很多程序會跑不起來
解決辦法:
在/dev下面創建這兩個文件:用下面這三條語句輕松搞定
#mknod -m 644 /dev/random c 1 8
#mknod -m 644 /dev/urandom c 1 9
#chown root:root /dev/random /dev/urandom
OK!現在可以開啟你夢寐以求的Apache了,在/home/cch/install/apache/bin/ 下,執行./apachectl這個文件,然后Apache就在你的開發板上跑起來了,在開發板上輸入top命令,
PID PPID USER STAT VSZ %VSZ CPU %CPU COMMAND
1 0 root S 2088 0.4 0 0.0 init
957 1 root S 5012 0.9 0 0.0 /home/ccj/install/apache/bin/httpd
958 957 nobody S 5012 0.9 0 0.0 /home/ccj/install/apache/bin/httpd
959 957 nobody S 5012 0.9 0 0.0 /home/ccj/install/apache/bin/httpd
960 957 nobody S 5012 0.9 0 0.0 /home/ccj/install/apache/bin/httpd
961 957 nobody S 5012 0.9 0 0.0 /home/ccj/install/apache/bin/httpd
962 957 nobody S 5012 0.9 0 0.0 /home/ccj/install/apache/bin/httpd
出現上面這樣的結果,表示已經成功了。從這里可以清楚的看出,Apache不是用root用戶啟動的,而是用nobody啟動的,而且Apache的子進程都是由“957”這個父進程創建出來的,而“957”的父進程是“1”;“1”進程又是init進程,系統的元老級的進程:init。
三、編譯安裝Mysql
3.1、下載安裝包:
要安裝mysql,需要先下載好這兩個源碼包
ncurses-5.6.tar.gz myqsl-5.1.51.tar.gz
3.2、 安裝開發包
假設我已經創建好了/home/ccj/works目錄下了,把下載好的安裝包都copy到該目錄下,然后解壓。會得到 ncurses-5.6 、myqsl-5.1.51。
3.2.1、編譯本地版本mysql
#cd mysql-5.1.51
#./configure -prefix=/usr/local/mysql
#make
①、運行configure
如果出現以下提示信息(沒有出錯就不用管):
checking for termcap functions library… configure: error: No curses/termcap library found
那么就安裝libncurses5-dev進行解決: root@ubuntu:/opt/lib/mysql-5.1.51# apt-get install libncurses5-dev
②、make完成后,將這個文件夾改名為mysql-5.1.51-pc留作備用。
3.2.2、交叉編譯ARM平台下的mysql
要交叉編譯MySQL -ARM版本,首先我們得先得到一個交叉編譯過的libncurses.a的庫,所以為了方便,我們先做這一步。
(1)、交叉編譯ncurses-5.6.tar.gz
# cd ncurses-5.6
#./configure -host=arm-linux-guneabihf -prefix=/home/ccj/install/ncurse –enable-static
# make
# make install
(2)、重新解壓mysql-5.1.51.tar.gz得到mysql-5.1.51
(3)、修改configure,注釋掉不支持交叉編譯的部分
找到所有如下語句:
①. if test "$cross_compiling" = yes; then
②. { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
③. $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
④. { { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5
⑤. $as_echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;}
⑥. { (exit 1); exit 1; }; }; }
⑦. else
修改成
①. if test "$cross_compiling" = yes; then
②. echo “skip corss_compiling test”;
③. #{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
④. # $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
⑤. #{ { $as_echo "$as_me:$LINENO: error: cannot run test program while
⑥. # cross compiling See \`config.log' for more details." >&5
⑦. #$as_echo "$as_me: error: cannot run test program while cross compiling #See \`config.log' for more details." >&2;}
⑧. #{ (exit 1); exit 1; }; }; }
⑨. else
注意:原文有4處這樣的地方,都要找出來注釋掉。或者可以用上面提到的方法,把 ①. if test "$cross_compiling" = yes; 中的yes改為no
(4)、交叉編譯MySQL
有了這些准備工作,這個時候就可以交叉編譯MySQL了。
①、配置configure ./configure --host=arm-linux-gnuaebihf --enable-static --with-named-curses-libs=/home/ccj/install/ncurses/lib/libncurses.a --prefix=/home/ccj/install/mysql --without-debug --without-docs --without-man --without-bench --with-charset=gb2312 --with-extra-charsets=ascii,latin1,utf8
②、make
make的時候會出現這樣的錯誤
make[2]: Leaving directory `/opt/mysql-5.5.3-m3/sql'
./gen_lex_hash > lex_hash.h-t
/bin/sh: ./gen_lex_hash: cannot execute binary file
這個時候就需要將剛才我們編譯好的PC版本的$mysql\sql\目錄下面的gen_lex_hash,然后cp到現在交叉編譯時對應的$mysql\sql\目錄覆蓋即可。覆蓋完成后不要急於make,這時輸入如下命令:touch –mysql/gen_lex_hash
然后再執行make
若出現錯誤:
sql_parse.cc:5432:21: operator '<' has no left operand
解決辦法:
這是由於宏變量STACK_DIRECTION沒有定義初值,網上查找資料發現arm中定義STACK_DIRECTION為1,所以找到sql_parse.cc文件,將第5432行的前面一行加入#define STACK_DIRECTION 1
③、make install
至此,mysql已經編譯完成,接下來就是移植和配置了。
3.3、移植mysql到ARM平台
a) 拷貝編譯生成的mysql到/home/ccj/installmysql開發板的相同目錄下
b) 到源碼中拷貝配置文件模版
將PC上的/home/ccj/works/mysql-5.1.51/support-files/my-medium.cnf這個文件copy一份到開發板的/etc下,並改名字為my.cnf
這里的my.cnf存放的路徑是按照手冊上的建議,前面編譯pc版本的MySQL中所述的路徑並非全局配置。該文檔的注釋中說:“# You can copy this file to /etc/my.cnf to set global options, mysql-data-dir/my.cnf to set server-specific options (in this installation this directory is /usr/local/mysql/var) or ~/.my.cnf to set user-specific options.”該配置文件的修改詳見mysql5.1的英文手冊的4.2.3.3. Using Option Files節中的敘述。
數據目錄是在:/var/lib/mysql (默認)
安裝目錄是在:/usr/local/mysql (默認)
但是我這里的安裝目錄是/home/ccj/install/mysql,跟默認的不一樣,所以要到配置文件里面去更改一下,數據目錄我改到/home/ccj/install/var下。
c)手動建立mysqld/mysqld.pid,手工建立: (這一步不需要,制定到/tmp/mysqld.pid就行)
#mkdir /home/ccj/install/mysql/var/run/mysqld
#touch /home/ccj/install/mysql/var/run/mysqld/mysqld.pid
這一步不知道是不是必須的。但我這樣做了。
d) 到源碼中拷貝啟動文件
/home/ccj/works/mysql-5.1.51/support-files/mysql.server 這個文件copy一份到開發板的/etc/init.d/目錄下,並改名為mysqld
修改該mysqld
詳見手冊中4.3.1. mysqld — The MySQL Server的敘述
加上了basedir和datadir,
還有pid-file=/tmp/mysqld.pid
還有service-pid-file=/tmp/mysqld.pid
修改完后,要給新的mysqld附以足夠的權限: Chmod +x mysqld
e) 設置軟連接使mysql, mysqldump, mysqladmin這三個命令能在開發板的shell中直接運行
# ln -s /home/ccj/install/mysql/bin/mysql /usr/bin
# ln -s /home/ccj/install/mysql/bin/mysqldump /usr/bin
# ln -s /home/ccj/install/mysql/bin/mysqladmin /usr/bin
其他的還有:鏈接庫文件
ln -s /home/ccj/install/mysql/lib/mysql/libmysqlclient.so.16 /lib
f) 在開發板開啟MySQL服務
開發板不支持service指令,所以service mysql start無效。
采用的方法是運行./etc/init.d/mysqld start
但最初運行該指令后出現下面的錯誤:
Starting MySQL... ERROR! Manager of pid-file quit without updating file.
困擾我好久,到開發板目錄/var/lib/mysql下查閱錯誤日志文件[hostname].err,在我的系統中該錯誤日志文件為EmbedSky.err,從中看到下面的記錄:
150713 21:04:49 [ERROR] Fatal error: Can't change to run as user 'mysql' ; Please check that the user exists!
可能的原因是:在arm的linux上無法執行groupadd mysql,因此需要采用如下方法解決該問題: cd /home/ccj/install/mysql/var/lib/mysql
ls –la可以看到里面的屬性中沒有mysql,於是使用下面的命令: adduser mysql
chown mysql:mysql -R /var/lib/mysql
然后開啟mysql服務,還是出現了ERROR! Manager of pid-file quit without updating file.又查看EmbedSky.err日志,其中多了一條:
150714 2:48:04 [ERROR] Can't start server: Bind on TCP/IP port: Address already in use
150714 2:48:04 [ERROR] Do you already have another mysqld server running on port: 3306 ?
很顯然是因為已經有mysql的進程嘗試打開3306端口,因此就被占用了,需要殺進程,索性重啟開發板,然后運行/etc/init.d/mysqld start,可以完美打開。
3.4、測試ARM平台下的MySQL
a) mysqladmin -uroot -p123456 最后一項為我的密碼 (設置密碼)
b) mysql -h 127.0.0.1 -uroot -p123456 或mysql -h localhost -uroot -p123456 這樣便可以進入mysql環境。
c) mysql>show databases;
mysql>create databases table1;
mysql>use table1;
mysql>create table student(id int(4) not null primary key auto_increment,stuname char(20));
mysql> insert into student(stuname) values('Tom');
如果這個成功了,那么后面就可以用這個來測試PHP與mysql能否協調工作了!到此,mysql也算成功移植上去了。
四、編譯安裝PHP
4.1、下載安裝包:
要安裝mysql,需要先下載好這三個源碼包
PHP-5.6.16.tar.gz Libxml-2.7.2.tar.gz Zlib-1.2.7-tar.gz
4.2、 安裝開發包
假設我已經創建好了/home/ccj/works目錄下了,把下載好的安裝包都copy到該目錄下,然后解壓。會得到php.5-6-16、libxml-2.7.2、zlib-1.2.7。
4.2.1、編譯本地版本PHP
#cd php.5-6-16
#./configure -prefix=/usr/local/php
# make
make完成后,將這個文件夾改名為php.5-6-16-pc留作備用。
4.2.2、交叉編譯ARM平台的PHP
(1)、交叉編譯安裝zlib
#cd zlib-1.2.7
#CC=arm-linux-gnueabihf-gcc ./configure --prefix=/home/ccj/install/zlib --host=arm-linux-gnueabihf --enable-shared
#make
#make install
(2)、交叉編譯安裝libxml
#cd libxml-2.7.2
#CC=arm-linux-gnueabihf-gcc ./configure --prefix=/home/ccj/install/libxml --host=arm-linux-gnueabihf --enable-#shared
#make
#make install
(3)、交叉編譯PHP
從新解壓php-5.6.16.tar.gz,得到php.5-6-16源碼
①、#cd php.5-6-16
②、#CC=arm-linux-gnueabihf-gcc \
./configure --host=arm-linux-gnueabihf \
--with-apxs2=/home/ccj/install/apache/bin/apxs \
--prefix=/home/ccj/install/php_arm \
--enable-pdo \
--with-mysql=/home/ccj/install-p/usr/local/mysql \
--with-mysqli=/home/ccj/install-p/usr/local/mysql/bin/mysql_config \
--with-pdo-mysql \
--with-zlib=/home/ccj/install/zlib \
--with-libxml-dir=/home/ccj/install/lib \
--enable-opcache=no \
--without-iconv
上面的apahce和mysql都是基於ARM的版本
執行configure時,可能會出現cannot run test program while cross compiling的錯誤,然后我查看了一下configure,發現只要把這四個地方的yes改為no即可。然后有些地方用了gcc -V的參數,是不能通過的,所以改為-v "可能需要注意一下大小寫"
③、接着#make
make的時候出現的經典的錯誤是上面提到的
generating phar.php/home/jason........./sapi/cli/php:1:Syntax error:word unexpected (expecting “)”)
或者
Generating phai.phai/home/jason/........./sapi/cli/php:1;syntax error:word unexpected (expecting “)”)
這個時候就需要本地編譯出來的PHP來幫忙了。我將基於PC平台下編譯的/sapi/cli/php拷貝到基於ARM的這個地方,當然先得將這里原來的備份改名成php-back,后面這個php-back還會用到的。這樣make就不會報錯了。
當然,這個時候還不能急着make,因為我們剛剛替換的php如果make就會把我們剛剛替換的那個php給沖掉,怎么解決的呢!當然是先touch -m php 一下這個文件,目的是告訴編譯器不要去跟新這個php文件。
④、然后#make test
⑤、最后#make install
在make install的時候我還遇到很多莫名奇妙的問題,說我在apache的安裝目錄下缺失了很多apr和apr-util的頭文件,當然,我把這些文件copy到我指定的apache安裝目錄下面。OK。這樣就能make install 了。
4.3、移植PHP到ARM平台
a)將交叉編譯生成的php拷貝到開發板的相同目錄下面,將源碼包的php-back文件拷貝到/home/ccj/install/php/bin下,並改名為php;拷貝php.ini-development文件拷貝到/home/ccj/install/php/lib下並改名為php.ini。
b)修改apache下的配置文件/home/ccj/install/apache/conf/httpd.conf
DirectoryIndex index.html
DirectoryIndex index.php
DirectoryIndex index.php3
DirectoryIndex index.phtml
ScriptAlias /cgi-bin/ "/usr/local/apache/cgi-bin/"
ScriptAlias /php5/ "/home/ccj/install/php/bin/"
AddType application/x-tar .tgz
AddType application/x-httpd-php .php3
AddType application/x-httpd-php .php
AddType application/x-httpd-php .phtml
紅色的部分是需要添加的,這樣apache就能支持php了。
五、測試Apache、PHP、MySQL的總體功能
1、在apache的htdocs下建立一個php文件php_test.php,里面的內容如下:
<?php
phpinfo();
?>
然后在瀏覽器里輸入http://127.0.0.1/php_test.php
如果出現php的相關配置,則證明Apache能成功啟動調用PHP,如果什么都沒有輸出,說明失敗!
2、在apache的htdocs下建立一個php文件mysql_test.php,里面的內容如下:
<?php
$mysqli=new mysqli();
$mysqli->connect('localhost','root','123456','table1');
$sqlstr='select * from student';// 創建查詢
$result=$mysqli->query($sqlstr);//發送查詢給MySql
while($row=$result->fetch_object())
{
$name=$row->stuname;
echo $name;
}
?>
然后在瀏覽器里輸入http://127.0.0.1/mysql_test.php
如果能在瀏覽器上出現
Tom
這個我們在mysql里面存放的一條記錄,那么證明PHP是可以成功調用MySQL數據庫的。到此,整個移植過程就順利完成了。可能你還會遇到其他我沒有提及到的錯誤,這時候你就要自己去百度咯,但要堅信,方法總是比問題多的。