91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Linux的共享內存與tmpfs文件系統是什么

發布時間:2021-12-24 15:15:35 來源:億速云 閱讀:129 作者:iii 欄目:系統運維

本篇內容介紹了“Linux的共享內存與tmpfs文件系統是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

前言

共享內存主要用于進程間通信,Linux有兩種共享內存(Shared Memory)機制:

另外,在Linux中不得不提一下內存映射(也可用于進程間通信):

System  V共享內存歷史悠久,使用也很廣范,很多類Unix系統都支持。一般來說,我們在寫程序時也通常使用***種。這里不再討論如何使用它們,關于POSIX共享內存的詳細介紹可以參考這里1,這里2。

** 講到那么多,那么問題來了,共享內存與tmpfs有什么關系? **

POSIX共享內存是基于tmpfs來實現的。實際上,更進一步,不僅PSM(POSIX shared  memory),而且SSM(System V shared memory)在內核也是基于tmpfs實現的。

tmpfs介紹

tmpfs主要有兩個作用:

(1)用于SYSV共享內存,還有匿名內存映射;這部分由內核管理,用戶不可見;

(2)用于POSIX共享內存,由用戶負責mount,而且一般mount到/dev/shm;依賴于CONFIG_TMPFS;

到這里,我們可以了解,SSM與PSM之間的區別,也明白了/dev/shm的作用。

下面我們來做一些測試:

測試

我們將/dev/shm的tmpfs設置為64M:

# mount -size=64M -o remount /dev/shm# df -lh  Filesystem Size Used Avail Use% Mounted on  tmpfs 64M 0 64M 0% /dev/shm

SYSV共享內存的***大小為32M:

# cat /proc/sys/kernel/shmmax  33554432

(1)創建65M的system V共享內存失敗:

# ipcmk -M 68157440  ipcmk: create share memory failed: Invalid argument

這是正常的。

(2)將shmmax調整為65M

# echo 68157440 > /proc/sys/kernel/shmmax# cat /proc/sys/kernel/shmmax  68157440# ipcmk -M 68157440  Shared memory id: 0# ipcs -m  ------ Shared Memory Segments --------  key shmid owner perms bytes nattch status  0xef46b249 0 root 644 68157440 0

可以看到system v共享內存的大小并不受/dev/shm的影響。

(3)創建POSIX共享內存

點擊(此處)折疊或打開

    /*gcc -o shmopen shmopen.c -lrt*/#include <unistd.h>      #include <fcntl.h>      #include <sys/stat.h>      #include <sys/types.h>      #include <sys/mman.h>      #include <stdio.h>      #include <stdlib.h>      #define MAP_SIZE 68157440      int main(int argc, char *argv[])      {          int fd;          void* result;          fd = shm_open("/shm1", O_RDWR|O_CREAT, 0644);          if(fd < 0){              printf("shm_open failed\n");              exit(1);          }          return 0;      }   # ./shmopen# ls -lh /dev/shm/shm1  -rw-r--r-- 1 root root 65M Mar  3 06:19 /dev/shm/shm1

僅管/dev/shm只有64M,但創建65M的POSIX SM也可以成功。

(4)向POSIX SM寫數據

點擊(此處)折疊或打開

    /*gcc -o shmwrite shmwrite.c -lrt*/#include <unistd.h>      #include <fcntl.h>      #include <sys/stat.h>      #include <sys/types.h>      #include <sys/mman.h>      #include <stdio.h>      #include <stdlib.h>      #define MAP_SIZE 68157440      int main(int argc, char *argv[])      {          int fd;          void* result;          fd = shm_open("/shm1", O_RDWR|O_CREAT, 0644);          if(fd < 0){               printf("shm_open failed\n");               exit(1);          }          if (ftruncate(fd, MAP_SIZE) < 0){              printf("ftruncate failed\n");              exit(1);          }          result = mmap(NULL, MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);          if(result == MAP_FAILED){              printf("mapped failed\n");              exit(1);          }          /* ... operate result pointer */          printf("memset\n");          memset(result, 0, MAP_SIZE);          //shm_unlink("/shm1");          return 0;      }   # ./shmwrite  memset  Bus error

可以看到,寫65M的數據會報Bus error錯誤。

但是,卻可以在/dev/shm創建新的文件:

# ls -lh /dev/shm/ -lh  總用量 64M  -rw-r--r-- 1 root root 65M 3月 3 15:23 shm1  -rw-r--r-- 1 root root 65M 3月 3 15:24 shm2  這很正常,ls顯示的是inode->size。  # stat /dev/shm/shm2  File: "/dev/shm/shm2"  Size: 68157440 Blocks: 0 IO Block: 4096 普通文件  Device: 10h/16d Inode: 217177 Links: 1  Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)  Access: 2015-03-03 15:24:28.025985167 +0800  Modify: 2015-03-03 15:24:28.025985167 +0800  Change: 2015-03-03 15:24:28.025985167 +0800

(5)向SYS V共享內存寫數據

將System V共享內存的***值調整為65M(/dev/shm仍然為64M)。

# cat /proc/sys/kernel/shmmax  68157440

點擊(此處)折疊或打開

/*gcc -o shmv shmv.c*/#include <sys/ipc.h>  #include <sys/shm.h>  #include <sys/types.h>  #include <unistd.h>  #define MAP_SIZE 68157440  int main(int argc, char** argv){  int shm_id,i;  key_t key;  char temp;  char *p_map;  char* name = "/dev/shm/shm3";  key = ftok(name,0);  if(key==-1)  perror("ftok error");  shm_id=shmget(key,MAP_SIZE,IPC_CREAT);  if(shm_id==-1)  {  perror("shmget error");  return;  }  p_map=(char*)shmat(shm_id,NULL,0);  memset(p_map, 0, MAP_SIZE);  if(shmdt(p_map)==-1)  perror(" detach error ");  }  #./shmv

卻可以正常執行。

(7)結論

雖然System V與POSIX共享內存都是通過tmpfs實現,但是受的限制卻不相同。也就是說/proc/sys/kernel/shmmax只會影響SYS  V共享內存,/dev/shm只會影響Posix共享內存。實際上,System  V與Posix共享內存本來就是使用的兩個不同的tmpfs實例(instance)。

內核分析

內核在初始化時,會自動mount一個tmpfs文件系統,掛載為shm_mnt:

點擊(此處)折疊或打開

//mm/shmem.cstatic struct file_system_type   shmem_fs_type = {      .owner = THIS_MODULE,     .name = "tmpfs",      .get_sb = shmem_get_sb,      .kill_sb = kill_litter_super,  };   int __init shmem_init(void) {      ...      error = register_filesystem(&shmem_fs_type);      if (error)       {          printk(KERN_ERR "Could not register tmpfs\n");          goto out2;      }      ///掛載tmpfs(用于SYS V)       shm_mnt = vfs_kern_mount(&shmem_fs_type, MS_NOUSER,shmem_fs_type.name, NULL);

/dev/shm的mount與普通文件mount的流程類似,不再討論。但是,值得注意的是,/dev/shm默認的大小為當前物理內存的1/2:

shmem_get_sb &ndash;> shmem_fill_super

點擊(此處)折疊或打開

//mem/shmem.c  int shmem_fill_super(struct super_block *sb, void *data, int silent)  {      ...  #ifdef CONFIG_TMPFS   /*  * Per default we only allow half of the physical ram per  * tmpfs instance, limiting inodes to one per page of lowmem;  * but the internal instance is left unlimited.  */      if (!(sb->s_flags & MS_NOUSER)) {///內核會設置MS_NOUSER           sbinfo->max_blocks = shmem_default_max_blocks();          sbinfo->max_inodes = shmem_default_max_inodes();          if (shmem_parse_options(data, sbinfo, false)) {              err = -EINVAL;              goto failed;          }      }      sb->s_export_op = &shmem_export_ops;  #else  ...   #ifdef CONFIG_TMPFS  static unsigned long shmem_default_max_blocks(void) {      return totalram_pages / 2;  }

可以看到:由于內核在mount tmpfs時,指定了MS_NOUSER,所以該tmpfs沒有大小限制,因此,SYS  V共享內存能夠使用的內存空間只受/proc/sys/kernel/shmmax限制;而用戶通過掛載的/dev/shm,默認為物理內存的1/2。

注意CONFIG_TMPFS.

另外,在/dev/shm創建文件走VFS接口,而SYS V與匿名映射卻是通過shmem_file_setup實現:

SIGBUS

當應用訪問共享內存對應的地址空間,如果對應的物理PAGE還沒有分配,就會調用fault方法,分配失敗,就會返回OOM或者BIGBUS錯誤:

點擊(此處)折疊或打開

static const struct vm_operations_struct shmem_vm_ops = {      .fault = shmem_fault,  #ifdef CONFIG_NUMA       .set_policy = shmem_set_policy,      .get_policy = shmem_get_policy,  #endif  };   static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)  {      struct inode *inode = vma->vm_file->f_path.dentry->d_inode;      int error;      int ret = VM_FAULT_LOCKED;      error = shmem_getpage(inode, vmf->pgoff, &vmf->page, SGP_CACHE, &ret);      if (error)          return ((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS);      return ret;  }   shmem_getpage &ndash;> shmem_getpage_gfp:  /*   * shmem_getpage_gfp - find page in cache, or get from swap, or allocate   *   * If we allocate a new one we do not mark it dirty. That's up to the   * vm. If we swap it in we mark it dirty since we also free the swap   * entry since a page cannot live in both the swap and page cache   */  static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,  struct page **pagep, enum sgp_type sgp, gfp_t gfp, int *fault_type)   {      ...      if (sbinfo->max_blocks) { ///dev/shm會有該值           if (percpu_counter_compare(&sbinfo->used_blocks,sbinfo->max_blocks) >= 0) {              error = -ENOSPC;              goto unacct;          }      percpu_counter_inc(&sbinfo->used_blocks);      }      //分配一個物理PAGE      page = shmem_alloc_page(gfp, info, index);      if (!page) {          error = -ENOMEM;          goto decused;      }      SetPageSwapBacked(page);      __set_page_locked(page);      error = mem_cgroup_cache_charge(page, current->mm,gfp & GFP_RECLAIM_MASK); ///mem_cgroup檢查  if (!error)      error = shmem_add_to_page_cache(page, mapping, index, gfp, NULL);

共享內存與CGROUP

目前,共享內存的空間計算在***個訪問共享內存的group

POSIX共享內存與Docker

目前Docker將/dev/shm限制為64M,卻沒有提供參數,這種做法比較糟糕。如果應用使用大內存的POSIX共享內存,必然會導致問題。

“Linux的共享內存與tmpfs文件系統是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

长武县| 贵溪市| 儋州市| 苏州市| 呈贡县| 兰坪| 滦南县| 清苑县| 石家庄市| 会宁县| 富蕴县| 紫阳县| 余姚市| 荥经县| 池州市| 略阳县| 禄劝| 金山区| 秭归县| 门头沟区| 正阳县| 洪雅县| 饶平县| 十堰市| 珠海市| 安远县| 靖宇县| 怀来县| 合作市| 色达县| 南平市| 白城市| 历史| 华坪县| 遂昌县| 通化县| 大埔区| 简阳市| 安新县| 驻马店市| 抚顺市|