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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

为什么/dev/shm中看不到shmget创建的内存文件及其它(下)

發(fā)布時(shí)間:2023/12/19 综合教程 39 生活家
生活随笔 收集整理的這篇文章主要介紹了 为什么/dev/shm中看不到shmget创建的内存文件及其它(下) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、如何看到sysV IPC shm文件名
1、file_system_type.get_sb修改
正如上篇所說,在用戶態(tài)無法看到可shm文件的名稱,不同的掛載點(diǎn)使用不同的dentry,而對(duì)于tmpfs文件,它的readdir的系統(tǒng)實(shí)現(xiàn)就是通過dcache_readdir函數(shù)來實(shí)現(xiàn)的,但是這個(gè)dentry的不同本質(zhì)上是由于
static int shmem_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
return get_sb_nodev(fs_type, flags, data, shmem_fill_super, mnt);
}
函數(shù)實(shí)現(xiàn)的,它會(huì)為每次掛載分配一個(gè)新的super_block結(jié)構(gòu),這個(gè)實(shí)現(xiàn)在get_sb_nodev中。作為對(duì)比我們,proc文件無論掛接在哪里,它看到的內(nèi)容都是一致的,所以可以以proc文件系統(tǒng)為例進(jìn)行修改,將這里的shmem_get_sub修改為如下形式
static int shmem_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
returnget_sb_single(fs_type, flags, data, shmem_fill_super, mnt);
}
這里注意到一個(gè)細(xì)節(jié),那就是sys_mount--->>>do_new_mount--->>do_kern_mount---->>>vfs_kern_mount--->>alloc_vfsmnt這個(gè)調(diào)用連中,vfsmount結(jié)構(gòu)是始終分配的,每次掛載都將會(huì)分配一個(gè)獨(dú)立的vfsmount結(jié)構(gòu),而所謂的single_sb,它只是說它的super_block是唯一的,進(jìn)一步說,這些vfsmount結(jié)構(gòu)中的mnt_root指針指向的位置是相同的。然后在path_lookup--->>>do_path_lookup--->>>link_path_walk---->>__link_path_walk--->>>do_lookup--->>>__follow_mount--->>lookup_mnt
這條路徑中將會(huì)返回這個(gè)vfsmount結(jié)構(gòu)的mnt_root作為新的文件夾(這一點(diǎn)在__follow_mount函數(shù)中的path->dentry = dget(mounted->mnt_root)完成)。
2、修改內(nèi)核掛接屬性
進(jìn)行上面修改之后,在用戶態(tài)通過
mount -t tmpfs none myshm
掛載,會(huì)提示參數(shù)錯(cuò)誤,這個(gè)地方時(shí)內(nèi)核在掛載內(nèi)核使用的shm_mnt的時(shí)候加了選項(xiàng)限制不能從用戶態(tài)掛載,所以此處也要做相應(yīng)修改。
linux-2.6.21mmshmem.c
static int __init init_tmpfs(void)
shm_mnt = vfs_kern_mount(&tmpfs_fs_type,MS_NOUSER,刪除該選項(xiàng),從而可以在用戶態(tài)掛載文件
tmpfs_fs_type.name, NULL);
3、修改dentry DCACHE_UNHASHED 屬性
做上面修改之后,用戶態(tài)可以掛載文件,在不同掛接點(diǎn)中看到的內(nèi)容一致,也就是說不同掛接點(diǎn)均可以看到,但是遺憾的時(shí)候通過shmget隱形創(chuàng)建的文件依然不可見,此時(shí)再次跟蹤,發(fā)現(xiàn)問題所在。在
linux-2.6.21mmshmem.c
struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
{
……
dentry = d_alloc(root, &this);
……
}
在d_alloc中創(chuàng)建的dentry項(xiàng)剛開始是出于刪除狀態(tài)(也就是DCACHE_UNHASED狀態(tài)),這個(gè)狀態(tài)也就是內(nèi)存文件的特征,它可以在內(nèi)存中的dentry結(jié)構(gòu)引用計(jì)數(shù)降低為零的時(shí)候從內(nèi)存中直接釋放,這也正是tmpfs中"tmp"屬性的體現(xiàn)。偏偏在執(zhí)行文件夾內(nèi)容顯示的dcache_readdir中:
for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
struct dentry *next;
next = list_entry(p, struct dentry, d_u.d_child);
if (d_unhashed(next)|| !next->d_inode)這里對(duì)于出于DCACHE_UNHASHED狀態(tài)的目錄項(xiàng)不予顯示,所以內(nèi)核中掛接點(diǎn)依然無法看到
continue;
對(duì)于通常的實(shí)體文件系統(tǒng)(例如ext2,),它們?cè)谡{(diào)用d_alloc之后一般要通過d_splice_alias--->>>d_rehash--->>_d_rehash
static void __d_rehash(struct dentry * entry, struct hlist_head *list)
{

entry->d_flags &= ~DCACHE_UNHASHED;
hlist_add_head_rcu(&entry->d_hash, list);
}
在這里通過該操作來清除對(duì)于文件的刪除狀態(tài),從而讓它在內(nèi)存中生效。由于shmem_file_setup并沒有代勞執(zhí)行這個(gè)操作,所以我們就不按套路出牌,強(qiáng)制在shmem_setup_file函數(shù)中,新分配的dentry結(jié)構(gòu)中清除這個(gè)標(biāo)志。
經(jīng)過這么一番折騰,用戶態(tài)終于可以看到內(nèi)核創(chuàng)建的文件了,由于我是通過IPC_PRIVATE創(chuàng)建了多個(gè)共享內(nèi)存,所以在該文件夾下可以看到很多個(gè)同名的文件,它們都是“SYSV00000000”,這也說明一個(gè)問題,那就是并非所有的文件系統(tǒng)都不能在同一個(gè)文件夾下有重名文件,文件系統(tǒng)的限制只是為了避免二義性。
二、為什么do_shmat中每次會(huì)分配一個(gè)struct file結(jié)構(gòu)
可以看到,在newseg函數(shù)中,已經(jīng)通過shmem_setup_file分配了一個(gè)struct file結(jié)構(gòu),但是在每次執(zhí)行shmat的時(shí)候還會(huì)再次分配一個(gè)結(jié)構(gòu),這個(gè)結(jié)構(gòu)是不是冗余的呢?后來我看了一下2.4.37的內(nèi)核版本,在sys_shmat調(diào)用中的確是沒有分配這個(gè)結(jié)構(gòu)的,使用的就是newseg中創(chuàng)建的那個(gè)file結(jié)構(gòu)。所以為什么在新的版本中必須要再次分配還真是不太容易理解。但是看一下兩個(gè)文件的差別,可以看新的版本的shm_file_operations定義為
static const struct file_operations shm_file_operations = {
.mmap = shm_mmap,
.fsync = shm_fsync,
.release = shm_release,
.get_unmapped_area = shm_get_unmapped_area,
};
而2.4版本中對(duì)應(yīng)內(nèi)容為
static struct file_operations shm_file_operations = {
mmap: shm_mmap
};
可見新的版本中定義了一些新的file_operations接口。并且其中還有一個(gè)判斷使用到了這個(gè)結(jié)構(gòu)
int is_file_shm_hugepages(struct file *file)
{
int ret = 0;

if (file->f_op == &shm_file_operations) {
struct shm_file_data *sfd;
sfd = shm_file_data(file);
ret = is_file_hugepages(sfd->file);
}
return ret;
}
所以猜測(cè)這里是為了支持hugepages功能而添加的一個(gè)功能?不管如何,這個(gè)都是一個(gè)猜測(cè)了,沒有實(shí)作,也算是一個(gè)疑案吧,知道的同學(xué)請(qǐng)指教。
三、為什么要定義shm_vm_ops結(jié)構(gòu)中的open/close接口
這個(gè)是一個(gè)比較特殊的例子,因?yàn)樗趍map的時(shí)候定義了vm_operations_struct結(jié)構(gòu)中的open和close接口,這兩個(gè)接口的調(diào)用位置分別為
copy_process-->>copy_mm--->>>dup_mm--->>>dup_mmap
if (tmp->vm_ops && tmp->vm_ops->open)
tmp->vm_ops->open(tmp);

