内核保留内存防止泄漏的机制_转

转自:http://blog.csdn.net/adaptiver/article/details/7425496

保留内存防止泄漏的机制:进程退出会调用
do_exit->exit_files->put_files_struct->close_files->filp_close->fput->__fput
在__fput里调用file->f_op->release(inode,
file)
而在保留内存对应release函数中,根据tgid做出判断,如果有对应tgid的保留内存块没有被主动释放,则认为是进程非正常退出,测试释放与tgid对应保留内存块。
但在android中调试发现,binder有时会在binder_deferred_func函数中调用put_files_struct来释放某个进程所属的文件资源,此时由于tgid属于binder所在workqueue所在的thread,保留内存检测不到该tgid,即使原来的进程有申请保留内存也不会被释放,从而出现泄漏。

内核中binder在binder_init中建立了一个workqueue

binder_deferred_workqueue
= create_singlethread_workqueue("binder");

void put_files_struct(struct files_struct *files)
{
 struct fdtable *fdt;

if
(atomic_dec_and_test(&files->count)) {
  close_files(files);
  /*
   * Free the fd and fdset arrays if we expanded them.
   * If the fdtable was embedded, pass files for freeing
   * at the end of the RCU grace period. Otherwise,
   * you can free files immediately.
   */
  rcu_read_lock();
  fdt = files_fdtable(files);
  if (fdt != &files->fdtab)
   kmem_cache_free(files_cachep, files);
  free_fdtable(fdt);
  rcu_read_unlock();
 }
}

static
void close_files(struct files_struct * files)
{
 int i, j;
 struct fdtable *fdt;

j
= 0;

/*
  * It is safe to dereference the fd table without RCU or
  * ->file_lock because this is the last reference to the
  * files structure.  But use RCU to shut RCU-lockdep up.
  */
 rcu_read_lock();
 fdt = files_fdtable(files);
 rcu_read_unlock();
 for (;;) {
  unsigned long set;
  i = j * __NFDBITS;
  if (i >= fdt->max_fds)
   break;
  set = fdt->open_fds->fds_bits[j++];
  while (set) {
   if (set & 1) {
    struct file * file = xchg(&fdt->fd[i], NULL);
    if (file) {
     filp_close(file, files);
     cond_resched();
    }
   }
   i++;
   set >>= 1;
  }
 }
}

int
filp_close(struct file *filp, fl_owner_t id)
{
 int retval = 0;

if
(!file_count(filp)) {
  printk(KERN_ERR "VFS: Close: file count is 0\n");
  return 0;
 }

if
(filp->f_op && filp->f_op->flush)
  retval = filp->f_op->flush(filp, id);

dnotify_flush(filp,
id);
 locks_remove_posix(filp, id);
 fput(filp);
 return retval;
}

void
fput(struct file *file)
{
 if (atomic_long_dec_and_test(&file->f_count))
  __fput(file);
}

static
void __fput(struct file *file)
{
 struct dentry *dentry = file->f_path.dentry;
 struct vfsmount *mnt = file->f_path.mnt;
 struct inode *inode = dentry->d_inode;

might_sleep();

fsnotify_close(file);
 /*
  * The function eventpoll_release() should be the first called
  * in the file cleanup chain.
  */
 eventpoll_release(file);
 locks_remove_flock(file);

if
(unlikely(file->f_flags & FASYNC)) {
  if (file->f_op && file->f_op->fasync)
   file->f_op->fasync(-1, file, 0);
 }
 if (file->f_op && file->f_op->release)
  file->f_op->release(inode, file);
 security_file_free(file);
 ima_file_free(file);
 if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev !=
NULL))
  cdev_put(inode->i_cdev);
 fops_put(file->f_op);
 put_pid(file->f_owner.pid);
 file_kill(file);
 if (file->f_mode & FMODE_WRITE)
  drop_file_write_access(file);
 file->f_path.dentry = NULL;
 file->f_path.mnt = NULL;
 file_free(file);
 dput(dentry);
 mntput(mnt);
}

static void binder_deferred_func(struct work_struct *work)
{
 struct binder_proc *proc;
 struct files_struct *files;

int
defer;
 do {
  mutex_lock(&binder_lock);
  mutex_lock(&binder_deferred_lock);
  if (!hlist_empty(&binder_deferred_list)) {
   proc = hlist_entry(binder_deferred_list.first,
     struct binder_proc, deferred_work_node);
   hlist_del_init(&proc->deferred_work_node);
   defer = proc->deferred_work;
   proc->deferred_work = 0;
  } else {
   proc = NULL;
   defer = 0;
  }
  mutex_unlock(&binder_deferred_lock);

files
= NULL;
  if (defer & BINDER_DEFERRED_PUT_FILES) {
   files = proc->files;
   if (files)
    proc->files = NULL;
  }

if
(defer & BINDER_DEFERRED_FLUSH)
   binder_deferred_flush(proc);

if
(defer & BINDER_DEFERRED_RELEASE)
   binder_deferred_release(proc); /* frees proc */

mutex_unlock(&binder_lock);
  if (files)
   put_files_struct(files);
 } while (proc);
}

