兩天實(shí)習(xí)筆記

1 任務(wù)一:實(shí)現(xiàn)固定內(nèi)存池

1.1 默認(rèn)內(nèi)存管理函數(shù)的不足

利用默認(rèn)的內(nèi)存管理函數(shù)new/deletemalloc/free在堆上分配和釋放內(nèi)存會(huì)有一些額外的開銷吞加。

如果應(yīng)用程序頻繁地在堆上分配和釋放內(nèi)存,則會(huì)導(dǎo)致性能的損失。并且會(huì)使系統(tǒng)中出現(xiàn)大量的內(nèi)存碎片,降低內(nèi)存的利用率。

而內(nèi)存池是在真正分配內(nèi)存之前按灶,先申請分配一定數(shù)量检访,大小相等(固定內(nèi)存池的情況)的內(nèi)存塊留作備用始鱼。當(dāng)有新的內(nèi)存需求的時(shí)候,便從內(nèi)存池分出一部分內(nèi)存塊脆贵。這樣做就減少了在堆上分配和釋放內(nèi)存的次數(shù)医清,提高內(nèi)存的利用率。

1.2 需要實(shí)現(xiàn)的效果

每次申請就分配一塊固定大小的內(nèi)存塊卖氨,返回其首地址会烙。在這個(gè)內(nèi)存塊需要回收時(shí),將其由內(nèi)存池來管理筒捺。在內(nèi)存池已經(jīng)分配完后持搜,再次接受到申請請求時(shí),要新開辟一塊內(nèi)存池焙矛。

1.3 思路

假設(shè)內(nèi)存池的內(nèi)存塊個(gè)數(shù)為BLOCK_SIZE,每一塊內(nèi)存塊大小為UNIT_SIZE個(gè)字節(jié)残腌。

一開始先用malloc函數(shù)申請BLOCK_SIZE * UNIT_SIZE 大小的內(nèi)存村斟,再將這塊內(nèi)存構(gòu)建成一個(gè)記錄當(dāng)前可供分配內(nèi)存塊的單向鏈表,鏈表每個(gè)元素的大小為UNIT_SIZE,如圖所示抛猫。

一開始的時(shí)候蟆盹,鏈表里的每個(gè)元素都是可供分配的。當(dāng)內(nèi)存申請時(shí)闺金,將鏈表的第一個(gè)分配出去逾滥,給申請對(duì)象返回該塊的首地址。在回收的時(shí)候败匹,將其添加回鏈表寨昙。當(dāng)分配滿了的時(shí)候,再申請一塊內(nèi)存來構(gòu)建單向鏈表掀亩。

因此整個(gè)過程就是構(gòu)建一個(gè)單向鏈表并維護(hù)該鏈表舔哪。

1.4 部分代碼

#define BLOCK_SIZE 5
#define UNIT_SIZE 31

// 數(shù)據(jù)結(jié)構(gòu)
typedef struct block {
    struct block * next;
} T;
// 可分配內(nèi)存塊的鏈表頭指針
T * avail = NULL;

// 構(gòu)建單向鏈表
T * init(){
    T * head = (T *)malloc(BLOCK_SIZE * UNIT_SIZE);
    T * p = head;
    for (int i = 0; i < BLOCK_SIZE - 1; i++){
        // 這里將T類型指針轉(zhuǎn)成char類型指針是確保指針移動(dòng)了UNIT_SIZE個(gè)字節(jié)數(shù)
        p->next = (T *)((char *)p + UNIT_SIZE);
        p = p->next;
    }
    p->next = NULL;
    return head;
}
// 申請一塊內(nèi)存塊
void * apply(){
    T * p;
    if (avail == NULL){
        avail = init();
        printf("generate new pool\n");
    }

    p = avail;
    avail = avail->next;
    // 返回?zé)o類型指針 void *
    return (void *)p;
}
// 回收
void recycle(void * temp){
    T * t = (T*)temp;
    t->next = avail;
    avail = t;
}

