1. 程式人生 > >mips-linux-gcc交叉編譯,kubernetes中pause二進位制資訊

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,等等,代表編譯成功。

編譯就完成!!!!