时间: 2024-08-10 17:21:04

内核保留内存防止泄漏的机制_转的相关文章

内核对象&句柄&泄漏&检测

今天看到这个问题如何评价王垠的 <讨厌的 C# IDisposable 接口>? - 王垠(人物),答案被歪到windows 内核对象和句柄,答案中谈的太浅显而且有误.翻出陈年老文章(此文成于2012年,只在公司内部分享过),大部分内容来自Windows内核原理 1句柄和句柄泄露 在Windows编程过程中,很多时候我们都要和句柄打交道,比如窗体句柄,内核对象句柄,GDI句柄,Windows Multimedia库中的多种句柄等等,以及其他更多未曾使用过的句柄类型.句柄(Handle)是Win

Linux 内核的文件 Cache 管理机制介绍

Linux 内核的文件 Cache 管理机制介绍 文件 Cache 管理是 Linux 内核中一个很重要并且较难理解的组成部分.本文详细介绍了 Linux 内核中文件 Cache 管理的各个方面,希望能够对开发者理解相关代码有所帮助. http://www.ibm.com/developerworks/cn/linux/l-cache/ http://www.cnblogs.com/MYSQLZOUQI/p/4857437.html 1 前言 自从诞生以来,Linux 就被不断完善和普及,目前它

Android驱动学习-内部机制_回顾binder框架关键点

内部机制_回顾binder框架关键点server注册服务时, 对每个服务都提供不同的ptr/cookie,在驱动程序里对每个服务都构造一个binder_node, 它也含有ptr/cookie client使用服务前要先getService:会在驱动程序里对该服务构造一个binder_ref, binder_ref含有desc, node成员, desc是整数, node指向对应服务的binder_node 使用服务时, client构造数据,调用ioctl:数据里含有handle 驱动程序根据

Linux 内核中的 Device Mapper 机制

http://www.68idc.cn/help/server/linux/20141127133367.html 结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物 简介: 本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机制下,

内核通知链原理及机制

转载:http://blog.chinaunix.net/uid-25871104-id-3086446.html 一.概念: 大 多数内核子系统都是相互独立的,因此某个子系统可能对其它子系统产生的事件感兴趣.为了满足这个需求,也即是让某个子系统在发生某个事件时通知其它的子系 统,Linux内核提供了通知链的机制.通知链表只能够在内核的子系统之间使用,而不能够在内核与用户空间之间进行事件的通知.通知链表是一个函数链表, 链表上的每一个节点都注册了一个函数.当某个事情发生时,链表上所有节点对应的函

【转】深入Windows内核——C++中的消息机制

上节讲了消息的相关概念,本文将进一步聊聊C++中的消息机制. 从简单例子探析核心原理 在讲之前,我们先看一个简单例子:创建一个窗口和两个按钮,用来控制窗口的背景颜色.其效果 图1.效果图  Win32Test.h 1 #pragma once 2 3 #include <windows.h> 4 #include <atltypes.h> 5 #include <tchar.h> 6 7 //资源ID 8 #define ID_BUTTON_DRAW 1000 9 #d

[转] Linux 内核中的 Device Mapper 机制

本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机制下,用户可以很方便的根据自己的需要制定实现存储资源的管理策略,当前比较流行的 Linux 下的逻辑卷管理器如 LVM2(Linux Volume Manager 2 version).EVMS(Enterprise Volume Management System).dmraid(Device M

【UNIX】内核对进程的调度机制

(调度器)            对于一般进程,CPU的使用时间都是系统平均分配给每一个进程的,因此这种公平分享都从进程的角度出发的.   1) 调度时机:什么情况下,什么时候进行调度 2) 调度的策略:根据什么准则选取下一个进程 3) 调度方式:是"可剥夺"还是"不可剥夺",当正在运行的进程并不自愿放弃对从CPU 的使用权时,是否强制性的暂时剥夺其使用权,停止其运行而给其他进程一个机会,若 果是可剥夺,是否在任何情况下都可剥夺? 调度时机: 首先,自愿的调度(主动

Linux 内核的文件 Cache 管理机制介绍-ibm

https://www.ibm.com/developerworks/cn/linux/l-cache/ 1 前言 自从诞生以来,Linux 就被不断完善和普及,目前它已经成为主流通用操作系统之一,使用得非常广泛,它与 Windows.UNIX 一起占据了操作系统领域几乎所有的市场份额.特别是在高性能计算领域,Linux 已经成为一个占主导地位的操作系统,在2005年6月全球TOP500 计算机中,有 301 台部署的是 Linux 操作系统.因此,研究和使用 Linux 已经成为开发者的不可回