mips-linux-gcc交叉編譯,kubernetes中pause二進位制資訊
一、編譯說明
剛接觸Kubernetes,便知道叢集搭建需要下載一個gcr.io/google_containers/pause-amd64:3.0
映象,然後每次啟動一個容器,都會伴隨一個pause容器的啟動,pause是每個pod需要的根映象。
遇到這種情況我們都是通過有docker hub或者阿里雲下載相關的pause映象,然後通過tag修改景象名稱,這裡我們就操作一下如何手動去編譯pause二進位制和製作pause映象。
二、編譯環境準備
pause
原始碼在kubernetes專案的kubernetes/build/pause/
中,我們可以在github上進行下載,
git clone -b v1.10.3 https://github.com/kubernetes/kubernetes.git ll kubernetes/build/pause <<'COMMENT' Dockerfile Makefile orphan.c pause.c COMMENT 包含了四個檔案: orphan.c是個測試檔案可以不用管; Makefile用於製作pause映象,製作映象的模板便是Dockerfile,非常重要; pause.c是原始碼檔案。
pause是C語言編寫,我們可以看一下原始碼資訊:
#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #define STRINGIFY(x) #x #define VERSION_STRING(x) STRINGIFY(x) #ifndef VERSION #define VERSION HEAD #endif static void sigdown(int signo) { psignal(signo, "Shutting down, got signal"); exit(0); } static void sigreap(int signo) { while (waitpid(-1, NULL, WNOHANG) > 0) ; } int main(int argc, char **argv) { int i; for (i = 1; i < argc; ++i) { if (!strcasecmp(argv[i], "-v")) { printf("pause.c %s\n", VERSION_STRING(VERSION)); return 0; } } if (getpid() != 1) /* Not an error because pause sees use outside of infra containers. */ fprintf(stderr, "Warning: pause should be the first process\n"); if (sigaction(SIGINT, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0) return 1; if (sigaction(SIGTERM, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0) return 2; if (sigaction(SIGCHLD, &(struct sigaction){.sa_handler = sigreap, .sa_flags = SA_NOCLDSTOP}, NULL) < 0) return 3; for (;;) pause(); fprintf(stderr, "Error: infinite loop terminated\n"); return 42; }
那麼需要編譯就需要系統上安裝了可以編譯c語言的gcc工具。
安裝gcc工具的教程一大推,大家網上百度一下,這裡講一下如果進行跨平臺交叉編譯。我們正常使用的linux都是centos系列,使用的amd64(64位)/amd i386(32位)架構,所以安裝相關的工具特別順暢,但是遇到arm甚至更加變態的mips、mipsel架構,在mips上安裝gcc裝不上去,就無法進行編譯,這時候我們就需要通過交叉編譯。這裡以mips為例。
我們這裡使用的mips交叉編譯的工具叫mips-linux-gcc。
網上有好多的都是arm-linux-gcc工具的教程,唯獨MIPS這一塊資料特別少,還有一部分通過buildroot工具進行編譯,而且是基於ubuntu的,關於這個工具有時間可以取研究,建議使用這種方式。
下面介紹我本次安裝交叉編譯工具鏈的過程。
/pub/linux/mips/people/macro/RPMS/ 的索引 [上級目錄] 名稱 大小 修改日期 i386/ 2013/5/5 上午8:00:00 mips/ 2012/9/2 上午8:00:00 mips64/ 2013/5/5 上午8:00:00 mips64el/ 2012/9/2 上午8:00:00 mipsel/ 2012/9/2 上午8:00:00 noarch/ 2012/12/26 上午8:00:00 vax/ 2013/5/5 上午8:00:00
這裡有兩點需要注意:
第一:本人的系統是amd64的系統而不是i386,但是本人沒有找到相關64位的包,暫且使用i386的包,至於相容問題,我在下面的著重講解。
第二:是我們下載檔案的版本,必須版本一致,或者向上進行相容。
首先我們的PC機是i386架構的,所以就進i386的目錄下,可以看到很多mips這裡有許多mips打頭的rpm包,這些就是我們需要的工具鏈!
這時我們可以根據你所使用的mips處理器是大端或小端來下載所需的工具,大端的工具都是以mips開頭的,而小端都是以mipsel開頭,可以通過uname -r指令檢視:
[[email protected] pause]# uname -r 3.10.0-862.ns7_4.016.mips64el 注意點: mips:大端32位 mips64:大端64位 mipsel:小端32位 mips64el:小端64位 本人的就屬於小端64位。
最後我們需要下載的是這幾個包:
mips64el-linux-binutils-x.xx.x-x.i386.rpm
mips64el-linux-gcc-x.xx.x-x.i386.rpm
mips64el-linux-gcc-c-x.xx.x-x.i386.rpm
mips64el-linux-gcc-cpp-x.xx.x-x.i386.rpm
mips64el-linux-sim-x.xx.x-x.i386.rpm
各個rpm包的版本儘量保持一致,由於mips64el-linux-gcc-c-x.xx.x-x.i386.rpm是主要的安裝包,其他包的版本資訊儘量小於等於它。本人安裝時使用的版本如下:
mips64el-linux-binutils-2.16.1-1.i386.rpm mips64el-linux-gcc-4.0.1-1.i386.rpm mips64el-linux-gcc-c-4.0.1-1.i386.rpm mips64el-linux-gcc-cpp-4.0.1-1.i386.rpm mips64el-linux-sim-6.8-2.i386.rpm
安裝rpm包,rpm -ivh mips64el-linux*.rpm
,會發現以下問題:
ld-linux.so.2 被 mips64el-linux-binutils-2.16.1-1.i386 需要 libc.so.6 被 mips64el-linux-binutils-2.16.1-1.i386 需要 libc.so.6(GLIBC_2.0) 被 mips64el-linux-binutils-2.16.1-1.i386 需要 libc.so.6(GLIBC_2.1) 被 mips64el-linux-binutils-2.16.1-1.i386 需要 libc.so.6(GLIBC_2.1.3) 被 mips64el-linux-binutils-2.16.1-1.i386 需要 libc.so.6(GLIBC_2.2) 被 mips64el-linux-binutils-2.16.1-1.i386 需要 libc.so.6(GLIBC_2.2.3) 被 mips64el-linux-binutils-2.16.1-1.i386 需要 ...... 等等一大推,這個問題就是我上面說到的第一個注意點,由於本人使用amd64位的,但是使用的包是amdi386的,所以需要安裝相容包。 安裝指令:yum install glibc.i686 安裝完成重複上面操作即可完成安裝。
驗證安裝是否成功:
[[email protected] mips]# mips64el-linux-gcc -v 使用內建 specs。 目標:mips64el-linux 配置為:../configure --prefix=/usr --mandir=/man --with-local-prefix=/mips64el-linux/local --enable-libc --disable-multilib --enable-shared --enable-static --with-system-zlib --enable-threads --cache-file=config.cache --build=i386-linux --host=i386-linux --target=mips64el-linux 執行緒模型:posix gcc version 4.0.1 看到最後的版本資訊代表安裝成功。
這幾個工具裝好之後,我們就可以寫個helloworld測試一下了:
#include <stdio.h> void main() { printf("Hello World!\n"); }
然後執行:
mips64el-linux-gcc hello.c -o hello
編譯失敗了。提示說找不到stdio.h,這是因為我們PC上並沒有對應mips的動態連結庫,所以我們編譯的時候還需要加上靜態選型
mips64el-linux-gcc -g hello.c -o hello -static
但是執行還是報錯。
解決辦法:我們還需下載一個靜態庫檔案的包,有了這個包,我們的靜態編譯才能通過。
mips-linux-glibc-devel-x.x.xx.noarch.rpm
mips-linux-glibc-static-x.x.xx.noarch.rpm
本人使用版本:
mips64el-linux-glibc-devel-2.4-13.noarch.rpm mips64el-linux-glibc-static-2.4-13.noarch.rpm
最後我們就可以編譯pause.c的原始碼了。
在原始碼包下面使用指令: mips64el-linux-gcc -o pause pause.c 可得到pause檔案 然後執行file pause,如果得到下面資訊: pause: ELF 64-bit LSB executable, MIPS, MIPS-III version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.4.0, not stripped 沒有其他多餘資訊,比如with unknown capability 0x756e670000000f41 = 0x104000000070100,等等,代表編譯成功。
編譯就完成!!!!