1.5 收獲

總體下來思路還是挺清晰的,實(shí)現(xiàn)過程出現(xiàn)的很多問題都是對(duì)C語言不熟悉特別是指針的移動(dòng)槽棍。出現(xiàn)的疑問有指針的加1操作捉蚤、結(jié)構(gòu)體大小計(jì)算以及字節(jié)對(duì)齊的原因等。

1.6 相關(guān)鏈接

2 任務(wù)二:使用存儲(chǔ)映射I/O(mmap函數(shù))修改文本文件

2.1 mmap和常規(guī)文件操作的區(qū)別

常規(guī)文件系統(tǒng)操作(調(diào)用read/fread等類函數(shù))中缆巧,函數(shù)的調(diào)用過程:
1、進(jìn)程發(fā)起讀文件請求豌拙。
2陕悬、內(nèi)核通過查找進(jìn)程文件符表,定位到內(nèi)核已打開文件集上的文件信息姆蘸,從而找到此文件的inode墩莫。
3芙委、inode在address_space上查找要請求的文件頁是否已經(jīng)緩存在頁緩存中。如果存在狂秦,則直接返回這片文件頁的內(nèi)容灌侣。
4、如果不存在裂问,則通過inode定位到文件磁盤地址侧啼,將數(shù)據(jù)從磁盤復(fù)制到頁緩存。之后再次發(fā)起讀頁面過程堪簿,進(jìn)而將頁緩存中的數(shù)據(jù)發(fā)給用戶進(jìn)程痊乾。

常規(guī)文件操作為了提高讀寫效率和保護(hù)磁盤,使用了頁緩存機(jī)制椭更。一個(gè)進(jìn)程讀文件需要兩次拷貝(文件頁到頁緩存哪审,頁緩存到進(jìn)程對(duì)應(yīng)的地址空間),寫操作也是一樣虑瀑。(?)

而使用mmap操作文件中湿滓,創(chuàng)建新的虛擬內(nèi)存區(qū)域建立文件磁盤地址和虛擬內(nèi)存區(qū)域映射這兩步,沒有任何文件拷貝操作舌狗。

兩者的區(qū)別如圖


最直觀的感覺就是使用mmap映射叽奥,多個(gè)進(jìn)程共享了文件的同一個(gè)副本。

2.2 mmap內(nèi)存映射的實(shí)現(xiàn)過程

(一)進(jìn)程啟動(dòng)映射過程痛侍,并在該進(jìn)程的虛擬地址空間中為映射創(chuàng)建虛擬映射區(qū)域
(二)調(diào)用內(nèi)核空間的系統(tǒng)調(diào)用函數(shù)mmap朝氓,實(shí)現(xiàn)文件物理地址和進(jìn)程虛擬地址的一一映射關(guān)系
(三)進(jìn)程發(fā)起對(duì)這片映射空間的訪問,引發(fā)缺頁異常主届,實(shí)現(xiàn)文件內(nèi)容到物理內(nèi)存(主存)的拷貝

該引用的文章鏈接為 https://www.cnblogs.com/huxiao-tee/p/4660352.html

2.3 需要實(shí)現(xiàn)的效果

新建文本文件赵哲,使用mmap來添加文字并保存。

2.4 代碼

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h> 
#include <unistd.h>
#define FILE_MODE   (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) 
int main(){
    // 待添加的文本
    char * src = "testtesttest";
    int out= open("./a", O_RDWR | O_CREAT | O_TRUNC,FILE_MODE);

    int input_size = strlen(src);
    // 下面兩步是為了將文件大小設(shè)置成待添加文本的大小君丁。映射的時(shí)候才會(huì)做到一一映射
    if(lseek(out, input_size - 1, SEEK_SET) == -1){//將光標(biāo)移到第input_size - 1的位置
        printf("lseek error\n");
    }
    if (write(out, "", 1) != 1){//寫入字節(jié)為1的空字符
        printf("write error\n");
    }

    void * dest = mmap(0, input_size, PROT_READ | PROT_WRITE,MAP_SHARED, out,0);
    if(dest == MAP_FAILED){
        printf("mmap error\n");
    }
    // 將fdin指向的區(qū)域拷貝到dst指向的區(qū)域誓竿,拷貝input_size個(gè)字節(jié)
    memcpy(dest, src, input_size);
    return 0;
}

