日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux 进程原理内存,linux进程通信之共享内存原理(基于linux 1.2.13)

發(fā)布時(shí)間:2025/4/5 linux 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux 进程原理内存,linux进程通信之共享内存原理(基于linux 1.2.13) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1 有一個(gè)全局的結(jié)構(gòu)體數(shù)據(jù),每次需要一塊共享的內(nèi)存時(shí)(shmget),從里面取一個(gè)結(jié)構(gòu)體,記錄相關(guān)的信息。

struct shmid_ds {

// 權(quán)限相關(guān)

struct ipc_perm shm_perm;/* operation perms */

// 共享內(nèi)存的大小

intshm_segsz;/* size of segment (bytes) */

time_tshm_atime;/* last attach time */

time_tshm_dtime;/* last detach time */

time_tshm_ctime;/* last change time */

// 創(chuàng)建該結(jié)構(gòu)體的進(jìn)程

unsigned shortshm_cpid;/* pid of creator */

unsigned shortshm_lpid;/* pid of last operator */

// 當(dāng)前使用該共享內(nèi)存的進(jìn)程數(shù)

shortshm_nattch;/* no. of current attaches */

/* the following are private */

// 共享內(nèi)存的頁數(shù)

unsigned short shm_npages;/* size of segment (pages) */

// 指向共享的物理內(nèi)存的指針

unsigned long *shm_pages;/* array of ptrs to frames -> SHMMAX */

// 使用該共享內(nèi)存的進(jìn)程信息

struct vm_area_struct *attaches; /* descriptors for attaches */

}

2 調(diào)用shmat的時(shí)候傳入shmget返回的id。shmat根據(jù)id找到對應(yīng)的shmid_ds 結(jié)構(gòu)體。新建一個(gè)vm_area_struct結(jié)構(gòu)體。開始地址和結(jié)束地址根據(jù)shmid_ds 中的信息計(jì)算,也就是用戶申請的大小。接著把vm_area_struct插入進(jìn)程中管理vm_area_struct的avl樹。并且把一些上下文信息保存到頁表項(xiàng)。缺頁中斷的時(shí)候在shm_swap_in里使用。

shm_sgn = shmd->vm_pte + ((shmd->vm_offset >> PAGE_SHIFT) << SHM_IDX_SHIFT);

for (tmp = shmd->vm_start; tmp < shmd->vm_end; tmp += PAGE_SIZE,

shm_sgn += (1 << SHM_IDX_SHIFT)) {

page_dir = pgd_offset(shmd->vm_task,tmp);

page_middle = pmd_alloc(page_dir,tmp);

if (!page_middle)

return -ENOMEM;

page_table = pte_alloc(page_middle,tmp);

if (!page_table)

return -ENOMEM;

pte_val(*page_table) = shm_sgn;

}

3 進(jìn)程訪問共享內(nèi)存范圍中的地址時(shí),觸發(fā)缺頁中斷。

void do_no_page(struct vm_area_struct * vma, unsigned long address,

int write_access)

{

pte_t * page_table;

pte_t entry;

unsigned long page;

// 在進(jìn)程頁表里獲取address對應(yīng)的頁表項(xiàng)地址

page_table = get_empty_pgtable(vma->vm_task,address);

// 分配失敗則返回

if (!page_table)

return;

entry = *page_table;

// 已經(jīng)建立了虛擬地址到物理地址的映射,返回

if (pte_present(entry))

return;

// 還沒有建立映射

if (!pte_none(entry)) {

do_swap_page(vma, address, page_table, entry, write_access);

return;

}

......

}

在缺頁中斷中調(diào)用do_swap_page。

static inline void do_swap_page(struct vm_area_struct * vma, unsigned long address,

pte_t * page_table, pte_t entry, int write_access)

{

pte_t page;

if (!vma->vm_ops || !vma->vm_ops->swapin) {

swap_in(vma, page_table, pte_val(entry), write_access);

return;

}

page = vma->vm_ops->swapin(vma, address - vma->vm_start + vma->vm_offset, pte_val(entry));

if (pte_val(*page_table) != pte_val(entry)) {

free_page(pte_page(page));

return;

}

if (mem_map[MAP_NR(pte_page(page))] > 1 && !(vma->vm_flags & VM_SHARED))

page = pte_wrprotect(page);

++vma->vm_task->mm->rss;

++vma->vm_task->mm->maj_flt;

// 寫入物理地址

*page_table = page;

return;

}

其中vma->vm_ops->swapin對應(yīng)shm.c的shm_swap_in

pte_val(pte) = shp->shm_pages[idx];

// 還沒有分配物理內(nèi)存

if (!pte_present(pte)) {

// 分配物理內(nèi)存

unsigned long page = get_free_page(GFP_KERNEL);

...

// 記錄物理地址

shp->shm_pages[idx] = pte_val(pte);

}

mem_map[MAP_NR(pte_page(pte))]++;

return pte_modify(pte, shmd->vm_page_prot);

如果還沒分配物理地址則分配,否則直接范圍已經(jīng)分配的地址。do_swap_page函數(shù)的最后一句會把物理地址寫入進(jìn)程的頁表項(xiàng)。下次就不會缺頁中斷了。

同理,其他進(jìn)程共享該塊內(nèi)存的時(shí)候,如果訪問范圍內(nèi)的地址,處理過程是類似的。進(jìn)程訪問某一個(gè)地址,發(fā)生缺頁中斷,然后進(jìn)入do_swap_page函數(shù)處理,再到shm_swap_in。發(fā)現(xiàn)這時(shí)候共享內(nèi)存已經(jīng)映射了物理地址。最后改寫自己的頁表項(xiàng)。因?yàn)楦鱾€(gè)進(jìn)程都對應(yīng)同一塊內(nèi)存,所以操作的時(shí)候會互相感知,實(shí)現(xiàn)通信。

總結(jié)

以上是生活随笔為你收集整理的linux 进程原理内存,linux进程通信之共享内存原理(基于linux 1.2.13)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。