linux+kernel+cmd+/dev/mem+memory,通过/dev/mem只能访问high_memory高端内存以下的内核线性地址空间...

通过/dev/mem只能访问高端内存以下的内核线性地址空间

《/proc/iomem和/proc /ioports对应的fops》

《浅析pc机上如何将vmlinuz- 2.6.31-14-generic解压出vmlinux》

fs_initcall(chr_dev_init);

chr_dev_init

==> register_chrdev(MEM_MAJOR,"mem",&memory_fops); // 建立/dev/mem字符节点

memory_open会根据inode的minor来定位具体的fops,

比如

1,1为mem_fops

1,2为kmem_fops

1,8为random_fops

等等(具体见下面的devlist[])

static const struct file_operations memory_fops = {

.open        = memory_open,    /* just a selector for the real open */

};

static const struct {

unsigned int        minor;

char            *name;

umode_t            mode;

const struct file_operations    *fops;

} devlist[] = { /* list of minor devices */

#ifdef CONFIG_DEVMEM

{1, "mem",     S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},

{2, "kmem",    S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},

#endif

{3, "null",    S_IRUGO | S_IWUGO,           &null_fops},

#ifdef CONFIG_DEVPORT

{4, "port",    S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},

#endif

{5, "zero",    S_IRUGO | S_IWUGO,           &zero_fops},

{7, "full",    S_IRUGO | S_IWUGO,           &full_fops},

{8, "random",  S_IRUGO | S_IWUSR,           &random_fops},

{9, "urandom", S_IRUGO | S_IWUSR,           &urandom_fops},

{11,"kmsg",    S_IRUGO | S_IWUSR,           &kmsg_fops},

#ifdef CONFIG_CRASH_DUMP

{12,"oldmem",    S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops},

#endif

};

static int memory_open(struct inode * inode, struct file * filp)

{

// 根据inode的minor子节点号定位具体功能驱动fops

switch (iminor(inode)) {

#ifdef CONFIG_DEVMEM

case 1:

filp->f_op = &mem_fops;

filp->f_mapping->backing_dev_info =

&directly_mappable_cdev_bdi;

break;

case 2:

filp->f_op = &kmem_fops;

filp->f_mapping->backing_dev_info =

&directly_mappable_cdev_bdi;

break;

#endif

case 3:

filp->f_op = &null_fops;

break;

#ifdef CONFIG_DEVPORT

case 4:

filp->f_op = &port_fops;

break;

#endif

case 5:

filp->f_mapping->backing_dev_info = &zero_bdi;

filp->f_op = &zero_fops;

break;

case 7:

filp->f_op = &full_fops;

break;

case 8:

filp->f_op = &random_fops;

break;

case 9:

filp->f_op = &urandom_fops;

break;

case 11:

filp->f_op = &kmsg_fops;

break;

#ifdef CONFIG_CRASH_DUMP

case 12:

filp->f_op = &oldmem_fops;

break;

#endif

default:

return -ENXIO;

}

if (filp->f_op && filp->f_op->open)

return filp->f_op->open(inode,filp);

return 0;

}

crw-rw-rw-  1 root root        1,   9 2010-05-16 09:18 urandom

crw-rw-rw-  1 root root        1,   3 2010-05-16 17:17 null

crw-rw-rw-  1 root root        1,   8 2010-05-16 17:17 random

crw-rw-rw-  1 root root        1,   5 2010-05-16 17:17 zero

brw-rw----  1 root disk        1,   9 2010-05-16 17:17 ram9

brw-rw----  1 root disk        1,   8 2010-05-16 17:17 ram8

brw-rw----  1 root disk        1,   7 2010-05-16 17:18 ram7

crw-r-----  1 root kmem        1,   4 2010-05-16 17:18 port

crw-rw----  1 root root        1,  12 2010-05-16 17:18 oldmem

crw-r-----  1 root kmem        1,   1 2010-05-16 17:18 mem

crw-rw----  1 root root        1,  11 2010-05-16 17:18 kmsg

crw-rw-rw-  1 root root        1,   7 2010-05-16 17:18 full

我们来看看/dev/mem都能读取到些什么

static const struct file_operations mem_fops = {

.llseek        = memory_lseek,

.read        = read_mem,

.write        = write_mem,

.mmap        = mmap_mem,

.open        = open_mem,

.get_unmapped_area = get_unmapped_area_mem,

};

/*

* This funcion reads the *physical* memory. The f_pos points directly to the

* memory location.

*/

static ssize_t read_mem(struct file * file, char __user * buf,

size_t count, loff_t *ppos)

