精华内容
下载资源
问答
  • linux下建立可加载mod的minecraft服务器

    万次阅读 2017-06-08 09:55:11
    如何在linux建立一个可以加载mod的minecraft服务器。本教程为入门教程。

    前言

    在上一篇文章中,我们介绍了如何在本地使用minecraft。但是,如果小伙伴想要一起玩同一个地图,就需要一个minecraft服务器。最简单的方法就是在单机游戏的情况下对局域网开放,这种方法是一种临时提供大家玩耍的途径;另一种比较复杂的方法就是需要有一台闲置的电脑,在上面运行minecraft服务器版本。接下来我会介绍这两种方法,重点在第二种方法上。

    目录

    服务器

    1. 临时服务器

    1.1. 首先进入一个单人游戏
    这里写图片描述


    1.2. 进入游戏后按esc调出菜单,选择对局域网开放。
    这里写图片描述


    这个时候,你可以改变游戏的一些属性,
    这里写图片描述
    比如game mode,可以换成上帝模式或者其他;以及是否允许使用作弊码。调整完游戏属性后,点击开始。这个时候你的游戏就作为一个临时的服务器面向局域网开放。游戏会为你分配一个端口号,并在屏幕上显示,在这个例子里是38413。

    这里写图片描述


    1.3. 其他人加入

    • 首先,你需要知道你自己的局域网ip,一般在网络设置里。网上教程有很多,比如: windows linux
      假设你的地址是192.0.0.102
    • 其他人打开minecraft选中多人游戏
      这里写图片描述
    • 选择直接连接,然后让小伙伴在地址栏填入你的ip地址和端口号,中间用冒号:连接
      本例中,填入192.0.0.102:38413。点击加入 大家就可以一起玩耍了。
      这里要注意一下,minecraft是用人名来区分玩家,所以大家不要取一个名字。名字的取法在上一篇文章有讲。
      这里写图片描述
      这里写图片描述

    这样建立服务器有明显的优缺点
    优点: 方便快捷,易于操作。适用于临时玩一会,或者向朋友分享自己的地图。
    缺点: 建立服务器的人不能下线,如果建立服务器的玩家不想玩了,也必须保持自己是登入状态。这个时候如果想要离开电脑,无法保证自己人物的安全(被怪物袭击)。另外,如果希望局域网之外的小伙伴可以玩的话,这样建立服务器是无法加入的,需要一个公网ip。

    2. 真•服务器

    现在我们就来讲一讲,如果我想让更多的人参与到minecraft里如何建立服务器。

    2.1 首先你需要一台”闲置的电脑”

    如果只有一台闲置电脑放在家里,那么建立的服务器并不具有公网ip,只能供局域网里的小伙伴玩。要想解决这个问题,可以使用花生壳等产品。
    另一种方法,直接租一个服务器,方法有很多。我租用的是阿里云服务器,最便宜的大概是100块钱一个月,也可以按小时租,大概0.7元一小时。

    这里我们统称上面两种电脑称为服务器。服务器的系统windows或者linux都可以。我个人喜欢linux一些,所以选取的阿里云的ubuntu 16.06 64位的系统。下面也以该系统为例介绍建立服务器。

    要在服务器里也安装jre,安装方法同上一篇单机版相同。

    2.2 下载minecraft服务器版本

    据说可以在官网下载,但是我真是没找到地址…
    所以我在azminecraft(点击下载)下载的,这里有两点要注意的:

    1. 服务器版本要尽量和本地游戏版本一致。所以我下载的是1.10.2版本的服务器
    2. 需要下载的文件只有一个
      windows下载后缀为.exe或.jar文件
      linux下载后缀为.jar文件

    我下载的文件名为minecraft_server.1.10.2.jar

    将该文件拷贝到服务器里,假设拷贝到minecraft_server文件夹里。

    2.3 运行服务器

    首先我们先来运行一下服务器程序,产生必要的一些文件。

    $ java -Xms512m -Xmx1024m -jar minecraft_server.1.10.2.jar nogui

    第一次运行,程序会自动退出,提示需要同意协议。本地会多出eula.txt文件

    #By changing the setting below to TRUE you are indicating your agreement to our ULA (https://account.mojang.com/documents/minecraft_eula).
    #Wed Sep 17 16:44:43 CST 2014
    eula=true

    将eula=false改为eula=true保存退出即可。
    第二次运行

    $ java -Xms512m -Xmx1024m -jar minecraft_server.1.10.2.jar nogui

    这个时候程序不会退出,会按照默认设置生成一个世界。用ctrl-C 手动退出。这个时候可以看到本地多了很多文件。

    -rw-rw-r--  1        2 Jun  7 21:36 banned-ips.json
    -rw-rw-r--  1        2 Jun  7 21:36 banned-players.json
    drwxrwxr-x  2     4096 Jun  7 18:39 config/
    -rw-rw-r--  1      180 Jun  7 14:38 eula.txt
    drwxrwxr-x  2     4096 Jun  8 08:03 logs/
    -rw-r--r--  1  9459897 Jun  7 14:30 minecraft_server.1.10.2.jar
    -rw-rw-r--  1      145 Jun  7 21:36 minecraft_service.log
    -rw-rw-r--  1        2 Jun  7 21:36 ops.json
    -rw-rw-r--  1      756 Jun  7 21:36 server.properties
    -rw-rw-r--  1      101 Jun  8 08:11 usercache.json
    -rw-rw-r--  1       50 Jun  7 18:05 usernamecache.json
    -rw-rw-r--  1        2 Jun  7 14:39 whitelist.json
    drwxrwxr-x  8     4096 Jun  8 10:23 world/

    world文件夹中储存的是默认创建的世界。

    server.properties文件是服务器配置文件,里面包含了服务器的设置以及生成世界的配置。
    我们只需将文件中

    online-mode=true

    改为

    online-mode=false

    该配置问价其他选项的说明参考我的世界百科

    第三次运行

    $ java -Xms512m -Xmx1024m -jar minecraft_server.1.10.2.jar nogui

    这个时候最基本服务器建设就结束了。小伙伴们只要在多人游戏里,输入服务器的ip和端口号(ip:端口号,默认的端口号是25565),就可以加入到服务器中。
    这个时候,可以试一试大家能不能加入。

    如果不能加入有一下几个问题:
    1. 服务器的防火墙阻断了minecraft端口,需要添加防火墙规则,允许tcp 25565端口。
    2. java问题,推荐大家全部使用oracle的java,之前我尝试用openjdk的java死活连不上。

    2.4 加载mod

    因为我们希望能够使用forge的mod插件,所以需要安装forge。

    2.4.1 下载forge api

    可以去官网下载,下载universal版本。要注意要和游戏版本对应。这里我下载1.10.2版本。
    文件名为forge-1.10.2-12.18.3.2185-universal.jar
    将该文件拷贝到服务器minecraft_server文件夹下。

    2.4.2 运行forge minecraft

    运行forge

    $ java -Xms512m -Xmx1024m -jar forge-1.10.2-12.18.3.2185-universal.jar nogui

    这个时候会报错误,因为缺少必要的库函数。我们需要把本地客户端里的库函数拷贝到服务器里。
    找到本地.minecraft中libraries文件夹,将该文件夹拷贝到服务器的minecraft_server文件夹下。再次运行forge

    $ java -Xms512m -Xmx1024m -jar forge-1.10.2-12.18.3.2185-universal.jar nogui

    等待一会,可以看到服务器重新启动了之前创建world存档。说明forge加载成功。ctrl-C退出。可以看到本地多了mods文件夹,该文件夹用来存放mod文件。

    2.4.3 加载liteloader

    为使得服务器支持小地图,我们需要加载liteloader插件。
    将本地客户端.minecraft/mods文件夹下的liteloader-1.10.2-release.jar拷贝到服务器下minecraft_server/mods文件夹下。

    2.4.4 加载mod

    对于forge的mod,只需要将mod文件拷贝到服务器的mods文件夹及客户端的mods文件夹就可以了。
    对于liteloader的mod,比如小地图voxelMapmod。不需要将mod文件(mod_voxelMap_1.6.21_for_1.10.2.litemod)拷贝到mods文件夹下,否则会引起错误。

    2.4.4 再运行forge minecraft

    再一次运行,服务器就建立完成了。

    $ java -Xms512m -Xmx1024m -jar forge-1.10.2-12.18.3.2185-universal.jar nogui

    2.5 后台运行及管理脚本

    直接在终端运行服务器,如果退出终端,那么服务器也会随之终端。所以最好能将服务器在后台运行。
    需要使用screen命令,具体的screen命令如何使用请参考网上众多教程。

    最后附上我写的利用screen开关服务器的脚本。很久之前写的,语法有一些不规范的地方,大家多多包含

    文件名: mcserver.sh

    #!/bin/sh
    
    
    
    if [ "$1" == --help ];then
        printf " ==========================================\n"
        printf " -r\t如果存在minecraft_service则重新启动\n"
        printf " -kf\t如果存在minecraft_service则kill掉该进程\n"
        printf " -s\t查看minecra_service的状态\n"
        printf " -f\t将minecraft调至前台\n"
        printf " --help\t帮助\n"
        printf " ------------------------------------------\n"
        exit 0
    fi
    
    declare -a pid_screen
    declare pid
    if [ "$1" == -f ];then
        pid_screen=$(screen -list | grep 'minecraft_service'|cut -d . -f 1)
        printf ${pid_screen}
        if [ -n ${pid_screen} ];then
    
        if [ ${#pid_screen[*]} -eq 1 ];then
            screen  -r minecraft_service
        else
            printf "\t有多个minecraft_service\n"
            screen -list
        fi
        else
            printf "\t后台没有minecraft_service\n"
        exit 0
        fi
        exit 0
    fi
    
    #查询是否已经开启minecraft
    pid=$(ps -ef | grep forge-1.10.2-12 | egrep -v 'grep|screen|tee|SCREEN' | awk '{ printf $2}')
    
    
    if [ -n "$1" ]; then
        if [ "$1" == -r ];then
        if [ -n "$pid"  ];then
            kill $pid
        fi
        #       echo "kill"
    
        elif [ "$1" == -kf ];then
        if [ -n "$pid" ];then
            kill $pid
        fi
    
        pid_screen=$(screen -list | grep 'minecraft_service'|cut -d . -f 1 )
        if [ ${#pid_screen[*]} -eq 1 ];then
            kill $pid_screen
    
            exit 0
        fi
        elif [ "$1" == -ka ];then
        if [ -n "$pid" ];then      
            kill $pid
        fi
            pid_screen=$(screen -list | grep 'minecraft_service'|cut -d . -f 1)
            kill $pid_screen
    
            exit 0
        elif [ "$1" ==  -s ]; then
        if [ -n "$pid" ]; then
            printf "\tminecraft在运行\n"
            ps -ef | grep forge-1.10.2-12 | egrep -v 'grep|screen|tee|SCREEN'
        else
            printf "\tminecraft服务没有运行\n"
        fi
        exit 0
        else
        printf "\t参数不正确\n使用--help可查看参数\n"
    
        exit 0
        fi
    else
        printf "\t参数不正确\n使用--help可查看参数\n"
    
        exit 0
    fi
    
    
    unset pid
    unset pid_screen
    date >> ./minecraft_service.log
    screen  -R minecraft_service java -Xms512m -Xmx1024m -jar forge-1.10.2-12.18.3.2185-universal.jar nogui| tee -a ./minecraft_service.log

    使用方法

    # 调用帮助
    $ bash ./mcserver.sh --help
    # 在screen中打开服务器
    $ bash ./mcserver.sh -r
    # 结束现有开启的服务器
    $ bash ./mcserver.sh -kf
    # 查看服务器运行状态
    $ bash ./mcserver.sh -s
    # 将后台的screen调至前台
    $ bash ./mcserver.sh -f
    展开全文
  • 通过本实验,使学生掌握在Linux系统内核中单独编译、加载和卸载所需的模块的一般方法和过程。
  • 学习创建和使用自定义控件写的试验代码,centos qt5.8可以使用。具体实现过程见我的文章:http://blog.csdn.net/csdn83419527/article/details/78870487 调试过程中出现的问题都有描述。另外控件代码用的lx100991的...
  • linux下opengl加载bmp、png、jpg格式图片

    热门讨论 2011-07-22 17:54:11
    程序功能:通过glx将x11和sdl创建的窗口联系起来(不是sdl-opengl的东西)供opengl渲染显示的小程序,其中bmp的是通过分析bmp文件格式读取位图数据和sdl_image两种方式加载,Png和Jpg文件格式比较复杂,所以直接使用...
  •  Linux下可以创建两种类型的库:  1、静态库(.a): 在链接期间被应用程序直接链接进执行文件  2、动态链接库(.so): 动态库还分为两种用法: a) 应用程序运行期间链接动态库,但是在编译期间声明动态库的存在,...
  • Linux下不能加载动态库问题 当出现下边异常情况 ./test: error while loading shared libraries: libmfs_open.so: cannot open shared object file: No such file or directory 若动态库的路径在(/usr/cluster/....
  • linux内核模块加载命令

    千次阅读 2021-01-04 20:25:48
    lsmod 是列出目前系统中已加载的模块的名称及大小等;另外我们还可以查看 /proc/modules ,我们一样可以知道系统已经加载的模块; [root@localhost beinan]# lsmod 2、modinfo 查看模块信息; modinfo 可以查看模块...

    一,内核相关的命令

    1、lsmod 列出已经加载的内核模块;

    lsmod 是列出目前系统中已加载的模块的名称及大小等;另外我们还可以查看 /proc/modules ,我们一样可以知道系统已经加载的模块;

    [root@localhost beinan]# lsmod
    

    2、modinfo 查看模块信息;

    modinfo 可以查看模块的信息,通过查看模块信息来判定这个模块的用途;

    [root@localhost beinan]# moinfo  模块名   
    

    举例:查看 br_netfilter模块

    [root@ct ~]# modinfo br_netfilter
    filename:       /lib/modules/3.10.0-957.el7.x86_64/kernel/net/bridge/br_netfilter.ko.xz
    description:    Linux ethernet netfilter firewall bridge
    author:         Bart De Schuymer <bdschuym@pandora.be>
    author:         Lennert Buytenhek <buytenh@gnu.org>
    license:        GPL
    retpoline:      Y
    rhelversion:    7.6
    srcversion:     C4DE536495D55C12BA6A8A8
    depends:        bridge
    intree:         Y
    vermagic:       3.10.0-957.el7.x86_64 SMP mod_unload modversions 
    signer:         CentOS Linux kernel signing key
    sig_key:        B7:0D:CF:0D:F2:D9:B7:F2:91:59:24:82:49:FD:6F:E8:7B:78:14:27
    sig_hashalgo:   sha256
    
    

    上面的例子是我们查看 br_netfilter这个模块的信息,通过查看,我们知道 br_netfilter模块是位于

    /lib/modules/3.10.0-957.el7.x86_64/kernel/net/bridge/br_netfilter.ko.xz
    

    我们再查查vfat 和ntfs 的模块信息;

    [root@localhost beinan]# modinfo vfat
    [root@localhost beinan]# modinfo ntfs 
    

    注意: 模块名是不能带有后缀的,我们通过modprobe -l 所看到的模块,都是带有.ko 或.o后缀;

    3、modprobe 挂载新模块以及新模块相依赖的模块

    modprobe 我们常用的功能就是挂载模块,在挂载某个内核模块的同时,这个模块所依赖的模块也被同时挂载;当然modprobe 也有列出内核所有模块,还有移除模块的功能;下在我们举个例子说一说咱们常用的功能和参数;

    modprobe [-v] [-V] [-C config-file] [-n] [-i] [-q] [-o <modname>] <modname> [parameters...]modprobe -r [-n] [-i] [-v] <modulename> ...modprobe -l -t <dirname> [ -a <modulename> ...]
    

    上面是modprobe 的用法,具体更为详细的帮助,我们可以查看 man modprobe ;

    [root@localhost beinan]# modprobe -c
    

    modprobe -c 可以查看modules 的配置文件,比如模块的别名是什么等;

     modprobe -l
    

    modprobe -l 是列出内核中所有的模块,包括已挂载和未挂载的;通过modprobe -l ,我们能查看到我们所需要的模块,然后根据我们的需要来挂载;其实modprobe -l 读取的模块列表就位于 /lib/modules/‘uname -r’ 目录中;其中uname -r 是内核的版本;

    [root@localhost beinan]# uname -r2.6.11-1.1369_FC4[root@localhost beinan]# ls /lib/modules/2.6.11-1.1369_FC4/
    
    [root@localhost beinan]# modprobe   模块名   注:挂载一个模块;
    

    举例:

    [root@localhost beinan]# modprobe ne2k-pci  //挂载 ne2k-pci 模块;
    [root@localhost beinan]# modprobe vfat   //挂载vfat 模块
    [root@localhost beinan]# modprobe ntfs    //挂载ntfs 模块
    [root@localhost beinan]# lsmod   //列出已挂载模块, 我们会看到ne2k-pci ,vfat ,ntfs的模块;
    

    注意: 模块名是不能带有后缀的,我们通过modprobe -l 所看到的模块,都是带有.ko 或.o后缀;

    [root@localhost beinan]# modprobe -r  模块名  //移除已加载的模块,和rmmod 功能相同;
    

    注意:模块名是不能带有后缀的,我们通过modprobe -l 所看到的模块,都是带有.ko 或.o后缀;

    [root@localhost beinan]# modprobe -r  模块名 
    

    举例:

    [root@localhost beinan]# modprobe  -r ne2k-pci
    

    就说这么多吧,更为详细的还是用 man modprobe 来查看和尝试;

    4、rmmod 移除已挂载模块;

    rmmod  模块名
    

    注意: 模块名是不能带有后缀的,我们通过modprobe -l 所看到的模块,都是带有.ko 或.o后缀;

    举例:

    [root@localhost beinan]# rmmod  vfat  //移除已挂载的模块vfat 
    

    5、depmod 创建模块依赖关系的列表

    这个模块管理工具是创建模块依赖关系的列表,有几个参数我们注意一下就行了,目前的的Linux 发行版所用的内核是2.6x版本,是自动解决依赖关系,所以这个命令知道就行了;模块之前也有依赖关系,比如我们想驱动USB 移动硬盘,目前有两种驱动,一种是udev ,在内核中有,但目前不太稳定;另一种办法是用usb-storage驱动,而usb-storage 依赖的模块是scsi 模块,所以我们要用usb-storage 的模块,也得把scsi 编译安装;

    再举个例子:sata的硬盘,在 Linux中的设备表示的是/dev/sd* ,比如 /dev/sda,/dev/sdb 等… 系统要驱动 sata硬盘,则需要把sata在内核中选中,或编译成模块,或内置于内核之中,在此同时,还需要在内核中选中ide ,scsi 的支持等;
    depmod 工具的洋文原意:depmod — program to generate modules.dep and map files.(译的:为modules.dep 文件或映射文件创建依赖关系)

    [root@localhost beinan]# depmod  -a    注:为所有列在/etc/modprobe.conf 或/etc/modules.conf  中的所有模块创建依赖关系,并且写入到modules.dep文件;
    [root@localhost beinan]# depmod -e     注:列出已挂载但不可用的模块;
    [root@localhost beinan]# depmod  -n    注:列出所有模块的依赖关系,但仅仅是输出出来 (Write the dependency file on stdout only) modules.dep 位于 /lib/modules/内核版本 目录
    

    比如 Fedora Core 4.0 中,系统默认的内核:

    [root@localhost beinan]# ls /lib/modules/2.6.11-1.1369_FC4/modules.dep/lib/modules/2.6.11-1.1369_FC4/modules.dep
    

    6、insmod 挂载模块;

    insmod 这个工具,和modprobe 有点类似,但功能上没有modprobe 强,modprobe 在挂载模块是不用指定模块文件的路径,也不用带文件的后缀.o 或.ko ;而insmod 需要的是模块的所在目录的绝对路径,并且一定要带有模块文件名后缀的(modulefile.o 或modulesfile.ko );

    对于这个工具,我们只是介绍一下, 并不推荐使用。因为模块有依赖关系,对于新手来说,可能不知道这个模块依赖和哪个模块依赖;

    举例:

    [root@localhost beinan]# insmod /lib/modules/2.6.11-1.1369_FC4/kernel/drivers/net/tg3.ko
    

    我们要到 /lib/modules/内核版本 uname -r 的命令输出/kernel/drivers 中找相对应的模块才行,要有绝对路径,而且必须要用到文件名的全称,不能把文件名的后缀省略;

    二,与内核模块加载相关的配置文件;

    1、模块的配置文件 modules.conf 或 modprobe.conf

    内核模块的开机自动挂载模块一般是位于一个配置文件,一般的Linux发行版本都有 /etc/modules.conf 或 /etc/modprobe.conf 。比如Fedora Core 4.0 内核模块开机自动加载文件是 /etc/modprobe.conf ;在这个文件中,一般是写入模块的加载命令或模块的别名的定义等;比如我们在modules.conf 中可能会发行类似的一行 ;

    alias eth0 8139too 
    

    而8029的网卡应该是

    alias eth0 ne2k-pci 
    

    这样系统启动的时候,首先会modprobe 8139too ,然后再为8139too 指定别名为 eth0,然后我们在登录的时候,用 ifconfig 就会查看到网卡的IP 等情况,当然您得为网卡设置IP 才行;

    一般的情况下,modproe.conf 或modules.conf的内容是我们用相应的硬件配置工具而生成的;如果您的硬件驱动是没有被内核支持,您自己到硬件的厂商下载而来的驱动。一般的情况下都有安装和帮助文件。他们的驱动在配置时,他会写入硬件的支持到modules.conf 或modprobe.conf 文件中。

    再比如我们的声卡在modules.conf 或modprobe.conf 中也有相应的内容,这是由alsaconf 配置工具生成的,明白了吧;同理网卡在modprobe.conf 或modules.conf中的内容也是由网卡的配置工具而来的。

    有些硬件是以内核模块的方式驱动的,模块一旦加载上就能用,也没有什么配置工具,比如vfat 和ntfs 的支持;如果是硬件驱动不以模块的方式支持,而是直接编入内核,也不会用在modprobe.conf 或 modules.conf 中加入什么内容;

    如果您有些模块不能开机加载,您想让一些模块加机自动加载,就可以把modprobe 模块 直接写入配置文件;

    2、内核模块其它配置文件

    内核模块的其它配置文件还是需要了解的,比如 /lib/modules/内核版本目录下的几个文件;了解一下就行;比如:

    [root@localhost beinan]# uname -r2.6.11-1.1369_FC4
    [root@localhost beinan]# ls /lib/modules/2.6.11-1.1369_FC4/build   
    misc  modules.ccwmap  modules.ieee1394map  modules.isapnpmap
    modules.symbols  sourcekernel  modules.alias  modules.dep 
    modules.inputmap  modules.pcimap   modules.usbmap
    

    三,、硬件驱动在系统中的目录;

    硬件驱动是必须由内核支持的,无论是我们自己安装驱动,还是内核自带的驱动都是如此。硬件驱动如果是以内核模块支持的,驱动目录位于: /lib/modules/内核版本/kernel/目录 或 /lib/modules/内核版本/kernel/drivers 目录中;

    [root@localhost beinan]# uname -r2.6.11-1.1369_FC4
    [root@localhost beinan]# ls /lib/modules/2.6.11-1.1369_FC4/
    kernelarch  crypto  drivers  fs  lib  net  sound
    

    注:只有驱动在内核中以模块的方法支持,驱动才位于 /lib/modules/相应的目录;如果是直接置入内核的,不会出现在/lib/modules驱动相关的目录;

    四、自己编译驱动的办法;

    通过源码编译驱动一般是./configure ;make;make install ,有时程序不提供./configure ,我们可以make或make install ,或者执行make;make install ;如果不能make install ,则需要我们自己复制.o或者.ko文件到 /lib/modules/内核版本/kernel/目录 或 /lib/modules/内核版本/kernel/drivers 目录中相应的驱动目录;

    这个还是自己尝试吧,说也说不清楚,遇到问题后就知道怎么弄了;具体的还是驱动的REAME和INSTALL为准;

    现在大多驱动都是在编译安装时,都自动复制.o或.ko 文件到内核模块目录,大多不用我们自己动手复制过去。如果您尝试编译安装声卡驱动 alsa-drivers 就会明白以上意思;

    展开全文
  • 最近在Linux 环境开发,搞了好几天 Compiler 和 linker,觉得有必要来写一篇关于Linux环境 ld.so的文章了,google上搜索了很多相关介绍性的文档,发现国内百度上却很少有相关类文档,觉得有必要来梳理一下: ...

    (转自:https://blog.csdn.net/elfprincexu/article/details/51701242

    最近在Linux 环境下开发,搞了好几天 Compiler 和 linker,觉得有必要来写一篇关于Linux环境下 ld.so的文章了,google上搜索了很多相关介绍性的文档,发现国内百度上却很少有相关类文档,觉得有必要来梳理一下:

     

     

    ld-linux.so.2 是linux下的动态库加载器/链接器,这篇文章主要来讲一下 ld-linux.so.2 是如何和Linux 以及相关应用打交道的。

     

    1. 什么是 ld.linux.so ? 

    很多现代应用都是通过动态编译链接的,当一个 需要动态链接 的应用被操作系统加载时,系统必须要 定位 然后 加载它所需要的所有动态库文件。 在Linux环境下,这项工作是由ld-linux.so.2来负责完成的,我们可以通过 ldd 命令来查看一个 应用需要哪些依赖的动态库:

     

    $ ldd `which ls`
          linux-gate.so.1 =>  (0xb7fff000)
          librt.so.1 => /lib/librt.so.1 (0x00b98000)
          libacl.so.1 => /lib/libacl.so.1 (0x00769000)
          libselinux.so.1 => /lib/libselinux.so.1 (0x00642000)
          libc.so.6 => /lib/libc.so.6 (0x007b2000)
          libpthread.so.0 => /lib/libpthread.so.0 (0x00920000)
          /lib/ld-linux.so.2 (0x00795000)
          libattr.so.1 => /lib/libattr.so.1 (0x00762000)
          libdl.so.2 => /lib/libdl.so.2 (0x0091a000)
          libsepol.so.1 => /lib/libsepol.so.1 (0x0065b000)

     

     

    当最常见的ls小程序加载时,操作系统会将 控制权 交给 ld-linux.so 而不是 交给程序正常的进入地址。 ld-linux.so.2 会寻找然后加载所有需要的库文件,然后再将控制权交给应用的起始入口。

    上面的ls在启动时,就需要ld-linux.so加载器将所有的动态库加载后然后再将控制权移交给ls程序的入口。

     

    ld-linux.so.2 man page给我们更高一层的全局介绍, 它是在 链接器(通常是ld)在运行状态下的部件,用来定位和加载动态库到应用的运行地址(或者是运行内存)当中去。通常,动态链接是 在连接阶段当中 隐式指定的。 gcc -W1 options -L/path/included -lxxx 会将 options 传递到ld 然后指定相应的动态库加载。 ELF 文件提供了相应的加载信息, GCC包含了一个特殊的 ELF 头: INTERP, 这个 INTERP指定了 加载器的路径,我们可以用readelf 来查看相应的程序

     

     

    $ readelf -l a.out
    
    Elf file type is EXEC (Executable file)
    Entry point 0x8048310
    There are 9 program headers, starting at offset 52
    
    Program Headers:
      Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
      PHDR           0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4
      INTERP         0x000154 0x08048154 0x08048154 0x00013 0x00013 R   0x1
          [Requesting program interpreter: /lib/ld-linux.so.2]
      LOAD           0x000000 0x08048000 0x08048000 0x004cc 0x004cc R E 0x1000
      LOAD           0x000f0c 0x08049f0c 0x08049f0c 0x0010c 0x00110 RW  0x1000
    . . .

     

     

    ELF 规格要求,假如 PT_INTERP 存在的话,操作系统必须创建这个 interpreter文件的运行映射,而不是这个程序本身, 控制权会交给这个interpreter,用来定位和加载所有的动态库。

    展开全文
  • 该结构体如下:当我们执行一个执行程序的时候, 内核会list_for_each_entry遍历所有注册的linux_binfmt对象, 对其调用load_binrary方法来尝试加载, 直到加载成功为止。上面代码可以看倒,ELF中加载程序...

    linux内核启动时将ELF格式注册到内核可支持的文件格式链表中,也就是通过register_binfmt 函数将定义的elf_format结构体添加到链表中。该结构体如下:

    当我们执行一个可执行程序的时候, 内核会list_for_each_entry遍历所有注册的linux_binfmt对象, 对其调用load_binrary方法来尝试加载, 直到加载成功为止。上面代码可以看倒,ELF中加载程序即为load_elf_binary,内核中已经注册的可运行文件结构linux_binfmt会让其所属的加载程序load_binary逐一前来认领需要运行的程序binary,如果某个格式的处理程序发现相符后,便执行该格式映像的装入和启动。

    接下来,我们具体分析load_elf_binary函数。

    第一步,填充并且检查目标程序ELF头部。

    首先是填充映像的文件头,使用了内核之前对bprm->buf填充的128个字节信息。然后比较了文件头的前4个字节,查看是否是标准的ELF文件魔数(”\177ELF”),然后还需要确认该文件是可执行文件还是动态链接库文件,也就是代码中的ET_EXEC和ET_DYN

    第二步,通过load_elf_phdrs加载目标程序的程序头表。

    该函数有两个参数,elf_ex表示需要程序头表需要被加载的二进制映像的ELF头部;elf_file表示这个打开的ELF二进制映像文件。

    函数首先检查该文件是否包含至少一个段,且所有段的大小之和是否超过64k。如果符合条件,调用kernel_read读入程序头表。

    第三步,处理解释器段。

    通过遍历每个段,找到PT_INTERP类型的段,也即解释器段,找到就说明运行过程中需要动态链接。同样也是通过kernel_read函数将解释器段的内容读入缓冲区。readelf命令可以查看到程序的解释器段其实就是一个字符串,也就是解释器的文件名,比如“/lib/ld-linux.so.2”。再调用open_exec()函数根据这个文件名打开解释器文件,和前面一样,再读入128个字节,也就是解释器映像的头部。

    第四步,检查并读取解释器的程序头表。

    可以看到加载解释器,其实原理和前面加载ELF可执行程序一样,也是线检查解释器头部信息,然后通过load_elf_phdrs加载解释器的程序头表。

    完成了解释器初始化工作,并加载了目标执行执行的程序头表后,开始加载程序的段信息。

    第六步,装入可执行文件的PT_LOAD段。

    先遍历每个段,找到类型为PT_LOAD的段,检查地址和页面的信息,确定装入地址后,通过elf_map()建立用户空间虚拟地址与目标映像文件中某个连续区间的映射,返回值就是实际映射的起始地址。

    第七步,填入程序的入口地址

    前面的步骤已经完成了目标映像和解释器的加载,并且将目标程序的各个段家在近内存,但是,一个程序成功执行,操作系统还需要知道程序的入口地址,才能开始执行加载好的映像。

    如果需要动态链接,就通过load_elf_interp装入解释器映像, 并把将来进入用户空间的入口地址设置成load_elf_interp()的返回值,即解释器映像的入口地址。

    而若不需要装入解释器,那么这个入口地址就是目标映像本身的入口地址。

    第八步,填写目标文件的参数环境变量等必要信息

    通过create_elf_tables,为目标映像和解释器准备一些有关的信息,包括argc、envc等,这些信息需要复制到用户空间,使它们在CPU进入解释器或目标映像的程序入口时出现在用户空间堆栈上。

    最后一步,通过start_thread准备进入新的程序入口。

    参考: https://blog.csdn.net/gatieme/article/details/51628257
    展开全文
  • 在使用Linux的过程中设置一个开机或登录的时候自动加载的环境变量是一个非常实用的技能,比如我有重要的数据存放在~/pyzahui/simulators/FlowRadar/data目录,所以我每天登录都需要切换到这个目录下去处理其中的...
  • Linux环境下加载Spring的问题

    千次阅读 2017-04-12 11:25:44
    Linus/Unix环境使用使用加载Spring配置文件失败。
  • linux设备和驱动加载的先后顺序

    千次阅读 2019-06-13 22:50:00
    Linux驱动先注册总线,总线上可以先挂device,也可以先挂driver,那么究竟怎么控制先后的顺序呢。 ...静态加载:将所有模块的程序编译到Linux内核中,由do_initcall函数加载 核心进程(/init/ma...
  • linux驱动模块的加载和卸载

    千次阅读 2020-01-09 12:04:03
    第二种就是将驱动编译成模块(Linux 模块扩展名为.ko),在Linux 内核启动以后使用“insmod”命令加载驱动模块。在调试驱动的时候一般都选择将其编译为模块,这样我们修改驱动以后只需要编译一下驱动代码即可,不...
  • SysLinux是一个Linux系统引导工具,它可以创建从MS DOS启动的Linux启动盘或Linux恢复盘。它安装很简单,一旦安装创建好之后,SysLinux软盘就可以操控标准的MS DOS工具。它占用的空间也很小,只需要7k的MS DOS空间或...
  • 今天有朋友问我linux系统Pci字符驱动加载流程,简单整理了一下,顺便做个记录。 首先说需要包含的头文件: 一个完整的字符驱动一般包含下面这些头文件: #include &amp;amp;lt;linux/types.h&amp;amp;...
  • linux elf加载过程

    千次阅读 2017-12-03 21:50:44
    通过前面linux 进程的创建加载我们知道,调用ececve()系统调用后会加载指定的执行程序并且运行起来,接下来我们分析这个加载过程,跑到do_execve()函数中。 linux-4.10/fs/exec.c int do_execve(struct ...
  • 假设要加载的驱动程序模块名为SHT21.ko ...将SHT21.ko文件拷贝到/lib/module/#uname -r#/目录,这里,#uname -r#意思是,在终端中输入 uname -r后显示的内核版本及名称,例如mini2440中#unam...
  • 本文以SNX串口卡在Centos7环境下加载驱动过程为例,分析串口的名称是如何确定的。 下面的终端显示为调用了modprobe snx后的输出,可以看到在第二步,内核发出消息到用户空间已经把串口名称确定了。 进入驱动代码...
  • 1. 第一个模块 ========================...要注意,linux内核源码的路径中,可以包含中文,但一定不能有空格; Makefile的例子: #KERNEL := /usr/src/linux-headers-`uname -r`/ KERNEL := /home/zht/class-e68
  • Linux内核模块自动加载机制

    千次阅读 2015-12-11 00:17:49
    然后在/etc/rcN.d/目录下创建一个符号链接,这个链接的名字以S开头,这内核启动时,就会自动运行这个脚本了,这样就可以在脚本中使用modprobe来实现自动加载。但是我们发现,内核中加载了许多硬件设备的驱动,而搜
  • 文中是linux下 C++动态库 实现接口提供类导出的一个例子 注意其中使用函数返回基类指针的用法,因为Linux的动态链接库不能像MFC中那样直接导出类 一、介绍 如何使用dlopen API动态地加载C++函数和类,是Unix C++...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 346,698
精华内容 138,679
关键字:

linux下建立可加载的

linux 订阅