zoukankan      html  css  js  c++  java
  • 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)

  • 相关阅读:
    VC++6.0 自定义按钮,无标题对话框的拖动方法
    完整的使用线程池的多线程C/S Socket类
    树形控件Tree Control
    关闭数据执行保护
    VC++开发垃圾文件清理软件(下)
    用完成端口开发大响应规模的Winsock应用程序
    去掉右键多余显卡菜单
    自动登陆系统
    查询数据库中所有表名和表中所有字段名
    单行编辑框文本垂直居中(包含计算字体高度)
  • 原文地址:https://www.cnblogs.com/0xcafebabe/p/4575877.html
Copyright © 2011-2022 走看看