2.5 收獲

這份代碼是按照書中例子敲的,但是自己不熟悉c語言的常用函數(shù)例如lseek,write等導(dǎo)致誤解了函數(shù)的作用谈截。所以說不懂的函數(shù)筷屡,參數(shù)就要多查,不要亂猜簸喂。把解決一個(gè)問題需要的前提條件和準(zhǔn)備工作構(gòu)思好毙死,然后去檢查案例代碼是否完成了這些工作!S黯扼倘!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子再菊,更是在濱河造成了極大的恐慌爪喘,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纠拔,死亡現(xiàn)場離奇詭異秉剑,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)稠诲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門侦鹏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人臀叙,你說我怎么就攤上這事略水。” “怎么了劝萤?”我有些...
    開封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵渊涝,是天一觀的道長。 經(jīng)常有香客問我床嫌,道長驶赏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任既鞠,我火速辦了婚禮,結(jié)果婚禮上盖文,老公的妹妹穿的比我還像新娘嘱蛋。我一直安慰自己,他們只是感情好五续,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開白布洒敏。 她就那樣靜靜地躺著,像睡著了一般疙驾。 火紅的嫁衣襯著肌膚如雪凶伙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天它碎,我揣著相機(jī)與錄音函荣,去河邊找鬼。 笑死扳肛,一個(gè)胖子當(dāng)著我的面吹牛傻挂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播挖息,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼金拒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了套腹?” 一聲冷哼從身側(cè)響起绪抛,我...
    開封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤资铡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后幢码,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體笤休,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年蛤育,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宛官。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡瓦糕,死狀恐怖底洗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情咕娄,我是刑警寧澤亥揖,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站圣勒,受9級(jí)特大地震影響费变,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜圣贸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一挚歧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吁峻,春花似錦滑负、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至啄骇,卻和暖如春痴鳄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缸夹。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來泰國打工痪寻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人虽惭。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓槽华,卻偏偏與公主長得像,于是被迫代替她去往敵國和親趟妥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子猫态,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 一、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運(yùn)行的地址不確定 關(guān)于...
    SeanCST閱讀 7,818評(píng)論 0 27
  • 2016年國慶假期終于把此書過完勇凭,整理筆記和體會(huì)于此。 關(guān)于書名 書名源于俄羅斯的演員斯坦尼斯拉夫斯基創(chuàng)作的《演員...
    李劍飛的簡書閱讀 7,251評(píng)論 2 65
  • 搬運(yùn)自乓逶客網(wǎng)大神總結(jié) extern關(guān)鍵字 extern修飾變量是個(gè)聲明虾标,此變量/函數(shù)是在別處定義的,要在此處引用 ...
    leon4ever閱讀 3,668評(píng)論 0 9
  • 對(duì)于一個(gè)畢業(yè)照都沒有好好拍過的人灌砖,緬懷大學(xué)這件事也是在畢業(yè)一年后才悟到一點(diǎn)點(diǎn)璧函。 轉(zhuǎn)眼到了屬于學(xué)弟學(xué)妹們的畢業(yè)季,找...
    桃子sweet1閱讀 241評(píng)論 0 0
  • 要保證每天的休息時(shí)間充足才行基显,否則疲勞會(huì)分散注意力蘸吓,容易走神,導(dǎo)致狀況頻出撩幽。意志力是會(huì)慢慢被消耗掉的库继,要懂得調(diào)節(jié)和...
    榴蓮酥君閱讀 192評(píng)論 0 0