do_exit---->>>exit_mm---->>>mmput--->>exit_mmap--->>remove_vma
if (vma->vm_ops && vma->vm_ops->close)
vma->vm_ops->close(vma);
在通過shmget創(chuàng)建一個(gè)tmpfs文件之后,這個(gè)文件不論是否執(zhí)行shmat,這個(gè)文件是始終存在的,刪除這個(gè)文件的方法就是通過shmctl RMID的方法來刪除這個(gè)文件。但是這里有一個(gè)比較奇特但是又比較典型的策略,就是當(dāng)一個(gè)資源被多個(gè)實(shí)例共享時(shí),如果該資源被刪除,那么刪除并不馬上執(zhí)行,而只是減少引用計(jì)數(shù),只有當(dāng)計(jì)數(shù)值降低為零的時(shí)候才真正執(zhí)行刪除操作。這一點(diǎn)在文件的刪除上比較常見和典型。
現(xiàn)在假設(shè)說一個(gè)shm被通過shmctl刪除,內(nèi)核只是對(duì)這個(gè)文件做了一個(gè)標(biāo)記SHM_DEST屬性,而真正的觸發(fā)則只有框架來支持,也就是說這里只能以“回調(diào)”的形式注冊(cè)給系統(tǒng),從而在引用附加和移除的時(shí)候得到通知并進(jìn)行計(jì)算,進(jìn)而根據(jù)計(jì)算結(jié)果做出可能的刪除操作
四、shm/shmem文件何時(shí)釋放
1、shm文件
這里所說的shm文件是在shmat中通過file = get_empty_filp();分配的struct file結(jié)構(gòu)。它的示范同樣是由mmap框架來完成。在前一節(jié)說vm_operations_struct的open/close函數(shù)的附近,各自都有對(duì)vma區(qū)間是否有文件映射的判斷,如果是文件映射,會(huì)分別遞增和遞減這個(gè)文件的引用次數(shù)。
dup_mmap函數(shù)中為
if (file) {
struct inode *inode = file->f_path.dentry->d_inode;
get_file(file);
remove_vma函數(shù)中
if (vma->vm_file)
fput(vma->vm_file);
然后在
fput--->>__fput
if (file->f_op && file->f_op->release)
file->f_op->release(inode, file);
在其中執(zhí)行自己私有數(shù)據(jù)的釋放。
2、shmem文件的釋放
這里所說內(nèi)容為newseg中創(chuàng)建的文件,它的釋放是通過
shm_destroy--->>>fput--->>>__fput--->>>dput--->>>dentry_iput--->>>iput--->>>generic_delete_inode--->>>shmem_delete_inode
釋放,由于該文件是內(nèi)存文件,所以inode dentry這些內(nèi)存結(jié)構(gòu)被刪除之后就無法恢復(fù),也意味著它們從系統(tǒng)中消失了。




總結(jié)

以上是生活随笔為你收集整理的为什么/dev/shm中看不到shmget创建的内存文件及其它(下)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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