天天看點

Ubuntu 編譯安裝 Linux 4.0.5 核心,并修複 vmware 網絡核心子產品編譯錯誤

.

.

.

.

.

今天把 Ubuntu 14.04 更新到了最新的 4.0.5 的核心版本,本來不打算記錄下來的,但是更新的過程中确實遇到了一些問題,是以還是記錄下來,分享給遇到同樣問題的猿友。

先去官網下載下傳最新的核心壓縮包:https://www.kernel.org/

網速不給力,隻能用虛拟機裡的迅雷下載下傳,然後再拷貝出來。

LZ 把源碼包拷貝到 /usr/src 下面,直接就在這裡編譯安裝了:

# 切換到 root 身份
>$ su
# 解壓縮源碼,得到檔案夾 /usr/src/linux-4.0.5
># tar xvf linux-4.0.5.tar.xz
># cd linux-4.0.5
# make mrproper 指令用來清理以前編譯時留下的臨時檔案,
# 因為 LZ 是解壓縮的新包,是以不需要這步
># make mrproper
# 把目前正在使用的核心編譯配置檔案拷過來作為模闆
># cp /boot/config-`uname -r` .config
# 啟動基于ncurse庫繪制的圖形配置界面,已經按照目前正在使用的核心的配置選好相關選項了,再啟用一些新特性即可
# 如果出現如下錯誤,那麼可能是沒有安裝 ncurse 庫,執行 apt-get install libncurses5-dev 指令安裝。
# In file included from scripts/kconfig/mconf.c:23:0:
# scripts/kconfig/lxdialog/dialog.h:38:20: fatal error: curses.h: No such file or directory
# #include CURSES_LOC
># make menuconfig
# 正常是要執行下面這三條指令的,但是 Ubuntu 上不用這麼麻煩
># make install
># make modules
># make modules_install
# Ubuntu 上用包管理器可以把核心和相關子產品編譯成 deb 包,熟悉 Ubuntu 的童鞋這下覺得好辦多了吧?
# 如果提示沒有 make-kpkg 指令的話,可以先用 apt-get 安裝
># apt-get install kernel-package
># make-kpkg clean
# 與 make 指令一樣,j8 參數可以指定 8 個線程同時編譯
#> make-kpkg --initrd kernel-image kernel-headers -j8
# 坐等編譯完成吧,會在上一級目錄中生成兩個 deb 包,接下來安裝它們:
># dpkg -i linux-image-4.0.5_4.0.5-10.00.Custom_amd64.deb
># dpkg -i linux-headers-4.0.5_4.0.5-10.00.Custom_amd64.deb
# grub 貌似不用更新也可以,安裝 deb 的時候會自動更新
># update-grub
# 重新開機系統,進入新的核心吧
># reboot      

編譯、安裝、重新開機都很順利,但是發現在新核心中啟動 vmware 的時候提示必須更新核心子產品,可是在編譯網絡子產品的時候死活過不去,LZ 猜測可能是由于核心中某些 API 被修改了,而 vmware 的驅動源碼跟最新的核心中的 API 不比對了,是以才報了一些文法錯誤,沒辦法,隻能手工修改了。

在 shell 中啟動 vmware,讓它自己編譯安裝子產品,編譯失敗之後會在 shell 中留下編譯失敗的錯誤提示,沿着提示修改代碼。

>$ vmware
/tmp/modconfig-WpjYEn/vmnet-only/userif.c: In function ‘VNetCopyDatagram’:
/tmp/modconfig-WpjYEn/vmnet-only/userif.c:526:4: error: implicit declaration of function ‘skb_copy_datagram_iovec’ [-Werror=implicit-function-declaration]
    return skb_copy_datagram_iovec(skb, 0, &iov, len);
    ^
/tmp/modconfig-WpjYEn/vmnet-only/driver.c: In function ‘VNetFileOpUnlockedIoctl’:
/tmp/modconfig-WpjYEn/vmnet-only/driver.c:1194:20: error: ‘struct file’ has no member named ‘f_dentry’
    if (filp && filp->f_dentry) {
                    ^
/tmp/modconfig-WpjYEn/vmnet-only/driver.c:1195:19: error: ‘struct file’ has no member named ‘f_dentry’
       inode = filp->f_dentry->d_inode;
... 此處省略一千行      

錯誤很明顯,是 userif.c 的 526 行和  driver.c 的 1194 行、1195 行出現了問題。

可是報出來的檔案路徑卻怎麼也找不到,而且每次編譯,這個報錯的路徑都在變,應該是編譯時現解壓縮出來的,而編譯後自動删除了,是以需要找到這兩個源檔案的壓縮包在哪才行。

經過一番 Google 之後終于找到了源碼包所在的位置,接下來就可以修改了。

# 切換到 root 身份
>$ su
# 進入源碼目錄
># cd /usr/lib/vmware/modules/source/
# 解開網絡相關的源碼包,注意隻是 tar 包,不是壓縮包,是以解包不要加 -z 參數
># tar xvf vmnet.tar
# 解包後得到 vmnet-only/ 檔案夾,進入
># cd vmnet-only/
# 一個一個的收拾
># vim userif.c +526
// 直接把這句替換成下面的一段 return skb_copy_datagram_iovec(skb, 0, &iov, len);
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)                                                                                                             
   return skb_copy_datagram_iovec(skb, 0, &iov, len);
#else
   struct iov_iter to;
   iov_iter_init(&to, READ, &iov, 1, len);
   return skb_copy_datagram_iter(skb, 0, &to, len);
#endif

># vim driver.c +1194

// 直接把原來的代碼注釋掉,使用 file_inode() 函數擷取 inode
#if 0                                                                                                                                                         
   if (filp && filp->f_dentry) {
      inode = filp->f_dentry->d_inode;
   }
#endif
   inode = file_inode(filp);


# 備份源碼包
># mv vmnet.tar vmnet_bak.tar
# 重新打包
>#tar cf vmnet.tar vmnet-only
# 再運作一次 vmware,發現編譯順利通過了,哦耶
>$ vmware
# 清理
># rm -rf vmnet-only/ vmnet_bak.tar
># exit
>$      

這個問題就這樣解決了。。

第一次發現,原來 Ubuntu 安裝核心居然可以把核心打包成 deb 的形式。。

新核心先繼續體驗着,等感覺穩定了再解除安裝原核心。

其實解除安裝也很簡單:

# 先檢視安裝了哪些核心
>$ sudo dpkg --get-selections | grep linux 
# 檢視目前正在使用的核心,别把正在使用的核心給解除安裝了
>$ uname -r
# 解除安裝舊的核心
>$ sudo apt-get purge linux-image-3.13.0-24-generic 
# 看看舊的核心是不是已經消失了
>$ sudo dpkg --get-selections | grep linux 
# 更新 grub 菜單
>$ sudo update-grub      

參考:

Ubuntu編譯核心

VMware – Backward-Compatible 3.19 Fix..

Linux host - Kernel 3.19 breaks VMware (vmnet)

繼續閱讀