linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] A new entry for /proc
@ 2005-01-06 21:11 Mauricio Lin
  2005-01-07  4:23 ` Andrew Morton
  0 siblings, 1 reply; 38+ messages in thread
From: Mauricio Lin @ 2005-01-06 21:11 UTC (permalink / raw)
  To: linux-kernel

Hi all,

Here is a new entry developed for /proc that prints for each process
memory area (VMA) the size of rss. The maps from original kernel is
able to present the virtual size for each vma, but not the physical
size (rss). This entry can provide an additional information for tools
that analyze the memory consumption. You can know the physical memory
size of each library used by a process and also the executable file.

Take a look the output:
# cat /proc/877/smaps
08048000-08132000 r-xp  /usr/bin/xmms
Size:     936 kB
Rss:     788 kB
08132000-0813a000 rw-p  /usr/bin/xmms
Size:      32 kB
Rss:      32 kB
0813a000-081dd000 rw-p 
Size:     652 kB
Rss:     616 kB
b67b5000-b67b6000 ---p 
Size:       4 kB
Rss:       0 kB
b67b6000-b6fb5000 rwxp 
Size:    8188 kB
Rss:       4 kB
b6fb5000-b6fbc000 r-xp  /usr/lib/xmms/Visualization/libsanalyzer.so
Size:      28 kB
Rss:       8 kB
b6fbc000-b6fbd000 rw-p  /usr/lib/xmms/Visualization/libsanalyzer.so
Size:       4 kB
Rss:       4 kB
b6fbd000-b6fc1000 r-xp  /usr/X11R6/lib/libXxf86vm.so.1.0
Size:      16 kB
Rss:       8 kB
b6fc1000-b6fc2000 rw-p  /usr/X11R6/lib/libXxf86vm.so.1.0
Size:       4 kB
Rss:       4 kB
b6fc2000-b702d000 r-xp  /usr/X11R6/lib/libGL.so.1.2
Size:     428 kB
Rss:     372 kB
b702d000-b7032000 rw-p  /usr/X11R6/lib/libGL.so.1.2
Size:      20 kB
Rss:      20 kB
b7032000-b7033000 rw-p 
Size:       4 kB
Rss:       0 kB
...

Here is the patch:

diff -rcNP linux-2.6.10/fs/proc/base.c linux-2.6.10-smaps/fs/proc/base.c
*** linux-2.6.10/fs/proc/base.c	Fri Dec 24 17:35:00 2004
--- linux-2.6.10-smaps/fs/proc/base.c	Thu Jan  6 15:47:37 2005
***************
*** 11,16 ****
--- 11,18 ----
   *  go into icache. We cache the reference to task_struct upon lookup too.
   *  Eventually it should become a filesystem in its own. We don't use the
   *  rest of procfs anymore.
+  *  2004, 10LE INdT <mauricio.lin@indt.org.br>. A new entry smaps
included in /proc.
+  *  It shows the size of rss for each memory area.
   */
  
  #include <asm/uaccess.h>
***************
*** 60,65 ****
--- 62,68 ----
  	PROC_TGID_MAPS,
  	PROC_TGID_MOUNTS,
  	PROC_TGID_WCHAN,
+ 	PROC_TGID_SMAPS,
  #ifdef CONFIG_SCHEDSTATS
  	PROC_TGID_SCHEDSTAT,
  #endif
***************
*** 86,91 ****
--- 89,95 ----
  	PROC_TID_MAPS,
  	PROC_TID_MOUNTS,
  	PROC_TID_WCHAN,
+ 	PROC_TID_SMAPS,
  #ifdef CONFIG_SCHEDSTATS
  	PROC_TID_SCHEDSTAT,
  #endif
***************
*** 123,128 ****
--- 127,133 ----
  	E(PROC_TGID_ROOT,      "root",    S_IFLNK|S_IRWXUGO),
  	E(PROC_TGID_EXE,       "exe",     S_IFLNK|S_IRWXUGO),
  	E(PROC_TGID_MOUNTS,    "mounts",  S_IFREG|S_IRUGO),
+ 	E(PROC_TGID_SMAPS,     "smaps",   S_IFREG|S_IRUGO),
  #ifdef CONFIG_SECURITY
  	E(PROC_TGID_ATTR,      "attr",    S_IFDIR|S_IRUGO|S_IXUGO),
  #endif
***************
*** 148,153 ****
--- 153,159 ----
  	E(PROC_TID_ROOT,       "root",    S_IFLNK|S_IRWXUGO),
  	E(PROC_TID_EXE,        "exe",     S_IFLNK|S_IRWXUGO),
  	E(PROC_TID_MOUNTS,     "mounts",  S_IFREG|S_IRUGO),
+ 	E(PROC_TID_SMAPS,      "smaps",   S_IFREG|S_IRUGO),
  #ifdef CONFIG_SECURITY
  	E(PROC_TID_ATTR,       "attr",    S_IFDIR|S_IRUGO|S_IXUGO),
  #endif
***************
*** 497,502 ****
--- 503,527 ----
  	.release	= seq_release,
  };
  
+ extern struct seq_operations proc_pid_smaps_op;
+ static int smaps_open(struct inode *inode, struct file *file)
+ {
+ 	struct task_struct *task = proc_task(inode);
+ 	int ret = seq_open(file, &proc_pid_smaps_op);
+ 	if (!ret) {
+ 		struct seq_file *m = file->private_data;
+ 		m->private = task;
+ 	}
+ 	return ret;
+ }
+ 
+ static struct file_operations proc_smaps_operations = {
+ 	.open		= smaps_open,
+ 	.read		= seq_read,
+ 	.llseek		= seq_lseek,
+ 	.release	= seq_release,
+ };
+ 
  extern struct seq_operations mounts_op;
  static int mounts_open(struct inode *inode, struct file *file)
  {
***************
*** 1341,1346 ****
--- 1366,1376 ----
  		case PROC_TGID_MOUNTS:
  			inode->i_fop = &proc_mounts_operations;
  			break;
+ 		case PROC_TID_SMAPS:
+ 		case PROC_TGID_SMAPS:
+ 			inode->i_fop = &proc_smaps_operations;
+ 			break;
+ 
  #ifdef CONFIG_SECURITY
  		case PROC_TID_ATTR:
  			inode->i_nlink = 2;
diff -rcNP linux-2.6.10/fs/proc/task_mmu.c linux-2.6.10-smaps/fs/proc/task_mmu.c
*** linux-2.6.10/fs/proc/task_mmu.c	Fri Dec 24 17:34:01 2004
--- linux-2.6.10-smaps/fs/proc/task_mmu.c	Wed Dec 29 10:21:04 2004
***************
*** 81,86 ****
--- 81,159 ----
  	return 0;
  }
  
+ static void resident_mem_size(struct mm_struct *mm, unsigned long
start_address,
+ 			unsigned long end_address, unsigned long *size) {
+ 	pgd_t *pgd;
+ 	pmd_t *pmd;
+ 	pte_t *ptep, pte;
+ 	unsigned long page;
+ 
+ 	for (page = start_address; page < end_address; page += PAGE_SIZE) {
+ 		pgd = pgd_offset(mm, page);
+ 		if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
+ 			continue;
+ 
+ 		pmd = pmd_offset(pgd, page);
+ 
+ 		if (pmd_none(*pmd))
+ 			continue;
+ 
+ 		if (unlikely(pmd_bad(*pmd)))
+ 			continue;
+ 
+ 		if (pmd_present(*pmd)) {
+ 			ptep = pte_offset_map(pmd, page);
+ 			if (!ptep)
+ 				continue;
+ 			pte = *ptep;
+ 			pte_unmap(ptep);
+ 			if (pte_present(pte)) {
+ 				*size += PAGE_SIZE;
+ 			}
+ 		}
+ 	}
+ }
+ 
+ static int show_smap(struct seq_file *m, void *v)
+ {
+ 	struct vm_area_struct *map = v;
+ 	struct file *file = map->vm_file;
+ 	int flags = map->vm_flags;
+ 	int len;
+ 	struct mm_struct *mm = map->vm_mm;
+ 	unsigned long rss = 0;
+ 	unsigned long vma_len = (map->vm_end - map->vm_start) >> 10;
+ 	
+ 	if (mm) {
+ 		resident_mem_size(mm, map->vm_start, map->vm_end, &rss);
+ 	}
+ 
+ 	seq_printf(m, "%08lx-%08lx %c%c%c%c %n",
+ 			map->vm_start,
+ 			map->vm_end,
+ 			flags & VM_READ ? 'r' : '-',
+ 			flags & VM_WRITE ? 'w' : '-',
+ 			flags & VM_EXEC ? 'x' : '-',
+ 			flags & VM_MAYSHARE ? 's' : 'p',
+ 			&len);
+ 
+ 	if (map->vm_file) {
+ 		len = sizeof(void*) * 6 - len;
+ 		if (len < 1)
+ 			len = 1;
+ 		seq_printf(m, "%*c", len, ' ');
+ 		seq_path(m, file->f_vfsmnt, file->f_dentry, " \t\n\\");
+ 	}
+ 	seq_putc(m, '\n');
+ 	
+ 	seq_printf(m, "Size:%8lu kB\n"
+ 			"Rss:%8lu kB\n",
+ 			vma_len,
+ 			rss >> 10);
+ 	
+ 	return 0;
+ }
+ 
  static void *m_start(struct seq_file *m, loff_t *pos)
  {
  	struct task_struct *task = m->private;
***************
*** 134,136 ****
--- 207,216 ----
  	.stop	= m_stop,
  	.show	= show_map
  };
+ 
+ struct seq_operations proc_pid_smaps_op = {
+ 	.start	= m_start,
+ 	.next	= m_next,
+ 	.stop	= m_stop,
+ 	.show	= show_smap
+ };

Suggestions are welcome.

BR,

Mauricio Lin.

^ permalink raw reply	[flat|nested] 38+ messages in thread
* Re: [PATCH] A new entry for /proc
@ 2005-02-24 18:56 Albert Cahalan
  2005-03-01 14:32 ` Mauricio Lin
  0 siblings, 1 reply; 38+ messages in thread
