vm_area_structの仮想空間


Rev.2を表示中。最新版はこちら

プロセス作成は親プロセスのtask_structをcloneで複写し、execで動作プロセスのメモリを確保しロードします。この子プロセスが使用するメモリはtask_struct->mm_struct->vm_area_structに設定されます。これは仮想アドレスで/proc/プロセスID/mapsで表示されるものです。なお必要とされるまで実メモリーは確保されていません。このプロセスが使う仮想メモリを見てみようと思います。

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>

#define PROC_NAME "hogehoge"
 
static size_t proc_write( struct file *filp, const char __user *buff,
                       unsigned long len, void *data );
 
static struct proc_dir_entry *dirp;

static int proc_init_module(void)
{
        dirp = (struct proc_dir_entry *)
                create_proc_entry(PROC_NAME, 0666, (struct proc_dir_entry *) 0);
        if (dirp == 0)
                return(-EINVAL);
        dirp->write_proc = (write_proc_t *) proc_write;
        return 0;
}
 
static void proc_cleanup_module(void)
{
        remove_proc_entry(PROC_NAME, (struct proc_dir_entry *) 0);
}
 
static	void	do_vm_area(struct task_struct *process)
{
     struct mm_struct *mm;
     struct vm_area_struct *vm_area;
     int	 i;

     mm = process->mm;
     vm_area = mm->mmap;
     printk("vm_area %d:\n", mm->map_count);
     for (i = 0; i < mm->map_count; i++) {
         printk("%08x-%08x\n", vm_area->vm_start, vm_area->vm_end);
	 vm_area = vm_area->vm_next;
     } 
}

static size_t proc_write( struct file *filp, const char __user *buff,
                       unsigned long len, void *data )
{
     char	_buff[64];

     if (copy_from_user(_buff, buff, len )) {
   		return -EFAULT;
     }
    int	 mypid = simple_strtol(_buff, NULL, 0);

    struct task_struct *process;
    process = find_task_by_vpid(mypid);
    if (process) { 
        do_vm_area(process);
    }
    else {
        mypid = -1;
        printk("pid error:%d\n", mypid);
  	return -EFAULT;
    }
    return len;
}

module_init(proc_init_module);
module_exit(proc_cleanup_module);
動作確認
root@localhost test]# insmod test.ko
[root@localhost test]# ps
  PID TTY          TIME CMD
 1477 pts/0    00:00:01 bash
 2579 pts/0    00:00:00 ps
[root@localhost test]# echo 1477 > /proc/hogehoge
[root@localhost test]# dmesg
vm_area 33:
00294000-00295000
002e7000-002f2000
002f2000-002f3000
002f3000-002f4000
00428000-00440000
00440000-00441000
00441000-00442000
0079d000-007b3000
007b3000-007b6000
00ad0000-00af0000
00af1000-00af2000
00af2000-00af3000
00af5000-00c63000
00c63000-00c65000
00c65000-00c66000
00c66000-00c69000
00c96000-00c99000
00c99000-00c9a000
00c9a000-00c9b000
00f49000-00f4c000
00f4c000-00f4d000
00f4d000-00f4e000
08047000-080fb000
080fb000-08100000
08100000-08105000
09615000-09656000
b7dce000-b7dea000
b7dea000-b7dec000
b7dec000-b7df3000
b7df3000-b7ed7000
b7ed7000-b80d7000
b80d7000-b80d9000
bfc3e000-bfc53000
これがbashが使う仮想メモリー空間ということです。/proc/1477/mapsの内容とぴったり一致いたします。注目するところは最後がbfc53000までということです。c0000000はカーネル空間が使うアドレスで一般プロセスは使用できないからです。
[root@localhost test]# cat /proc/1477/maps
00294000-00295000 r-xp 00294000 00:00 0          [vdso]
002e7000-002f2000 r-xp 00000000 fd:00 409723     /lib/libnss_files-2.9.so
002f2000-002f3000 r--p 0000a000 fd:00 409723     /lib/libnss_files-2.9.so
002f3000-002f4000 rw-p 0000b000 fd:00 409723     /lib/libnss_files-2.9.so
00428000-00440000 r-xp 00000000 fd:00 386058     /usr/lib/gconv/libJIS.so
00440000-00441000 r--p 00017000 fd:00 386058     /usr/lib/gconv/libJIS.so
00441000-00442000 rw-p 00018000 fd:00 386058     /usr/lib/gconv/libJIS.so
0079d000-007b3000 r-xp 00000000 fd:00 465706     /lib/libtinfo.so.5.6
007b3000-007b6000 rw-p 00015000 fd:00 465706     /lib/libtinfo.so.5.6
00ad0000-00af0000 r-xp 00000000 fd:00 464272     /lib/ld-2.9.so
00af1000-00af2000 r--p 00020000 fd:00 464272     /lib/ld-2.9.so
00af2000-00af3000 rw-p 00021000 fd:00 464272     /lib/ld-2.9.so
00af5000-00c63000 r-xp 00000000 fd:00 464273     /lib/libc-2.9.so
00c63000-00c65000 r--p 0016e000 fd:00 464273     /lib/libc-2.9.so
00c65000-00c66000 rw-p 00170000 fd:00 464273     /lib/libc-2.9.so
00c66000-00c69000 rw-p 00c66000 00:00 0
00c96000-00c99000 r-xp 00000000 fd:00 464279     /lib/libdl-2.9.so
00c99000-00c9a000 r--p 00002000 fd:00 464279     /lib/libdl-2.9.so
00c9a000-00c9b000 rw-p 00003000 fd:00 464279     /lib/libdl-2.9.so
00f49000-00f4c000 r-xp 00000000 fd:00 385855     /usr/lib/gconv/EUC-JP.so
00f4c000-00f4d000 r--p 00002000 fd:00 385855     /usr/lib/gconv/EUC-JP.so
00f4d000-00f4e000 rw-p 00003000 fd:00 385855     /usr/lib/gconv/EUC-JP.so
08047000-080fb000 r-xp 00000000 fd:00 395533     /bin/bash
080fb000-08100000 rw-p 000b3000 fd:00 395533     /bin/bash
08100000-08105000 rw-p 08100000 00:00 0
09615000-09656000 rw-p 09615000 00:00 0          [heap]
b7dce000-b7dea000 r--p 00000000 fd:00 369496     /usr/share/locale/ja/LC_MESSAGES/libc.mo
b7dea000-b7dec000 rw-p b7dea000 00:00 0
b7dec000-b7df3000 r--s 00000000 fd:00 386077     /usr/lib/gconv/gconv-modules.cache
b7df3000-b7ed7000 r--p 034df000 fd:00 294949     /usr/lib/locale/locale-archive
b7ed7000-b80d7000 r--p 00000000 fd:00 294949     /usr/lib/locale/locale-archive
b80d7000-b80d9000 rw-p b80d7000 00:00 0
bfc3e000-bfc53000 rw-p bffeb000 00:00 0          [stack]
ちなみに小さいプロセスの仮想メモリー空間をみてみると、
#include "stdio.h"
main()
{
   while(1)
       sleep(100);
}

root@localhost test]# ./a.out &
[1] 2608
[root@localhost test]# echo 2608 > /proc/hogehoge
[root@localhost test]# dmesg
vm_area 12:
00a03000-00a04000
00ad0000-00af0000
00af1000-00af2000
00af2000-00af3000
00af5000-00c63000
00c63000-00c65000
00c65000-00c66000
00c66000-00c69000
08048000-08049000
08049000-0804a000
b809b000-b809d000
bfda4000-bfdb9000
使われるメモリー空間がもちろんbashより小さいです。最後はやはりc0000000を超えてはいませんね。各プロセスのメモリ空間はtask_struc->mm_struct->vm_area_structで管理されているということでした。

最終更新 2010/01/14 19:30:07 - north
(2010/01/14 19:20:59 作成)


検索

アクセス数
3574996
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。