zoukankan      html  css  js  c++  java
  • Solaris下开发64位程序的注意事项

    Solaris下开发64位程序的注意事项

    引用自:http://blog.csdn.net/icefireelf/article/details/5688529

    1. ABI(Application Binary Interface):在Intel或AMD体系结构下,32位Solaris程序基于i386 ABI,64位程序基于AMD64 ABI;在SPARC体系结构下,32位程序是基于SPARC V8 ABI,64位的程序基于SPARC V9 ABI。可以用以下命令查看当前Solaris平台支持特性:
    uname –a   查看操作系统版本
    isainfo –v    查看操作系统支持的ABI
    isainfo –b    查看操作系统内核的位数
    isainfo –x    查看操作系统支持的指令集
    至于在源代码中如何区分平台,可以通过包含,然后检查以下宏定义:

    宏定义 说明
    __x86 所有x86的处理器架构都会定义此宏,包括386, 486, Pentium, IA-32, AMD64, EM64T。
    __i386 输出程序采用32-bit的i386 ABI时会定义此宏,它不能与__amd64同时定义。
    __amd64 输出程序采用64-bit的AMD64 ABI时会定义此宏,它不能与__i386同时定义。
    __sparc 所有SPARC V7, SPARC V8 与 SPARC V9平台都会定义此宏。
    __sparcv8 输出程序采用32-bit的SPARC V8 ABI时会定义此宏,它不能与__sparcv9同时定义。
    __sparcv9 输出程序采用64-bit的SPARC V9 ABI时会定义此宏,它不能与__sparcv8同时定义。

    另外,Indel与AMD平台会定义_LITTLE_ENDIAN,SPARC平台会定义_BIG_ENDIAN

    2. 数据模型:与其他UNIX及Linux一样,32位Solaris使用ILP32,64位Solaris使用LP64模型(基本数据类型中只有指针类型与long类型变为了64位),使用gcc在编译时会分别定义 _ILP32 _LP64(不 需要包含任何头文件)。关于几种数据模型的差别可以查看相关资料,在此不做过多讨论,唯一值得注意的是:由于Win64采用LLP64模型(指针为64 位,但long类型仍然为32位),因此如果要编写跨平台的应用程序,必须小心处理long型变量在两种数据模型中的长度差异。具体类型定义可以用下面的 命令进行查询:
    man 3 types
    建议包含,该头 文件里定义了int8_t,uint8_t,…,int64_t及uint64_t等跨平台的类型,且定义了 INT8_MIN,UINT8_MIN,…,UINT64_MAX等极值。另外,在LP64模型中,因为指针都是64位,所以在一些需要将指针转化为整数 值进行计算的算法中,如果直接将指针强转为int或long会面临兼容性问题,这种情况下建议将指针转换为 intptr_t 或 uintptr_t,它们是在任何平台下都保证能存下指针的数值类型。

    3.字符常量:在使用64位编程时尤其要注意使用l,ul,ll,ull或INT8_C(c), ...,INT64_C(c), UINT8_C(c,...,UINT64_C(c)来声明const literal,否则将一个无符号数赋给64位变量时极易出错,例如:
    unsigned long  i = –1U;    //在LP64中,i被赋值为0xFFFFFFFF,而非0xFFFFFFFFFFFFFFFF
    但 unsigned long i = –1; 在LP64中,i被赋值为0xFFFFFFFFFFFFFFFF,-1为int32,先提升至int64(这时会扩展符号位),再转为uint64,因此将全为F。

    4.默认编译参数:为了与现有的大量32位程序保持兼容,如果不附加额外的参数,gcc编译器默认以32位的ABI编译代码,生成的ELF32格式的二进制文件(即使在64位的Solaris),例如:
    gcc  test.c
    如 果在Intel 或 AMD平台下,上面的命令将以i386 ABI生成二进制文件;如果在SPARC平台下,将以SPARC V8 ABI生成二进制文件。注意:虽然gcc可以在64位环境中交叉编译32位的程序,但不能在Intel或AMD平台中生成SPARC ABI的对象,反之亦然。
    如果要生成ELF64的对象,需要添加-xarch=generic64-m64的编译参数,如:
    gcc –m64 test.c
    注意:用32位的编译器也能生成64位的程序,但是不能在32位系统中运行;另外,并非所有32位程序都能在64位平台上编译通过,或者即使编译过也不一定与原来32位平台下的特性一致,例如使用了/proc接口的一些库与程序。

    5.链接搜索目录:链接中间文件与静态库时,所有文件的ELF(Executable and Linking Format)必须一致,如果最终生成的是32位程序,则要求所有中间文件与静态库都是ELF32格式;如果最终生成的是64位程序,则要求所有中间文件 与静态库都是ELF64格式;如果出现混合,编译器会报错。如果程序还链接了动态库,则要求程序执行时能搜索到对应格式的动态库,否则执行时会出错。编译 器与执行时的搜索目录是通过LD_LIBRARY_PATHLD_LIBRARY_PATH_64两个环境变量来控制。其中LD_LIBRARY_PATH_64只对64位程序有效,如果没有设定此环境变量,再使用LD_LIBRARY_PATH,这时很可能与32位的库混淆,具体32位库与64位库的位置可以参看系统文档与配置。

    6. 64位下的调试:一般64位机器上既装了32位的gdb(gdb32),也安装了64位的gdb(gdb64),64位的程序只能用gdb64进行调试,因此在调试时注意gdb的版本。

    7. 执行文件分发:假如我们现在又一个叫myapp的工程,编译了i386,amd64,sparc_v7,sparc_v9等多个版本,为了方便一次性分发,使其在不同平台下执行不同的程序,我们最好将各个版本的执行文件分别放置在几个子目录中,如:
    ./amd64/myapp
    ./i386/myapp
    ./sparcv9/myapp
    ./sparcv7/myapp
    然后在基目录编写下面的脚本,在下面的脚本执行时会使用isalist获取平台支持的特性,遍历各个子目录,执行第一个被找到的程序:

    #! /bin/sh
    CMD=‘basename $0‘
    DIR=‘dirname $0‘
    EXEC=
    for isa in ‘/usr/bin/isalist‘; do
        if [-x ${DIR}/${isa}/${CMD}]; then
             EXEC=${DIR}/${isa}/${CMD}
             break
        fi
    done
    if [-z "${EXEC}"]; then
    echo 1>&2 "$0: no executable for this architecture"
    exit 1
    fi
    exec ${EXEC} "${@}"

    另外,这个脚本的功能也可以在C代码中通过isaexec()函数来实现。

  • 相关阅读:
    3 Redis 的常用五大数据类型
    Oracle12C 基本操作和使用
    CentOS7安装VNC服务
    CentOS7.6 安装Oracle12C(下)
    CentOS7.6 安装Oracle12C(上)
    博主创建了一个AGV吧的Discuz,欢迎各位加入进来
    六、openTCS4.17汉化版源码包含通信DEMO,gitee地址见内容
    毕马威图形数独
    五、OpenTCS4.12的模拟运行
    四、通过Socket实现跟AGV小车通信(仅做Demo演示,跟实际工厂运行无关)
  • 原文地址:https://www.cnblogs.com/langqi250/p/2537965.html
Copyright © 2011-2022 走看看