From: Albert Cahalan @ 2005-02-24 18:56 UTC (permalink / raw)
  To: linux-kernel mailing list; +Cc: Andrew Morton OSDL

[quoting various people...]

> Here is a new entry developed for /proc that prints for each process
> memory area (VMA) the size of rss. The maps from original kernel is   
> able to present the virtual size for each vma, but not the physical   
> size (rss). This entry can provide an additional information for tools
> that analyze the memory consumption. You can know the physical memory
> size of each library used by a process and also the executable file.
>
> Take a look the output:
> # cat /proc/877/smaps 
> 08048000-08132000 r-xp  /usr/bin/xmms
> Size:     936 kB
> Rss:     788 kB 
> 08132000-0813a000 rw-p  /usr/bin/xmms
> Size:      32 kB
> Rss:      32 kB 
> 0813a000-081dd000 rw-p
> Size:     652 kB
> Rss:     616 kB

The most important thing about a /proc file format is that it has
a documented means of being extended in the future. Without such
documentation, it is impossible to write a reliable parser.

The "Name: value" stuff is rather slow. Right now procps (ps, top, etc.)
is using a perfect hash function to parse the /proc/*/status files.
("man gperf") This is just plain gross, but needed for decent performance.

Extending the /proc/*/maps file might be possible. It is commonly used
by debuggers I think, so you'd better at least verify that gdb is OK.
The procps "pmap" tool uses it too. To satisfy the procps parser:

a. no more than 31 flags
b. no '/' prior to the filename
c. nothing after the filename
d. no new fields inserted prior to the inode number

> If there were a use for it, that use might want to distinguish between
> the "shared rss" of pagecache pages from a file, and the "anon rss" of
> private pages copied from file or originally zero - would need to get
> the struct page and check PageAnon.  And might want to count swap
> entries too.  Hard to say without real uses in mind.
...
> It's a mixture of two different styles, the /proc/<pid>/maps
> many-hex-fields one-vma-per-line style and the /proc/meminfo
> one-decimal-kB-per-line style.  I think it would be better following
> the /proc/<pid>/maps style, but replacing the major,minor,ino fields
> by size and rss (anon_rss? swap?) fields (decimal kB? I suppose so).

The more info the better. See the pmap "-x" option, currently missing
some data that the kernel does not supply. There are numerous other     
pmap options that are completely unimplemented because of the lack of   
info. See the Solaris 10 man page for pmap, available on Sun's web site.



^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2005-04-30  1:25 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-01-06 21:11 [PATCH] A new entry for /proc Mauricio Lin
2005-01-07  4:23 ` Andrew Morton
2005-01-07 12:30   ` Roger Luethi
2005-01-08 20:20   ` Hugh Dickins
2005-01-08 21:47     ` Alan Cox
2005-01-10  9:21     ` Edjard Souza Mota
2005-01-10 15:23     ` Mauricio Lin
2005-02-22 13:13     ` Mauricio Lin
2005-02-24  8:31       ` Mauricio Lin
2005-02-24  9:09         ` Andrew Morton
2005-02-24 11:43           ` Mauricio Lin
2005-02-24 11:52             ` Andrew Morton
2005-02-25 15:14               ` Mauricio Lin
2005-02-28  9:43                 ` Mauricio Lin
2005-02-28  9:56                   ` Mauricio Lin
2005-02-28 20:41                     ` Hugh Dickins
2005-03-01  8:08                       ` Mauricio Lin
2005-03-01 14:17                         ` Mauricio Lin
2005-03-01 15:44                           ` Mauricio Lin
2005-03-02 12:20                             ` Mauricio Lin
2005-03-02 19:07                               ` Hugh Dickins
2005-03-03  7:25                                 ` Mauricio Lin
2005-03-03 12:48                                   ` Hugh Dickins
2005-03-03 14:23                                     ` Mauricio Lin
2005-01-10 14:35   ` Mauricio Lin
2005-01-14 22:46   ` Mauricio Lin
     [not found]     ` <20050114154209.6b712e55.akpm@osdl.org>
2005-01-17 18:03       ` Mauricio Lin
2005-01-17 19:02         ` Mauricio Lin
2005-01-17 17:30           ` Marcelo Tosatti
2005-01-17 21:27             ` Mauricio Lin
2005-01-17 21:35             ` William Lee Irwin III
2005-01-18  1:07               ` Nick Piggin
2005-01-19 12:59                 ` Nick Piggin
2005-01-24 22:14             ` Mauricio Lin
2005-04-29 18:36   ` Mauricio Lin
2005-04-30  1:25     ` Andrew Morton
2005-02-24 18:56 Albert Cahalan
2005-03-01 14:32 ` Mauricio Lin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).