【问题标题】:Does any operating system allow an application programmer to create pointers out of thunks?是否有任何操作系统允许应用程序程序员从 thunk 中创建指针?
【发布时间】:2012-08-24 22:21:48
【问题描述】:

许多操作系统允许一个内存映射文件,并懒惰地读取它们。如果操作系统可以做到这一点,那么它就有能力从 thunk 中创建常规指针。

任何操作系统都允许应用程序程序员从他自己的 thunk 中创建指针吗?

我知道操作系统在一定程度上已经支持此功能,因为可以创建管道,将其映射到内存中,并将进程连接到管道以完成我正在谈论的某些内容,因此此功能不似乎不太可能或不合理。

这个特性的一个简单例子是一个指针,它计算它被取消引用的次数。以下程序将输出 0,然后输出 1。

static void setter(void* environment, void* input) {
 /* You can't set the counter */
}

static void getter(void* environment, void* output) {
  *((int*)output) = *((int*)environment)++;
}

int main(int argc, char** argv) {
 volatile int counter = 0;
 volatile int * const x = map_special_voodoo_magic(getter, setter, sizeof(*x),
                                                   &counter);

 printf("%i\n", *x);
 printf("%i\n", *x);

 unmap_special_voodoo_magic(x);
}

附:需要一个 volatile 限定符,因为 x 指向的值会意外更改,对吗?同样,编译器没有理由认为取消引用 x 会改变计数器,所以那里也需要一个 volatile 对吗?

【问题讨论】:

  • If the operating system can do this then effectively it has the power to create regular pointers out of thunks -- 嗯?
  • @RobertHarvey thunk 是一段延迟评估的数据。延迟读取内存映射文件。因此,内存映射文件是一个 thunk 流,并且还有一个指向它的指针。
  • 那里的逻辑有问题。这有点像说狗是人类最好的朋友,每个人都需要一个朋友,所以每个人都应该养一只狗。
  • @RobertHarvey 也许我有点不清楚,但我希望我能明白操作系统有能力制作懒惰评估的数据,我想知道应用程序程序员是否也有能力做到这一点(它具有指针接口。)
  • @Steven Stewart-Gallus 使用 C,你不能只通过指针来做到这一点,你必须调用函数,而不是取消引用指针。但是,使用 C++,您可以通过自己的智能指针。 (你也许可以在某些平台上通过捕获 SIGSEGV 并在信号处理程序中执行 mmap() 来在 C 中做类似的事情 - 这不值得麻烦。)

标签: c pointers memory-mapped-files memory-mapping thunk


【解决方案1】:

以下代码没有错误检查,也不是完整的实现。但是,以下代码确实说明了如何将 thunk 转换为指针的基本思想。特别是,值 4 是按需计算的,而不是更早分配给内存的。

#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>
#include <signal.h>

void * value;

static void catch_function(int signal, siginfo_t* siginfo,
                 void* context) {
    if (value != siginfo->si_addr) {
        puts("ERROR: Wrong address!");
        exit(1);
    }

    mmap(value, sizeof(int), PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED
                        | MAP_ANON, -1, 0);

    *((int*)value) = 2 * 2;
}

int main(void) {
    struct sigaction new_action;

    value = mmap(NULL, sizeof(int), PROT_NONE, MAP_ANON | MAP_SHARED, -1,
                    0);

    sigemptyset(&new_action.sa_mask);

    new_action.sa_sigaction = catch_function;
    new_action.sa_flags = SA_SIGINFO;

    sigaction(SIGBUS, &new_action, NULL);

    printf("The square of 2 is: %i\n", *((int*)value));

    munmap(value, sizeof(int)); 

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-25
    • 2020-04-04
    • 2011-01-02
    • 1970-01-01
    • 2014-02-05
    • 2018-03-13
    • 2019-03-13
    • 1970-01-01
    相关资源
    最近更新 更多