当前位置:早雪网网络学院编程文档C/C++ → Unix编程/应用问答中文版 ---8.Solaris内核编程相关问题

Unix编程/应用问答中文版 ---8.Solaris内核编程相关问题

减小字体 增大字体 作者:不详  来源:supcode.com收集整理  发布时间:2005-7-22 19:40:41
: 我正在写一个流模块,其中用到了#pragma pack(),当使用 

   gcc -D_KERNEL -c abc.c 
   ld -r -o abc abc.o 

   编译链接时,一切正常。为了获得64-bit模块,我必须使用Sun Workshop 5.0, 
   结果导致系统崩溃。访问 

   http://docs.sun.com/htmlcoll/coll.32.8/iso-8859-1/CPPPG/Pragmas.html#15434 

   上面说必须在编译链接应用程序的时候指定"-misalign",所以我用了如下命令编译 

   /opt/SUNWspro/bin/cc -D_KERNEL -misalign -c abc.c 
   /usr/ccs/bin/ld -r -o abc abc.o 

   但是我不知道该如何在链接时指定"-misalign"。使用的是"/usr/ccs/bin/ld"。 

A: Casper H.S. Dik - Network Security Engineer <Casper.Dik@Holland.Sun.Com> 

   "-misalign"仅仅用于应用程序,无法应用到内核编程中。"-misalign"使得编译 
   获得的代码增加了一些runtime glue,它们将指示内核模拟unaligned load(慢)。 
   作为内核编程,没有等效技术。 

Q: 使用#pragma pack()是因为需要读取来自Windows客户端的报文,对端使用 
   #pragma pack(1)压缩了所使用的数据结构 

   #pragma pack(1) 
   typedef struct pkt_hdr_struct 
   { 
       uint8_t  pkt_ver; 
       uint32_t pkt_type; 
       uint32_t pkt_len; 
   } pkt_hdr_t; 
   #pragma pack() 

   为了采用这个结构读取网络数据,Solaris端的服务程序需要强制转换匹配该结构, 
   但是一旦企图读取紧接在pkt_ver成员之后的pkt_type成员,崩溃了。尝试过其他 
   办法,首先用一个字符指针读取第一个字节,然后指针增一,把该指针强制类型 
   转换成( uint32_t * ),然后读取数据,依然崩溃。 

   此外,是否意味着无法在内核模块编程中使用#pragma pack() 

A: Ed L Cashin <ecashin@coe.uga.edu> 

   我想你可以单独写一个pkt_header_read()函数,单字节读取然后拼装成相应的数 
   据类型。如果你想避免函数调用,可以使用"inline"关键字。 

A: Casper H.S. Dik - Network Security Engineer <Casper.Dik@Holland.Sun.Com> 

   你是否意识到pkt_hdr_t结构使得你必须自己转换字节序(对端是x86平台) 
   我不认为#pragma pack()是最好的解决办法,考虑定义如下结构 

   struct phs 
   { 
       char ver; 
       char type[4]; 
       char len[4]; 
   } 

   采用memcpy()读取数据 

   memcpy( &phs.type[0], &pkt.pkt_type, 4 ); 

A: Andrew Gabriel <andrew@cucumber.demon.co.uk> 

   采用字符指针是正确的,但是你犯了个错误,编写如下函数 

   int read_misaligned_int ( int * iptr ) 
   { 
       int    i; 
       int    value; 
       char * ptr  = ( char * )iptr; 
       char * vptr = ( char * )&value; 

       for ( i = 0; i < sizeof( int ); i++ ) 
       { 
           *vptr++ = *ptr++; 
       } 

       return( value ); 
   } 

   此外,既然你提到对端是x86平台,可能还需要考虑字节序转换的问题 

A: W. Richard Stevens <1999年逝世,享年49岁> 

/* 
* return value: 
*     1 big-endian 
*     2 little-endian 
*     3 unknow 
*     4 sizeof( short ) != 2 
*/ 
static int byte_order ( void ) 

    union 
    { 
        short s; 
        char  c[ sizeof( short ) ]; 
    } un; 

    un.s = 0x0201; 
    if ( 2 == sizeof( short ) ) 
    { 
        if ( ( 2 == un.c[0] ) && ( 1 == un.c[1] ) ) 
        { 
            puts( "big-endian" ); 
            return( 1 ); 
        } 
        else if ( ( 1 == un.c[0] ) && ( 2 == un.c[1] ) ) 
        { 
            puts( "little-endian" ); 
            return( 2 ); 
        } 
        else 
        { 
            puts( "unknow" ); 
            return( 3 ); 
        } 
    } 
    else 
    { 
        puts( "sizeof( short ) = %d", sizeof( short ) ); 
        return( 4 ); 
    } 
    return( 3 ); 
}  /* end of byte_order */ 

