为特定地址分配值

时间:2011-03-23 01:56:12

标签: memory-address

这是一个面试问题,我在一本书中看到了采访,后来在接受采访时。

问题是

  

如何为地址(比如0)指定价值(比如0x12345678)。

我最好的尝试这个问题(在面试后很长一段时间)

  

地址是一个可以存储在指针中的数字,我们可以通过指针为地址分配一个值,其值是地址,如:

         int* p = 0x12345678;
         *p = 0;
  

但是,在具有内存管理的系统上不可能,因为该程序没有特定地址的权限。

     

根据我自己的经验,这种操作唯一有效的时间是在没有任何操作系统的8086芯片上进行的实验,而那时我使用的语言是汇编。

请帮我纠正,改进并完成我的答案。感谢。

4 个答案:

答案 0 :(得分:3)

您的代码是正确的,但如果操作系统将0x12345678定义为只读,则可能会在运行时崩溃。

虽然“常规”操作系统会这样做,但“较轻”操作系统不会这样做。

你想写一个内核空间黑客程序来做它。

如果你想看看我解决了它的问题:


1)构建这个模块(example.ko):

#include <linux/module.h>
#include <linux/fs.h>       /* for file_operations  */
#include <linux/uaccess.h>  /* copy_from & copy_to  */

char*   g_value=0;
size_t  size =0; 

int driver_open(struct inode *inode, struct file *filp)
{
    printk("open driver");
    return 0;
}

int driver_write(struct file*,          /*ignored*/
                const char __user *umem,/*source in user-space's address*/
                size_t size,            /*max size to be writen*/
                loff_t*)                /*offset - ignored*/
{
    unsigned long ret = 0;

    g_value = (char*) kmalloc(size, GFP_KERNEL);

    if (!g_value)
    {
        printk("ERROR:allocation failure\n");
        return -ENOMEM;
    }

    ret = copy_from_user(g_value,   /*destination*/
                        umem,       /*source*/
                        size);      /*size*/

    if (ret<0)
    {
        printk("ERROR:copy failure\n");
        return -EACCES;
    }

    return g_size = size;;
}

int driver_read(struct file*,       /*ignored*/
                 char __user *umem, /*destination in user-space's address*/
                 size_t size,       /*max size to be read*/
                 loff_t*)           /*offset - ignored*/
{

    /*  don't use copy_to_user(umem,    &value, size)!!
        we want to do exectly what it is made to protect from */

    int i = ((g_size>size)?size:g_size)-1; /*MIN(g_size,size)-1*/
    for (; i>=0; --i)
    {
        umem[i]=g_value[i]; /*can be done more effectively, thats not the point*/
    }

    return size;
}

int driver_close(struct inode *inode, struct file *filp)
{
    if (g_value)
        free(g_value);
    g_value = 0;
    printk("close driver");
    return 0;
}

/***interface***/

struct file_operations driver_ops = {
    open: driver_open,
    write: driver_write,
    read:  driver_read,
    release: driver_close
};

/***implementation***/

static int g_driver_fd = 0;

static void driver_cleanup(void) 
{
    printk("ERROR:driver exit\n");
    unregister_chrdev(g_driver_fd, "driver");
}

static int driver_init(void)
{

    printk("driver init\n");
    g_driver_fd =  register_chrdev(0,"ROM-bypass", &driver_ops);
    if (g_driver_fd<0)
    {
        printk("ERROR:failed to register char driver\n");
        return -1;
    }
    return 0;
}

module_init(driver_init);
module_exit(driver_cleanup);

/***documentation***/

MODULE_DESCRIPTION("write on OS's \"read only\" segment");
MODULE_AUTHOR("Elkana Bronstein");
MODULE_LICENSE("GPL");

2)将其添加到内核模块:

$insmod example.ko

3)在列表中找到模块的“主要”:

$cat /proc/devices

4)使节点与设备关联:

$mknod /dev/rom_bypass  c <major> <minor>

'c'用于字符设备,'minor'可以是0-255

中的任何一个

5)将代码中的设备用作文件:

int main()
{

    int fd;
    int value = 0;

    fd = open("/dev/rom_bypass",O_RDWR);    
    if (fd<0)
    {
        fprintf(stderr,"open failed");
        return -1;
    }

    /*write the desirable value into the device's buffer*/
    write(fd,&value,sizeof(value));
    /*read the device's buffer into the desirable object - without checking*/
    read(fd,0x12345678,sizeof(value));

    close(fd);
}

答案 1 :(得分:1)

(几乎)不可能知道哪些内存位置可以写入。

您可以通过使用malloc()函数让操作系统为您提供可用的地址,然后使用free()释放该位置。

另一种方法是使用堆栈内存。只需定义一个变量int * p = 0; &amp; p将为您提供此地点的地址。

如果您尝试将值分配给不可用的位置,则最终可能会出现分段错误错误。

希望这有帮助!

答案 2 :(得分:0)

即使在具有内存管理的系统中,这种事情绝对是可能的,如果指针位于当前进程的可访问空间之外,它就会出错,但这就是应该发生的事情。如果没有,则设置值,然后继续。除此之外,你的榜样对我来说似乎很好。

答案 3 :(得分:-1)

也许答案是没有答案,因为在具有内存管理的系统中这是不可能的。

在没有内存管理的系统中,我会直接尝试使用汇编代码。

希望有所帮助