顯示具有 compiler 標籤的文章。 顯示所有文章
顯示具有 compiler 標籤的文章。 顯示所有文章

2015年3月3日 星期二

[bug] make modules_prepare



Symptom:
- when compiling the driver, there maybe exist issue like :
......
In file included from include/linux/gfp.h:4:0,
                 from include/linux/slab.h:12,
                 from include/linux/percpu.h:5,
                 from include/asm/local.h:4,
                 from include/linux/module.h:19,
                 from
AX88179_178A_LINUX_DRIVER_v1.13.0_SOURCE/ax88179_178a.c:30:
include/linux/mmzone.h:18:26: fatal error: linux/bounds.h: No such file or directory
 #include <linux/bounds.h>
                          ^
.........

Root Cause:
- Header file miss.

Solution:
- go to kernel folder, issue the command:
make modules_prepare 
- after that, go back to make driver again

ref:
https://forums.gentoo.org/viewtopic-t-819002-start-0.html



2014年3月17日 星期一

#pragma pack

src:
http://www.cplusplus.com/forum/general/14659/
http://blog.xuite.net/jackie.xie/bluelove/7788211

notes:
14'3/17 :
[1]
- For linux [declared in data structure only ? In one line]
__attribute__ ((packed))

- For Window [declared by range]
#pragma pack...

#pragma pack...


[2] declaration of #pragma
- format-1
#pragma pack(1 )  [begin]
#pragma pack( )  [end]

