在裝置驅動方面,Linux2.6相對於Linux2.4有較大的改動,這主要表現在核心API中增加了不少新功能(如記憶體池)、sysfs檔案系統、核心模組從.o變為.ko、驅動模組編譯方式、模組使用計數、模組載入和卸載函數的定義等方面
Linux核心主要有進程調度、記憶體管理、虛擬檔案系統、網路介面和處理序間通訊等5個子系統組成,如:
在裝置驅動編程中,當請求的資源不能滿足時,驅動一般會調度其他線程執行,並使驅動對應的進程進入睡眠狀態,直到它請求的資源被釋放,才會被喚醒而紀念日就緒狀態
在裝置驅動編程中,如果需要幾個並發執行的任務,可以啟動核心線程,啟動核心線程的函數為:int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
Linux記憶體管理完成為每個進程進行虛擬記憶體到實體記憶體的轉換。一般而言,Linux的每個進程享有4GB的記憶體空間,0-3GB屬於使用者空間,3-4GB屬於核心空間,核心空間對常規記憶體、I/O裝置記憶體以及高端記憶體存在不同的處理方式
虛擬檔案系統隱藏了各種硬體的具體細節,為所有的裝置提供了統一的介面。而且,它獨立於各個具體的檔案系統,是對各種檔案系統的一個抽象,它使用super block存放檔案系統相關資訊,使用索引節點inode存放檔案的物理資訊,使用目錄項dentry存放檔案的邏輯資訊
Linux系統只能通過系統調用和硬體中斷完成從使用者空間到核心空間的控制轉移
Linux下的c編程
1、零長度數組
GNU C中允許使用零長度的數組。它們作為結構體的最後一個元素十分有用,在ISO C89中,你需要給目錄分配長度1,意味著要浪費空間或者使malloc的參數變得複雜。在ISO C99中,你可以使用靈活的數組元素,只是在文法和主義上有微小的差異。
·靈活的數組元素寫為contents[]不帶0。
·靈活的數組元素具有不完全的類型,所以sizeof操作也許不能被應用。作為零長度數組的原始實現的奇怪之處,sizeof被賦值為0。
靈活的數組元素可以作為結構體的最後一個元素出現當其它元素非空時。GCC現在在任何地方允許零長度數組。定義僅含有一個零長度數組的結構體,無論如何,你可能會遇到問題。這樣的用法被反對,我們建議僅當靈活數組元素被允許的地方使用零長度數組。如:
#include <stdio.h>
#include <string.h>
struct arr
{
int a;
char buff[0];
};
int main()
{
char b[0];
struct arr *ptr;
ptr = (struct arr *)malloc(sizeof(struct arr)+4);
if(ptr == NULL)
{
printf("malloc failed/n");
return -1;
}
memset(ptr,0x30,sizeof(struct arr)+4);
printf("0x%x 0x%x 0x%x 0x%x/n", ptr->buff[0],ptr->buff[1],ptr->buff[2],ptr->buff[3]);
printf("%d %d %d/n",sizeof(struct arr),sizeof(int),sizeof(b[0]));
return 0;
}
其中malloc分配了資料結構struct arr的大小再加上4個位元組大小,實際上sizoef(struct arr) = 4 = sizoef(int),不包括零長度數組的大小,所以memset之後,buff的內容都是0x30,sizeof(b[0]) = 1。
2、case範圍
GNU c支援case x…y這樣的文法,區間[x, y]的數都滿足這個case條件,如:
Switch(ch)
{
Case ‘0’ …’9’ : c -= ‘0’;
Break;
Case ‘a’…’f’ : c -= ‘a’ – 10;
Break;
}
3、語句運算式
GNU c把包含在括弧的複合陳述式看做一個運算式,稱為語句運算式,它可以出現在允許運算式出現的任何地方。我們可以在語句運算式中使用原本只能在複合陳述式中使用的迴圈變數、局部變數等。如:
#include <stdio.h>
#define min_t(type, x, y) /
({type __x = (x); type __y = (y); __x < __y ? __x : y;})
int main()
{
int ia, ib, mini;
float fa, fb, minf;
ia = 1;
ib = 2;
fa = 1.1;
fb = 2.2;
mini = min_t(int, ++ia, ++ib);
minf = min_t(float, ++fa, ++fb);
printf("mini = %d/nminf = %f/n", mini, minf);
return 0;
}
4、typeof關鍵字
Typeof(x)語句可以獲得x的類型,因此,我們可以藉助typeof重新定義min_t
#define min_t(x, y) ({ /
const typeof(x) __x = (x); /
const typeof(y) __y = (y); /
(void)(&__x == &__y); /
__x < __y ? __x : __y;})
5、可變參數的宏
標準c只支援可變參數的函數,例如printf的原型為
int printf(const char *format {, argument}…);
在GNC c中,宏也可以接受可變數目的參數,如:
#define pr_debug(fmt, arg…) printfk(fmt, ##arg)
“##”是處理arg不代表任何參數的情況,這時候,前面的逗號就變得多餘了,使用“##”之後,GNU c前置處理器會丟棄前面的逗號
6、標號元素
指定數組的方法是在初始化值前添加“[index]=”,當然也可以用“[first … last] = ”的形式指定一個範圍。如:
unsigned char data[MAX] = {[0 … MAX-1] = ‘a’};
7、當前函數名
GNU c預定義了兩個標誌儲存當前函數的名字,__FUNCTION__儲存函數在源碼中的名字,__PRETTY_FUNCTION__儲存帶有語言特色的名字,在c函數中,這兩個名字是相同的:
void example()
{
printf("This is function: %s ", __FUNCTION__);
printf("This is function: %s", __PRETTY_FUNCTION__);
}
輸出:example example
8、特殊屬性聲明
GNU c允許函數、變數和類型的特殊屬性,以便進行手工的代碼最佳化和定製代碼檢查的方法。指定一個聲明的屬性,只需要在聲明後添加__attribute__(( ATTRIBUTE ))。其中ATTRIBUTE為屬性說明,如果存在多個屬性,則以逗號分隔。GNU c支援noreturn、format、section、aligned、packed等十多個屬性
noreturn屬性作用於函數,表示該函數從不返回。這會讓編譯器最佳化代碼,並消除不必要的警告資訊。如:
#define ATTRIB_NORET __attribute__((noreturn))
asmlinkage NORET_TYPE void do_exit(long error_code) ATTRIB_NORET
format屬性頁面用於函數,表示使用printf、scanf或strftime風格的參數,指定format屬性可以讓編譯器根據格式串檢查參數類型,如:
asmlinkage int printk(const char *fmt, …) __attribute__((format (printf, 1, 2)));
上述代碼中的第一個參數時格式串,從第二個參數開始都會根據printf函數的格式串規則檢查參數。
unused屬性作用於函數和變數,表示該函數或變數可能不會被用到,這個屬性可以避免編譯器產生警告資訊。
aligned屬性用於變數、結構體或聯合體,指定變數、結構體或聯合體的對界方式,以位元組為單位,如:
struct example_struct
{
char a;
int b;
long c;
}__attribute__((aligned(4)));
表示該結構體的變數以4位元組對界
packed屬性作用於變數和類型,用於變數或結構體成員時表示使用最小可能的對界,用於枚舉、結構體或聯合體類型時,表示該類型使用最小的記憶體。如
struct example_struct
{
char a;
int b;
long c __attribute__((packed));
};
編譯器對結構體成語及變數對界的目的是為了更快的訪問結構體或成員及變數佔據的記憶體,如,對一個32位整形變數,若以4位元組的方式存放(即低兩位地址為00),則cpu在一個匯流排周期內就可以讀取32為,若不然,cpu需要兩次匯流排周期才能組合為32位整數
9、內建函數
GNU c提供了大量的內建函數,其中大部分是標準c庫函數GNU c編譯器內建版本,如memcpy等,它們與對應的標準c庫函數功能相同。不屬於庫函數的其他內建函數的命名通常以__builtin開始。
do{}while(0)
在Linux核心中,do{}while(0);主要用於宏定義,可避免分支、邏輯、分號使用的錯誤,保證能無編譯錯誤的使用宏,如
#include<stdio.h>
#include<malloc.h>
//#define SAFE_FREE(p) ({free(p); p = NULL;})
#define SAFE_FREE(p) do{free(p); p = NULL;}while(0)
int main()
{
int *p = malloc(4);
if(NULL != p)
SAFE_FREE(p);
else
return -1;
printf("success!/n");
return 0;
}
goto
在Linux核心中隊goto的應用非常廣泛,但是一般只限於錯誤處理中,用於錯誤處理的goto用法簡單而高效,只需保證在錯誤處理時登出、資源釋放的順序與正常的註冊、釋放申請的順序相反。
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/dingyuanpu/archive/2010/05/09/5572297.aspx