{

unsigned long p = *ppos;

ssize_t read, sz;

char *ptr;

/*

// for arm

int valid_phys_addr_range(unsigned long addr, size_t size)

{

if (addr < PHYS_OFFSET) // 只能CONFIG_DRAM_BASE这个DDR物理内存首地址开始的空间~到高端内存之间内核线性地址

return 0;

if (addr + size > __pa(high_memory))

return 0;

return 1;

}

// for x86

static inline int valid_phys_addr_range(unsigned long addr, size_t count)

{

if (addr + count > __pa(high_memory)) // 只有高端内存以下的地址才能访问.

return 0;

return 1;

}

*/

if (!valid_phys_addr_range(p, count))

return -EFAULT;

read = 0;

#ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED

/* we don't have page 0 mapped on sparc and m68k.. */

if (p < PAGE_SIZE) {

sz = PAGE_SIZE - p;

if (sz > count)

sz = count;

if (sz > 0) {

if (clear_user(buf, sz))

return -EFAULT;

buf += sz;

p += sz;

count -= sz;

read += sz;

}

}

#endif

while (count > 0) {

/*

* Handle first page in case it's not aligned

*/

if (-p & (PAGE_SIZE - 1))

sz = -p & (PAGE_SIZE - 1);

else

sz = PAGE_SIZE;

sz = min_t(unsigned long, sz, count);

/*

* On ia64 if a page has been mapped somewhere as

* uncached, then it must also be accessed uncached

* by the kernel or data corruption may occur

*/

ptr = xlate_dev_mem_ptr(p); // 将物理地址p转化为内核线性虚拟地址

//        #define xlate_dev_mem_ptr(p)    __va(p)

//        #define __va(x)            ((void *)((unsigned long)(x)+PAGE_OFFSET))

//        #define PAGE_OFFSET        ((unsigned long)__PAGE_OFFSET)

//        #define __PAGE_OFFSET        _AC(CONFIG_PAGE_OFFSET, UL)

//        vim arch/x86/configs/i386_defconfig 我们获取的参数[luther.gliethttp]

//        CONFIG_PAGE_OFFSET=0xC0000000

if (copy_to_user(buf, ptr, sz))

return -EFAULT;

buf += sz;

p += sz;

count -= sz;

read += sz;

}

*ppos += read;

return read;

}

让我们实际演练演练,我们读取释放到内存中的kernel代码

tatic struct resource code_resource = {

.name    = "Kernel code",

.start    = 0,

.end    = 0,

.flags    = IORESOURCE_BUSY | IORESOURCE_MEM

};

start_kernel

==> setup_arch

code_resource.start = virt_to_phys(_text); // _text内核代码相对DDR物理内存的偏移量,也就是内核线性地址偏移量[luther.gliethttp]

code_resource.end = virt_to_phys(_etext)-1;

data_resource.start = virt_to_phys(_etext);

data_resource.end = virt_to_phys(_edata)-1;

bss_resource.start = virt_to_phys(&__bss_start);

bss_resource.end = virt_to_phys(&__bss_stop)-1;

subsys_initcall(request_standard_resources);

request_standard_resources

==> init_iomem_resources(&code_resource, &data_resource, &bss_resource);// 这样/proc/iomem就可以看到这里设置的信息了

request_resource(res, code_resource);

request_resource(res, data_resource);

request_resource(res, bss_resource);

==> request_resource(&iomem_resource, &video_ram_resource);

luther@gliethttp:~$ cat /proc/iomem

00000000-00001fff : System RAM

00002000-00005fff : reserved

00006000-0009dbff : System RAM

0009dc00-0009ffff : reserved

000a0000-000bffff : Video RAM area

000c0000-000cefff : Video ROM

000cf000-000d07ff : Adapter ROM

000d2000-000fffff : reserved

000f0000-000fffff : System ROM

00100000-5bf0ffff : System RAM

00100000-00575553 : Kernel code

00575554-0078d307 : Kernel data

0081a000-008a809f : Kernel bss

以上的

00100000-00575553 : Kernel code

就是kernel代码存储区了

0x00100000等于1048576

0x00575553等于5723475

luther@gliethttp:~$ sudo dd bs=1 skip=1048576 count=208 if=/dev/mem 2>/dev/null | xxd -g 1

0000000: f6 86 11 02 00 00 40 75 14 0f 01 15 22 8e 74 00  ......@u....".t.

0000010: b8 18 00 00 00 8e d8 8e c0 8e e0 8e e8 fc 31 c0  ..............1.

0000020: bf 00 a0 81 00 b9 a0 80 8a 00 29 f9 c1 e9 02 f3  ..........).....

0000030: ab bf c0 56 7c 00 b9 00 04 00 00 fc f3 a5 8b 35  ...V|..........5

0000040: e8 58 7c 00 21 f6 74 0c bf e0 2a 7c 00 b9 00 02  .X|.!.t...*|....

0000050: 00 00 f3 a5 66 81 3d c6 58 7c 00 07 02 72 1c a1  ....f.=.X|...r..

0000060: fc 58 7c 00 3d 03 00 00 00 73 0e 8b 04 85 80 22  .X|.=....s....."

0000070: 7c 00 2d 00 00 00 c0 ff e0 0f 0b bf 00 90 8a 00  |.-.............

0000080: ba 00 a0 81 00 b8 03 00 00 00 8d 4f 67 89 0a 89  ...........Og...

0000090: 8a 00 0c 00 00 83 c2 04 b9 00 04 00 00 ab 05 00  ................

00000a0: 10 00 00 e2 f8 bd 03 90 a4 00 39 e8 72 dc 81 c7  ..........9.r...

00000b0: 00 00 00 c0 89 3d 80 a5 74 00 c1 e8 0c a3 84 f0  .....=..t.......

00000c0: 81 00 b8 67 b0 81 00 a3 fc af 81 00 e9 6d 6b 46  ...g.........mkF

阅读(3595) | 评论(2) | 转发(1) |

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值