千家信息网

Linux的共享内存与tmpfs文件系统是什么

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,本篇内容介绍了"Linux的共享内存与tmpfs文件系统是什么"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学
千家信息网最后更新 2026年11月03日Linux的共享内存与tmpfs文件系统是什么

本篇内容介绍了"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       #include       #include       #include       #include       #include       #include       #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       #include       #include       #include       #include       #include       #include       #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   #include   #include   #include   #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 –> 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 –> 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文件系统是什么"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

内存 文件 内核 系统 大小 物理 限制 实际 数据 用户 空间 分配 影响 普通 两个 作用 内容 实际上 更多 知识 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技工作委员会毛军 互联网与科技发展 广州互联网科技公司 互联网科技作文 互联网科技公司官网 易通互联网络科技有限公司 科技互联网公司logo 互联网 科技服务平台 银川新华互联网科技职业技术培训学校图片 互联网还是高科技吗 黑科技闪耀互联网之光 崇明区互联网教育科技售后服务 哈尔滨屹滨互联网科技有限公司 深圳育鹏互联网科技有限公司招聘 互联网科技快讯热点 广州有谷有贝互联网科技有限公司 上海乐五互联网科技有限公司 西安左小互联网科技有限公司 唐山双旺合互联网科技产业园 科技互联网企业在行动 科技互联网企业 互联网科技财经 礼当家互联网科技 贷财互联网科技 郑州华宇互联网科技 哈尔滨新华互联网科技 昊天互联网科技有限公司 深圳市优智互联网科技有限公司 互联网金融科技公司的优势 华人运通互联网科技公司
0