D: CERNET 华中地区网络中心 程序设计版 集体讨论汇总 

为了解决Unix自定义结构在GCC优化编译中对齐问题,一般解决办法是用如下宏封装 
自定义结构 

    #pragma pack(1) 

    struct my_arphdr 
    { 
    }; 

    #pragma pack() 

如果是SPARC/Solaris,还可以这样 

    struct my_arphdr 
    { 
    } __attribute__ ((packed)); 

两种办法其实都可以用在Unix系统/GCC编译器中。 

D: mbuf@smth 

关于结构中字节对齐问题,相应编译器选项为 

GCC/G++           : -fpack-struct 
Sun Workshop cc/CC: -misalign 

最好不这样做,会大大降低程序效率,特别在某些架构中。应该尝试用位操作来处理。 

D: Unknown@smth 

GCC可以这么解决 

#ifdef __GCC__ 
#define PACKED __attribute__((__packed__)) 
#else 
#define PACKED 
#endif 

struct msg 

    u_int16_t PACKED first; 
    ... 
}; 

还是 VC 简单,#include <pshpack1.h> 就搞定了 

A: gfh_nuaa 

DEC   : #pragma pack(1) 
SUN   : #pragma pack(1) 
AIX   : 编译时 -q align=packed 
HP-UX : #pragma pack 1 

D: Joe Durusau 

在 Visual C++ 中,使用 "-ZP1" 就可以让编译器对自定义结构进行单字节对齐,实 
际就是取消了对齐优化。 

A: law@apue.dhs.org 2001-12-20 13:09 

1) 结构内部成员的pack 

struct foo 

    char a; 
    int  b __attribute__ ((packed)); 
}; 

2) 整个结构的pack 

struct foo 

    char a; 
    int  b; 
}__attribute__ ((packed)); 

3) 文件范围的pack 

#pragma pack(1) 

struct foo 

    char a; 
    int  b; 
}; 

... ... 

4) 编译选项的pack 

-fpack-struct 

但这是最危险的做法,因为这样做可能会使库函数和你的程序对结构内成员的偏移理 
解不一致。 

Q: 小四 <scz@nsfocus.com> 

#pragma pack(push) 
#pragma pack(n) 
... ... 
#pragma pack(pop) 

push/pop这个用法都谁支持啊 

A: law@apue.dhs.org 

这个写法我没见过,VC和GCC都是这样写的 

#pragma (push, N)  // 把原来align设置压栈,并设新的pack为N 
#pragma (pop)      // align设置弹栈 

8.6 如何得到非局部变量列表 

Q: 什么工具可以从目标文件中提取非局部变量列表 

A: Donald McLachlan <don@mars.dgrc.crc.ca> 

最简单的就是nm,假设你有一个目标文件(或者已链接过的可执行文件),nm -g将显 
示所有"全局"变量。下面是一个Solaris的例子: 

-------------------------------------------------------------------------- 
/* gcc -o junk junk.c */ 

int        var1; 
static int var2; 

int main ( void ) 

    int var3; 

    return( 0 ); 
}  /* end of main */ 
-------------------------------------------------------------------------- 

$ nm -g junk 

junk: 

[Index]   Value      Size    Type  Bind  Other Shndx   Name 

[66]    |    133640|       0|OBJT |GLOB |0    |15     |_DYNAMIC 
[61]    |    133496|       0|OBJT |GLOB |0    |13     |_GLOBAL_OFFSET_TABLE_ 
[71]    |    133528|       0|OBJT |GLOB |0    |14     |_PROCEDURE_LINKAGE_TABLE_ 
[69]    |         0|       0|NOTY |WEAK |0    |UNDEF  |__deregister_frame_info 
[60]    |         0|       0|NOTY |WEAK |0    |UNDEF  |__register_frame_info 
[70]    |    133836|       0|OBJT |GLOB |0    |19     |_edata 
[59]    |    133872|       0|OBJT |GLOB |0    |20     |_end 
[58]    |    133864|       4|OBJT |GLOB |0    |20     |_environ 
[72]    |     67960|       0|OBJT |GLOB |0    |12     |_etext 
[67]    |    133600|       0|FUNC |GLOB |0    |UNDEF  |_exit 
[75]    |     67936|      20|FUNC |GLOB |0    |11     |_fini 
[64]    |     67908|      28|FUNC |GLO

上一页  [1] [2] [3]  下一页

[数据载入中...] [返回上一页] [打 印]