再談binder_mmap

以下是基于Android 7.0,在關(guān)鍵的地方寫了備注野揪》梅蓿看著備注就可以知道在講什么了。


關(guān)于用戶空間斯稳,內(nèi)核空間海铆,用戶空間地址,內(nèi)核地址挣惰,虛存游添,物理內(nèi)存系草,頁等操作系統(tǒng)的基礎(chǔ)知識就不展開了,需要自己事先去學(xué)習(xí)掌握唆涝。

首先要了解比較多的linux的知識了找都。

  • struct vm_area_struct:該結(jié)構(gòu)體表示用戶空間的內(nèi)存地址
  • struct vm_struct:該結(jié)構(gòu)體表示內(nèi)核空間的內(nèi)存地址
  • struct page:表示一個物理頁的映射
  • struct vm_struct * get_vm_area(unsigned long size, unsigned long flags):尋找一塊空間內(nèi)存區(qū)域,創(chuàng)建一個vm_struct結(jié)構(gòu)
  • void *kmalloc(size_t size, gfp_t flags):申請內(nèi)存廊酣,內(nèi)核調(diào)用
  • struct page * alloc_pages(gfp_t gfp_mask, unsigned int order):分配頁并且返回struct page實例
  • int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages):完成物理頁到虛擬內(nèi)存的映射
  • int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *):把分配的物理頁插到用戶vm能耻,可以理解為產(chǎn)生物理頁的映射

//在ProcessState中會調(diào)用mmap(),其中的fd是binder_open()后返回的亡驰,因此后面會根據(jù)binder注冊的file_operation調(diào)用到binder_mmap, 這里的vm_area_struct也是因為mmap()中的參數(shù)設(shè)置為NULL后由操作系統(tǒng)自動完成晓猛。
static int binder_mmap(struct file *filp, struct vm_area_struct *vm){
  struct vm_struct *area;
  //在binder_open的時候,binder_proc就會保存在private_data中
  struct binder_proc *proc = filp->private_data;
  struct binder_buffer *buffer;
  //映射的內(nèi)存不超過4MB
  if((vma->vm_end - vma->vm_start) > SZ_4M)
    vma->vm_end = vma->vm_start + SZ_4M;
  //根據(jù)用戶空間的vm_area_struct大小在內(nèi)核空間也尋找對應(yīng)大小的內(nèi)存vm_struct
  area = get_vma_area(vm->vm_end - vma->vm_start, VM_IOREMAP);
  //用binder_proc->buffer保存內(nèi)核空間映射的首地址
  proc->buffer = area->addr;
  //用binder_proc->user_buffer_offset保存用戶空間地址和內(nèi)核空間地址的差凡辱,這樣方便相互之間的轉(zhuǎn)換運算
  proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;
  //頁內(nèi)存對齊戒职,為pages分配內(nèi)存大小對應(yīng)的頁數(shù)量的結(jié)構(gòu)體page
  proc->pages = kzalloc(sizeof(proc->pages[0]) * ((vma->vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL);
  //分配并且映射物理內(nèi)存
  binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma);
  ...
}

//在本例中,proc表示當(dāng)前進程binder_proc數(shù)據(jù)結(jié)構(gòu)透乾,allocate為1洪燥,start為對應(yīng)的內(nèi)核空間的首地址,end為首地址后一個page頁的地址乳乌,vma對應(yīng)用戶空間的地址捧韵。
static int binder_update_page_range(struct binder_proc *proc, int allocate, void *start, void *end, struct vm_area_struct *vma){
  void *page_addr;
  unsigned long user_page_addr;
  struct page **page;
  struct mm_struct *mm;
  //本例只分配一個PAGE
  for(page_addr = start; page_addr < end; page_addr += PAGE_SIZE){
  struct page **page_array_ptr;
  //本次循環(huán)操作的是第N頁, 本例中是0
  page = &proc->pages[([page_addr - proc->buffer) / PAGE_SIZE];
  //分配實際的物理內(nèi)存
  *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEN | __GFP_ZERO);
  tmp_area.addr = page_addr;
  //這里我也不清楚汉操,為什么是2個PAGE_SIZE
  tmp_area.size = PAGE_SIZE + PAGE_SIZE;/*  guard page */
  page_array_ptr = page;
  //映射物理頁到內(nèi)核虛存
  map_vm_area(&tmp_area, PAGE_KERNEL, &page_array_ptr);
  //開始映射物理頁到用戶內(nèi)存
  user_page_addr = (uintptr_t)page_addr + proc->user_buffer_offset;
  vm_insert_page(vma, user_page_addr, page[0]);
  }
}

從上面可以看到再来,Binder利用mmap將用戶空間內(nèi)存和內(nèi)核空間內(nèi)存映射到同一塊物理內(nèi)存,這樣就避免了數(shù)據(jù)在空間空間和內(nèi)核空間的拷貝過程磷瘤,使得用戶空間/內(nèi)核空間在物理頁的數(shù)據(jù)修改在另一方直接可見芒篷。
同時物理頁也不是直接要多少分配多少,而是使用多少分配多少采缚。
當(dāng)然這里也涉及到了內(nèi)存不足時的交換空間针炉,缺頁錯誤等操作系統(tǒng)的知識,因此要提高計算機能力仰担,基礎(chǔ)知識不可謂不重要糊识。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末绩社,一起剝皮案震驚了整個濱河市摔蓝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌愉耙,老刑警劉巖贮尉,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異朴沿,居然都是意外死亡猜谚,警方通過查閱死者的電腦和手機败砂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來魏铅,“玉大人昌犹,你說我怎么就攤上這事±婪迹” “怎么了斜姥?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長沧竟。 經(jīng)常有香客問我铸敏,道長,這世上最難降的妖魔是什么悟泵? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任杈笔,我火速辦了婚禮,結(jié)果婚禮上糕非,老公的妹妹穿的比我還像新娘蒙具。我一直安慰自己,他們只是感情好峰弹,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布店量。 她就那樣靜靜地躺著,像睡著了一般鞠呈。 火紅的嫁衣襯著肌膚如雪融师。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天蚁吝,我揣著相機與錄音旱爆,去河邊找鬼。 笑死窘茁,一個胖子當(dāng)著我的面吹牛怀伦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播山林,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼房待,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了驼抹?” 一聲冷哼從身側(cè)響起桑孩,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎框冀,沒想到半個月后流椒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡明也,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年宣虾,在試婚紗的時候發(fā)現(xiàn)自己被綠了惯裕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡绣硝,死狀恐怖蜻势,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鹉胖,我是刑警寧澤咙边,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站次员,受9級特大地震影響败许,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜淑蔚,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一市殷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧刹衫,春花似錦醋寝、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至仓犬,卻和暖如春嗅绰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背搀继。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工窘面, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人叽躯。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓财边,卻偏偏與公主長得像,于是被迫代替她去往敵國和親点骑。 傳聞我的和親對象是個殘疾皇子酣难,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345