我要好offer之 系統基礎大總結

1. APUE Unix環境高級編程

(1) Unix基礎知識: 內核->系統調用->shell和庫函數->應用軟件html

(2) 文件I/O:read函數返回值、進程的文件描述符表、文件共享、inode、fcntl函數node

(3) 文件和目錄:文件類型(普通、目錄、socket、FIFO、PIPE)、文件系統(硬連接、軟連接)linux

(4) 標準I/O庫:FIFE封裝、最佳緩衝大小測試c++

(5) 進程環境:進程終止狀況、longjmp、volatile用法程序員

(6) 進程控制:fork(返回值、父子進程的文件描述符表)、wait函數、exec系函數算法

(7) 信號:三種處理方式、常見信號(SIGCHLD、SIGSEGV)及其默認處理方式shell

(8) 線程同步:進程和線程的異同點、線程回調函數的傳參、進程和線程原語對比、線程同步(讀寫、寫寫、i++多線程、mutex)編程

(9) 高級I/O(一):非阻塞I/O、select使用、readn和writen封裝、mmap映射數組

(10) 高級I/O(二):管道、消息隊列、共享存儲器mmap緩存

(11) 網絡套接字:大小端字節序、addrinfo結構體、getaddrinfo函數、tcp_listen和tcp_connect封裝

 

2. Linux系統編程

(1) 系統調用、API和ABI、文件(各類類型簡介、inode、軟連接、硬連接)、進程簡介

(2) 文件I/O:read函數返回值、readn和writen函數封裝、文件定位、文件同步、文件截斷、多路I/O(select、poll)、Linux內核實現

(3) 標準I/O緩衝:測試最佳I/O緩衝區大小、三種類型緩衝、標準I/O的線程安全、標準I/O的缺點

(4) 高級I/O:彙集I/O(readv、writev性能好、原子性)、epoll(LT和ET)、mmap(優缺點)、I/O調度算法(電梯調度)

(5) 進程管理:進程pid分配方法、fork and exec、copy on write、wait、殭屍進程的回收

(6) 進程調度:Linux進程調度算法(FIFO、最短優先、時間片輪轉)、CPU綁定(緩存影響)

(7) 線程:虛擬化抽象(虛擬內存與進程關聯、虛擬處理器與線程關聯)、多線程好處、多線程i++解析、pthread使用、RAII封裝mutex

(8) 文件和目錄管理:文件inode節點元數據、目錄操做、軟連接和硬連接、塊設備/dev/null

(9) 內存管理:進程地址空間、動態分配內存(malloc、calloc、brk)、數據對齊、匿名文件映射、變長數組

(10) 信號:信號的3中處理方式、常見的信號

(11) 時間:gettimeofday、sleep休眠、定時器alarm

 

3. 位、字節、整型

字節序問題:

大端:地址爲 閱讀順序:Sun系統 和 網絡字節序

小端:地址爲 逆閱讀序:X86

 

信息 = Bit位 + 解釋方式,不管怎麼轉換,Bit位是永遠不變的,只有解釋方式改變了

對於int的使用,參見:Google c++編程規範中int型使用

C語言整型溢出問題by @左耳朵耗子

儘可能不要使用無符號數,極易bug:當執行一個運算時,若是一個運算數是有符號的而另外一個是無符號的,那麼c語言會隱式地將有符號數強制類型轉換爲無符號數

好比:函數參數類型爲size_t, 我傳入實參-1,這時-1會隱式的 轉換爲 最大正數,徹底錯了

 

4. 數據對齊、結構體訪問、offsetof

結構體數據對齊有2個原則:

(1) 每一個成員數據的偏移 必須是 該數據類型大小的整數倍

(2) 整個結構體大小 必須是 最大數據類型大小的 整數倍

數據對齊產生了 內部碎片,爲了使內部碎片最小,必須讓 最大的數據類型擺放在最前面

 

如何計算 每一個成員數據在結構體內的偏移呢? C語言提供 offsetof宏

