.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
参考: