Messages in this thread Patch in this message | | | From | cd_smith@ou ... | Date | Wed, 28 Jul 1999 20:38:53 -0500 (CDT) | Subject | [PATCH] Uniquely identifying memory usage |
| |
Hi,
Here is a really short patch that uses the proc filesystem to tell user space what processes are share virtual memory. I may have missed something, but I don't think that there's currently any way to find out if two processes are sharing memory or just happen to be using exactly the same amount of memory. The patch adds a /proc/*/mm_id that provides a unique ID for memory usage.
The patch has one known issue that really ought to be solved if it becomes actually a part of the kernel: It uses the process ID of the first process to use a mm_struct as the ID for that struct. This means that under the following scenario, the scheme fails:
1. Process A is forked 2. A clones B with CLONE_MM 3. A exits 4. Process C is forked, and reuses A's pid.
Now B and C will share an mm_id despite the fact that they are not even related to each other. I didn't fix this because first of all, doing so would require some way to keep track of free mm_ids, which might require some extra kernel memory. (Actually, if we use a bit mask it requires 64 bytes for the default NR_TASKS == 512, but I just thought of this a few seconds ago).
Second, this situation won't ever actually happen under the only situation most people use CLONE_MM, which is for LinuxThreads. That doesn't excuse the BUG, but it does mean that the patch is usable by most people until the bug gets fixed.
Comments are welcome. Since this is actually my first kernel patch ever, is it considered good enough to just post a small patch like this to the list, or should I put it on my web page somewhere? I assume the list archives are good enough?
Chris Smith <cd_smith@ou.edu>
diff -Nru linux-old/fs/proc/array.c linux/fs/proc/array.c --- linux-old/fs/proc/array.c Sat Jul 3 14:04:12 1999 +++ linux/fs/proc/array.c Wed Jul 28 19:17:25 1999 @@ -1052,6 +1052,23 @@ size, resident, share, trs, lrs, drs, dt); } +static int get_mm_id(int pid, char * buffer) +{ + struct task_struct *tsk; + int mm_id = 0; + + read_lock(&tasklist_lock); + tsk = find_task_by_pid(pid); + read_unlock(&tasklist_lock); + + if (!tsk) + return 0; + if (tsk->mm && tsk->mm != &init_mm) + mm_id = tsk->mm->mm_id; + + return sprintf(buffer,"%d\n", mm_id); +} + /* * The way we support synthetic files > 4K * - without storing their contents in some buffer and @@ -1416,6 +1433,8 @@ return get_stat(pid, page); case PROC_PID_STATM: return get_statm(pid, page); + case PROC_PID_MM_ID: + return get_mm_id(pid, page); #ifdef __SMP__ case PROC_PID_CPU: return get_pidcpu(pid, page); diff -Nru linux-old/fs/proc/base.c linux/fs/proc/base.c --- linux-old/fs/proc/base.c Sat Jun 26 14:04:39 1999 +++ linux/fs/proc/base.c Wed Jul 28 19:18:34 1999 @@ -159,6 +159,12 @@ 0, &proc_arraylong_inode_operations, NULL, proc_pid_fill_inode, }; +static struct proc_dir_entry proc_pid_mm_id = { + PROC_PID_MM_ID, 5, "mm_id", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations, + NULL, proc_pid_fill_inode, +}; #if CONFIG_AP1000 static struct proc_dir_entry proc_pid_ringbuf = { @@ -194,6 +200,7 @@ proc_register(&proc_pid, &proc_pid_stat); proc_register(&proc_pid, &proc_pid_statm); proc_register(&proc_pid, &proc_pid_maps); + proc_register(&proc_pid, &proc_pid_mm_id); #ifdef __SMP__ proc_register(&proc_pid, &proc_pid_cpu); #endif diff -Nru linux-old/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- linux-old/include/linux/proc_fs.h Wed Jul 7 11:21:05 1999 +++ linux/include/linux/proc_fs.h Wed Jul 28 19:33:44 1999 @@ -70,6 +70,7 @@ PROC_PID_STAT, PROC_PID_STATM, PROC_PID_MAPS, + PROC_PID_MM_ID, #if CONFIG_AP1000 PROC_PID_RINGBUF, #endif diff -Nru linux-old/include/linux/sched.h linux/include/linux/sched.h --- linux-old/include/linux/sched.h Wed Jul 7 11:20:45 1999 +++ linux/include/linux/sched.h Wed Jul 28 19:22:20 1999 @@ -187,6 +187,7 @@ * part of Linux does not know about any segments. */ void * segments; + pid_t mm_id; }; #define INIT_MM(name) { \ @@ -200,7 +201,8 @@ 0, 0, 0, \ 0, 0, 0, 0, \ 0, 0, 0, \ - 0, 0, 0, 0, NULL } + 0, 0, 0, 0, NULL, \ + 0 } struct signal_struct { atomic_t count; diff -Nru linux-old/kernel/fork.c linux/kernel/fork.c --- linux-old/kernel/fork.c Mon Jul 5 22:34:31 1999 +++ linux/kernel/fork.c Wed Jul 28 18:50:07 1999 @@ -382,6 +382,7 @@ if (!mm) goto fail_nomem; + mm->mm_id = tsk->pid; tsk->mm = mm; copy_segments(nr, tsk, mm); retval = new_page_tables(tsk);
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |