.html
.node
.linux
.shell
.vim
今天把 Ubuntu 14.04 升級到了最新的 4.0.5 的內核版本,原本不打算記錄下來的,可是升級的過程當中確實遇到了一些問題,因此仍是記錄下來,分享給遇到一樣問題的猿友。網絡
先去官網下載最新的內核壓縮包:https://www.kernel.org/函數
網速不給力,只能用虛擬機裏的迅雷下載,而後再拷貝出來。es5
LZ 把源碼包拷貝到 /usr/src 下面,直接就在這裏編譯安裝了:spa
# 切換到 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
參考: