Unix C學習小結

轉自:http://www.cnblogs.com/zhangming-blog/p/4020535.html

1.malloc工作原理:     malloc使用一個數據結構(鏈表)維護分配空間

    鏈表的構成:分配的空間/上一個空間數據/下一個空間/空間大小等信息.
    對malloc分配的空間不要越界訪問.因爲容易破壞後臺維護結構.導致malloc/free/calloc/realloc不正常工作.
2.有關__stdcall __cdecl __fastcall
<1>.決定函數棧壓棧的參數順序. <2>.決定函數棧的清空方式   <3>.決定了函數的名字轉換方式.
__cdecl
  這是編譯器默認的函數調用轉換方式,它可以處理可變參數的函數調用。參數的入棧順序是從右向左。在函數運行結束後,由調用函數負責清理入棧的參數。在編譯時,在每個函數前面加上下劃線(_),沒有函數名大小寫的轉換。即_functionname
  每一個調用它的函數都包含清空堆棧的代碼,所以產生的可執行文件大小會比調用_stdcall函數的大。函數採用從右到左的壓棧方式。注意:對於可變參數的成員函數,始終使用__cdecl的轉換方式。
 
__fastcall
  有一些函數調用的參數被放入ECX,EDX中,而其它參數從右向左入棧。被調用函數在它將要返回時負責清理入棧的參數。在內嵌彙編語言的時候,需要注意寄存器的使用,以免與編譯器使用的產生衝突。函數名字的轉換是:@functionname@number沒有函數名大小寫的轉換,number表示函數參數的字節數。由於有一些參數不 需要入棧,所以這種轉換方式會在一定程度上提高函數調用的速度。
 
__stdcall
  函數參數從右向左入棧,被調用函數負責入棧參數的清理工作。函數名轉換格式如下:_functionname@number
 
3.虛擬內存:      虛擬地址與物理地址映射的時候有一個基本單位: 4k  一個內存頁.     如果虛擬地址沒有映射到物理地址,試圖用指針訪問必定發生段錯誤
4.分配釋放內存函數:      int brk(void *end);//分配空間,釋放空間
     void *sbrk(int size);//返回空間地址 
            sbrk(int  size)
    sbrk與brk後臺系統維護一個指針.
    指針默認是null.
    調用sbrk,判定指針是否是0,是:得到大塊空閒空間的首地址初始化指針.
5.映射虛擬內存函數:
  mmap(分配)/unmap(釋放)
 
void *mmap(
void *start,//指定映射的虛擬地址 0由系統指定開始位置)
size_t length,//映射空間大小 pagesize倍數
int prot,//映射權限  PROT_NONE | PROT_READ PROT_WRITE PROT_EXEC
int flags,//映射方式
int fd,//文件描述符號
offset_t off);//文件中的映射開始位置(必須是pagesize的倍數)
 
映射方式:
內存映射:匿名映射。
文件映射:映射到某個文件   只有文件映射最後兩個參數有效。
 
MAP_ANONYMOUS
MAP_SHARED   MAP_PRIVATE(二選一)
 
 
 
6.編譯工具與動態庫:
 
<1> gcc
-o  輸出文件名
-O  -O0 -O1 -O2 -O3 編譯優化
-g  -g0 -g1 -g2 -g3  產生調試信息
-W  all  error  
-Wall  顯示所有警告 
-Werror   把警告當錯誤
-w  關閉警告
 
 
 
-c  只編譯不連接
-E  預編譯
-S  彙編
 
-D 在命令行定義宏。
在代碼中定義宏
在命令行定義宏
 
-x  指定編譯的語言類型
c++
c
.S
none 自動判定
-std=C89
C99
 
 
 
編譯過程:-E  -c -S   自動調用連接器
連接器 ld
補充:
.c
.cpp
.CC
.h
.hpp
.o
.a
.so
.i    預編譯文件
.s  彙編文件
 
 
<2>
1.編譯過程(*.a   achieve)
1.1.編譯成目標文件
-static  可選
gcc -c -static 代碼文件.c
 
1.2.歸檔成靜態庫
ar工具
ar -r  ||  -t
ar -r 靜態庫文件  被歸檔的文件
 
nm工具(察看函數符號表)
nm 靜態庫或者動態庫或者目標文件或者執行文件
1.3.使用靜態庫
gcc 代碼  靜態庫 
 
2.庫的規範與約定
庫命名規則:
lib庫名.a.主版本號.副版本號.批號
lib庫名.a
庫使用規則
-l 庫名
-L 庫所在目錄
 
 
<3>.動態庫的編譯
 
1.什麼是動態庫?(共享庫)
動態庫是可以執行,靜態庫不能執行
但動態庫沒有main,不能獨立執行。
動態庫不會連接成程序的一部分。
程序執行的時候,必須需要動態庫文件。
 
2.工具
       ldd  察看程序需要調用的動態庫
ldd 只能察看可執行文件.
readelf -h 察看執行程序頭.
nm   察看庫中的函數符號
 
3.動態庫的編譯
3.1.編譯
-c -fpic(可選)
3.2.連接
shared
4.使用動態庫
gcc 代碼 動態庫文件名
gcc 代碼   -l庫名 -L動態庫所在路徑
 
標準命名規則:
lib庫名.so
        lib庫名.a
-l 庫名  -L 庫所在路徑
 
<5>使用libdl.so庫
動態庫加載的原理 動態庫中函數的查找已經封裝成庫libdl.so
 
dlopen  打開一個動態庫
dlsym 在打開動態庫找一個函數
dlclose 關閉動態庫
//dlerror 返回錯誤
 
 
7.make工具的使用:
(1). vi  demo.mk
(2)編輯:  demo:
                           gcc -c -fpic test1.c
                           gcc -c -fpic test2.c
                           gcc test1.o  test2.o  -shared  -o libtest.so
                           gcc main.c -l test -o main -L.
(3).執行demo.mk文件:
               make -f demo.mk demo
注意:須將libtest.so 庫文件拷貝到/lib或usr/lib目錄下
 
 
 
8.使用main方法參數獲得環境變量:(直接獲取可以用env)
 
int main(int argc,char*argv[],char**arge)
{
        while(*arge)
       {
              printf("%s\n",*arge);
              arge++;
       }
}
 
 
 
9.IO基礎
 
<1>.認識內核對象
不允許訪問內核設備和內存,
但可以通過內核系統函數去訪問.
對每個內核對象進行編號ID.
如果訪問內核對象,只能通過ID.
編程模型:
申請得到一個ID
在內核系統函數中使用ID得到對應內核對象數據
<2>.怎麼訪問文件
使用函數,傳遞一個文件,系統打開文件,加載文件數據,
返回一個ID.
使用函數,傳遞ID,得到數據.
使用函數傳遞ID,告訴系統釋放文件.
 
ID:文件描述符號.file description (fd)
 
每個程序執行的時候都有一個目錄,存放打開的文件描述符號
 
<3>.每個程序默認打開三個文件設備:
0:標準輸入
1:標準輸出
2:錯誤輸出
 
<4>.操作文件描述符號
ssize_t write(int fd,
void *buf,//要寫入內核對象的數據
size_t size);//寫入數據大小
返回:
>0 實際寫入的數據
-1 寫入錯誤
 
ssize_t read(int fd,
void *buf,//返回數據的空間
size_t size);//空間大小
返回:
>0:實際讀取的數據
=0:碰到文件結束符號EOF (ctrl+d)
-1:讀取錯誤
 
建議:
0:輸入
1:輸出
2:錯誤輸出
<5>.linux系統下文件的類型:
       目錄文件d
       普通文件f
       字符設備文件c
       塊設備文件b
       軟連接文件l
       管道文件p
       socket文件s
發佈了35 篇原創文章 · 獲贊 7 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章