#define offsetof(type, member) (size_t)&(((type*)0)->member)
    struct test {
        int  val;
        int  a[2];
    };
    // 結構體訪問和數組訪問的實質都是 首地址加上對應偏移,而後讀取對應數據,注意 取地址 和 取成員 操做的區別
    struct test* ptest = NULL;              // 結構體首地址爲0
    fprintf(stdout, "1:%p\n", &ptest->val); // 注意:這是讀取 結構體成員數據的偏移,直接就是 首地址加上 offset,而不是 先取到數據而後取地址
    fprintf(stdout, "2:%d\n", ptest->val);  // 錯誤,能夠打印地址0的地址值,可是不能訪問地址值爲0的數據
    fprintf(stdout, "3:%p\n", &ptest->a);   // 正確,首地址加上offset
    fprintf(stdout, "4:%p\n", ptest->a);    // 同上,數組名退化爲 數組首地址,因此這仍是一個取地址操做

具體詳見:C語言結構體內的數組和指針by@左耳朵耗子

5. cache 矩陣乘法

CPU Cache示例by@左耳朵耗子

C語言數組行優先存儲,當數組大小超過 緩存塊大小時,不一樣的存取方式之間 差異很大,以 A[N][N] * B[N][N] 存儲在 C[N][N]中

     

 

 

 

6. 編譯連接

 

靜態編譯和動態編譯

詳見陳碩的 <C++編譯連接模型精要>

 

連接器主要完成兩件事:

(1) 符號解析:將每一個符號的引用(reference)對應到相應符號的定義(definition)

C程序員應該儘量使用static屬性在模塊內部隱藏變量和函數聲明,即模塊私有

注:使用 readelf命令來查看目標文件的符號表

當linker遇到重名時:

重名Local定義:編譯器解決

重名Global定義:強符號(函數名和已初始化的全局變量)和弱符號(未初始化的全局變量)

(2) 重定位:合併不一樣文件時修改符號地址,將符號的相對地址 改成 絕對地址

Linux系統爲動態連接庫提供了一個簡單的接口,容許應用程序在運行時加載和連接共享庫

#include <dlfcn.h>
void* dlopen(const char* filename, int flag); // dlopen函數加載和連接共享庫filename
void* dlsym(void* handle, char* symbol);      // dlsym函數的輸入參數爲dlopen打開的共享庫句柄和符號名,返回符號的地址
int   dlclose(void* handle);  

 

7. 進程間通訊

(1) 管道、FIFO(命名管道)

管道:管道是一種半雙工的通訊方式,數據只能單向流動,並且只能在具備親緣關係的進程間使用。進程的親緣關係一般是指父子進程關係

FIFO:有名管道也是半雙工的通訊方式,可是它容許無親緣關係進程間的通訊。

(2) 信號(Signal)

信號用於通知接受進程有某種事件發生,除了用於進程間通訊外,進程還能夠發送信號給進程自己;linux除了支持Unix早期信號語義函數sigal外,還支持語義符合Posix.1標準的信號函數sigaction(實際上,該函數是基於BSD的,BSD爲了實現可靠信號機制,又可以統一對外接口,用sigaction函數從新實現了signal函數)

(3) 報文(Message)隊列(消息隊列)

消息隊列是消息的連接表,包括Posix消息隊列system V消息隊列。有足夠權限的進程能夠向隊列中添加消息,被賦予讀權限的進程則能夠讀走隊列中的消息。消息隊列克服了信號承載信息量少、管道只能承載無格式字節流以及緩衝區大小受限等缺點。

(4) 信號量(semaphore)

主要做爲進程間以及同一進程不一樣線程之間的同步手段,是一個計數器,用於多進程對共享數據對象的訪問

(5) 共享內存

共享內存就是映射一段能被其餘進程所訪問的內存,這段共享內存由一個進程建立,但多個進程均可以訪問

共享內存是最快的 IPC 方式(由於數據不須要在客戶進程和服務器進程之間複製)

使用mmap進行文件內存映射 和 匿名存儲映射(將fd設爲-1)

(6) socket套接字

套接字接口既能夠用於多機之間進程通訊,也能夠用於單機內部進程通訊

8. 進程同步原語

(1) 互斥鎖

(2) 條件變量

(3) 讀寫鎖

9.高效拷貝文件 

    

10.高效傳輸遠程文件

相關文章
相關標籤/搜索