- format-2 (it's better?)
#pragma pack(push, 1)
#pragma pack(pop)


----------------
(Very ) Basically the compiler unless otherwise directed will line up structure members on
2 byte or 4 byte boundaries - this makes it easier and faster for the processor to handle.
So the structure contains secret padding bytes to make this happen.

The pragma pack directive (in MS Compiler) allows you to change this alignment scheme.

Some things (particularly in relation to hardware) do not have the luxury to waste bytes like
this and they send their data in an exact fit.
This means that it is not wise to read data from a hardware device directly into a normal structure.

If you have want to read data that is an exact fit into a structure - you can tell the compiler
to make the structure an exact fit like this (microsoft compiler);
1
2
3
4
5
6
7
8
#pragma pack(push, 1) // exact fit - no padding
struct MyStruct
{
  char b; 
  int a; 
  int array[2];
};
#pragma pack(pop) //back to whatever the previous packing mode was 


Without the pragma directive, the size of the structure is 16 bytes - with the packing of 1 - the size is 13 bytes


----------------

#pragma pack(1) "是表示什麼意思呢?!

在這裡我先解釋"#pragma"的作用,"#pragma"就像是compiler的功能選擇開關,
也就是#pragma是用來設定complier的選項,跟你在complier後加 -Zp -Xk 等等設定是一樣的。使用它其實就如同你在dos下使用compiler時,在命令列輸入那些參數一樣,所達到的功能是一致的,像在 Watcom C/C++ 中 "#pragma off (check_stack)", 代表的是把WC++的stack檢查關閉,當然你也可以從命令列輸入參數做到一樣的功能,不過有點不一樣的,用"#pragma",你可以選擇所需要這麼處理的程式區段,所以比命令列更方便更好用.不過"#pragma"所提供的功能切換在不同的compiler上並不相同,所以要特別注意.

接下來進入主題,到底"#pragma pack(1)"是做什麼的?其實"#pragma pack( )"就是要compiler照我們的意思去做記憶體aligment(對齊)的工作,在Win32下為了提高記憶體存取效率,所以記憶體配置(對齊)的預設值是以DWORD(4BYTES也就是32bits)為單位,因此在配置struct的記憶體空間的時候,往往會造成struct內部的資料在記憶體位址上並不連續,在我們的程式之中,如果不是用指標去存取這些資料,可能還不會出錯,可是如果我們真的用指標去存取的話,由於資料排列不連續,我們可能會讀不到我們想要的值,這還不打緊,如果這個結構是傳址給Win API來取得資料,那就問題大條了,因為API會以為struct內部的記憶體位址是連續的,所以會造成錯誤,像我之前寫"在Win95/98下存取邏輯磁區"那篇文章的範例程式時,就為此吃足苦頭,不但結果不正確,還一直當機,後來才發現是記憶體aligment的問題,為了讓struct內部的記憶體位址是連續的,這時我們就必需要用"#pragma pack(1)"這個命令,來讓compiler把這個struct,以BYTE為單位做記憶體aligment,如此一來struct使用時就不會出錯了.

"#pragma pack()"有幾個值可供設定,如下所述,"#pragma pack(1)"是對齊BYTE,"#pragma pack(2)"是對齊WORD,而"#pragma pack( )"等於"#pragma pack(4)",就是對齊DWORD,另外,還有"#pragma pack(8)",以及"#pragma pack(16)"可以選用,所以我們只要將struct的定義區段,用"#pragma pack(1)"和"#pragma pack( )"包起來,就可以了使struct正確被存取了.以下是個示範aligment的程式:

////本程式在BCB5中順利編譯執行
#include <stdio.h>
#include <conio.h>
#include <windows.h>
int main(int argc, char* argv[])
{

    #pragma pack(4)
    ////記憶體對齊單位用DWORD
    typedef struct _aligment_DWORD{
        char a ;
        WORD test1;
        char b ;
        char c ;
        char d ;
    } aligment_DWORD;
    #pragma pack( )

    #pragma pack(1)
    ////記憶體對齊單位用BYTE
    typedef struct _aligment_BYTE{
        char e ;
        WORD test2 ;
        char f ;
        char g ;
        char h ;
    } aligment_BYTE;
    #pragma pack( )

    aligment_BYTE ali_byte ;
    aligment_DWORD ali_dw ;
    ali_dw.a = 'A' ;
    ali_dw.b = 'B' ;
    ali_dw.c = 'C' ;
    ali_dw.d = 'D' ;
    ali_byte.e = 'E' ;
    ali_byte.f = 'F' ;
    ali_byte.g = 'G' ;
    ali_byte.h = 'H' ;
    LPTSTR pointer ;

    printf("aligment_DWORD struct is %d BYTES \n",sizeof(ali_dw));
    printf("aligment_BYTE struct is %d BYTES\n",sizeof(ali_byte));
    pointer = (LPTSTR)(&ali_byte) ;
  
    //請注意記憶體的位址,和輸出的結果之間的關係
    printf("ali_byte.e is %c \n",*pointer);
    printf("ali_byte.f is %c \n",*(pointer + 3 ));
    printf("ali_byte.g is %c \n",*(pointer + 4 ));
    printf("ali_byte.h is %c \n",*(pointer + 5 ));

    pointer = (LPTSTR)(&ali_dw) ;
    printf("ali_byte.a is %c \n",*pointer);
    printf("ali_byte.b is %c \n",*(pointer + 4 ));
    printf("ali_byte.c is %c \n",*(pointer + 5 ));
    printf("ali_byte.d is %c \n",*(pointer + 6 ));

    getch();
    return 0;
}

    ////輸出結果如下

    aligment_DWORD struct is 8 BYTES
    aligment_BYTE struct is 6 BYTES
    ali_byte.e is E
    ali_byte.f is F
    ali_byte.g is G
    ali_byte.h is H
    ali_byte.a is A
    ali_byte.b is B
    ali_byte.c is C
    ali_byte.d is D

    ////////////////////////////////// 

讓我們來看上面這個程式還有它的輸出結果,程式中的兩個struct內容總共都是 6 BYTES,可是由於aligment設定的不同,一個size是正常的6 BYTES,另一個竟然變成是8 BYTES,為了輸出正確結果,那個aligment設為DWORD的struct,在printf( )中的位址變得很奇怪吧!!

所以如果我們要避免struct在Win32的程式中出錯,以後可別忘了加上"#pragma pack(1)"和"#pragma pack( )" !


#pragma pack(n)是用來讓struct的成員對齊記憶體用的,在32bit系統下基於處理器效率的考量,由於預設的對齊位置是4 bytes,所以所有的struct成員視為 #pragma pack(4),但有時候我們希望struct裡成員是連績的,尤其是控制硬體相關的io位置,所以會設為#paragma pack(1),讓struct的成員要用 Byte 來對齊。看以下例子:

struct pci_conf {
        WORD VendorID;
        WORD DeviceID;
        ...
} pci;
如果沒有用#pragma pack(1),VendorID後會空2 bytes不用,以便對到4 bytes
(假設一開始是對齊的),然後才配置DeviceID。
可是若沒留意這樣的問題,
(BYTE*) p = &pci;
預期*(p+0x2)是DeviceID就會出問題。
#pragma pack和數據對齊問題
結構數據存放時預設是按4
 bytes對齊,考慮以下程序,輸出結果為:sizeof(A)=12

typedef struct _A
{
    int x;
    char z[7];
}A;

void main()
{
    int len = sizeof(A);
    printf("sizeof(A)=%d\n", len);    // len = 12
}


使用 #pragma pack,設置數據按1對齊,此時輸出結果為:sizeof(A)=11
#pragma pack(push)
#pragma pack(1)
typedef struct _A
{
    int x;
    char z[7];
}A;
#pragma pack(pop)

void main()
{
    int len = sizeof(A);
    printf("sizeof(A)=%d\n", len);    // len = 11
}

其中 : 


push 就是在改變為 1 之前先儲存原來的設定。 
pop 當然就是恢復原來的設定了。

__attribute__ ((packed))

src:
http://hi.baidu.com/weipatty/item/b5a9964daab2f1aadf2a9fd4

notes:

----------

__attribute__ ((packed)) 的作用

最近在看我们的代码的时候发现声明类型的时候有 __attribute__ ((packed))的结构体类型声明,不知道是什么意思,查了下知道是如下含义:
1. __attribute__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法。这个功能是跟操作系统没关系,跟编译器有关,gcc编译器不是紧凑模式的,我在windows下,用vc的编译器也不是紧凑的,用tc的编译器就是紧凑的。例如:
在TC下:struct my{ char ch; int a;} sizeof(int)=2;sizeof(my)=3;(紧凑模式)
在GCC下:struct my{ char ch; int a;} sizeof(int)=4;sizeof(my)=8;(非紧凑模式)
在GCC下:struct my{ char ch; int a;}__attrubte__ ((packed)) sizeof(int)=4;sizeof(my)=5
2. __attribute__关键字主要是用来在函数或数据声明中设置其属性。给函数赋给属性的主要目的在于让编译器进行优化。函数声明中的__attribute__((noreturn)),就是告诉编译器这个函数不会返回给调用者,以便编译器在优化时去掉不必要的函数返回代码。
GNU C的一大特色就是__attribute__机制。__attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。

__attribute__书写特征是:__attribute__前后都有两个下划线,并且后面会紧跟一对括弧,括弧里面是相应的__attribute__参数。

__attribute__语法格式为:

__attribute__ ((attribute-list))

其位置约束:放于声明的尾部“;”之前。

函数属性(Function Attribute):函数属性可以帮助开发者把一些特性添加到函数声明中,从而可以使编译器在错误检查方面的功能更强大。__attribute__机制也很容易同非GNU应用程序做到兼容之功效。

GNU CC需要使用 –Wall编译器来击活该功能,这是控制警告信息的一个很好的方式。

packed属性:使用该属性可以使得变量或者结构体成员使用最小的对齐方式,即对变量是一字节对齐,对域(field)是位对齐。
/* __attribute__ ((packed)) 的位置约束是放于声明的尾部“;”之前 */
struct str_struct{
        __u8    a;
        __u8    b;
        __u8    c;
        __u16   d;
} __attribute__ ((packed));

/* 当用到typedef时,要特别注意__attribute__ ((packed))放置的位置,相当于:
   * typedef struct str_stuct str;
   * 而struct str_struct 就是上面的那个结构。
*/
typedef struct {
        __u8    a;
        __u8    b;
        __u8    c;
        __u16   d;
} __attribute__ ((packed)) str;
/* 在下面这个typedef结构中,__attribute__ ((packed))放在结构名str_temp之后,其作用是被忽略的,注意与结构str的区别。*/
typedef struct {
        __u8    a;
        __u8    b;
        __u8    c;
        __u16   d;
}str_temp __attribute__ ((packed));