【问题标题】:How to pass a local struct as parameter to pthread_create?如何将本地结构作为参数传递给 pthread_create?
【发布时间】:2016-07-28 15:26:11
【问题描述】:

以下功能不起作用。 pin_thread_function 有时会收到垃圾而不是结构数据。怎么了?我知道这是一些与范围相关的基本问题,但我无法解释。

typedef void (*state_callback_t)(int state);

struct pin_thread_params
{
    char pin[3 + 1];
    state_callback_t callback_onchange;
};

extern int pin_monitor_create(const char * pin,
        state_callback_t callback_onchange)
{
    int ret;
    unsigned long int thread;
    struct pin_thread_params params;

    //Setup struct
    strcpy(params.pin, "123");
    params.callback_onchange = callback_onchange;

    //Create thread with struc as parameter
    ret = pthread_create(&thread, NULL, pin_thread_function, &params);
    if (!ret)
    {
        ret = pthread_detach(thread);
    }

    return ret;
}

static void * pin_thread_function(void * context)
{
    struct pin_thread_params params;
    memcpy(&params, context, sizeof(params));

    //Sometimes the correct string, most time garbage 
    printf("Started monitoring %s", params.pin);
}

在 pthread_create 之前对 params 进行 malloc 时,一切正常,如下所示:

...
    struct pin_thread_params * params;

    //Setup struct with malloc
    params = malloc(sizeof(struct pin_thread_params));
    strcpy(params->pin, "123");
    params->callback_onchange = callback_onchange;
...

【问题讨论】:

    标签: c linux pointers scope pthreads


    【解决方案1】:

    struct pin_thread_params params 是静态分配的,一旦它的范围结束(即在pin_monitor_create 返回之后),它的地址就可以安全使用。有时可能会发生线程执行在pin_monitor_create 退出之前开始并且您在params 中看到有效数据的情况。但是,动态分配的内存来自堆,在您释放它之前一直可用,因此您始终可以在 pin_thread_function 内的 params 中获得有效数据。

    【讨论】:

    • 所以paramspthread_create 之后丢失。我几乎可以肯定它只会在函数 pin_monitor_create... 结束时消失;-( 我错过了一些基本的范围概念吗?
    • 不,再读一遍他写的。它在pin_monitor_create 的末尾消失了。
    • @natenho 在pthread_create 之后没有丢失,在pin_monitor_create 之后丢失了。您无法直接控制线程调度程序。如果主线程在pin_thread_function 线程运行之前完成了pin_thread_create 的执行,您将获得垃圾数据。如果幸运并且pin_thread_function 线程在主线程完成之前执行,您将看到您的字符串。或者在多核芯片上,两个线程真的可以并行运行。上下文切换可能随时发生。您必须采用一些线程同步技术。
    【解决方案2】:

    我对 pthreads 不是特别了解(还不能完全评论),但是您正在将一个指向堆栈分配内存的指针传递给线程,该线程最终将被正在进行的函数调用破坏。

    【讨论】:

    • 参数和堆栈不应该一直存活到 pin_monitor_create 结束吗?
    • 参数在堆栈上一直存在,直到引脚监视器创建结束。
    • 是的,但是您依赖 pin_thread_function() 在 pin_monitor_create() 完成之前制作副本。这就是为什么有时你会得到垃圾而其他时候它会起作用。您取决于调度程序。 mallocing 将是处理此问题的正确方法。
    • @natenho 是的。问题是,正如这两个答案所说,pin_monitor_create 不会等待pin_thread_function 完成执行。据我从手册页可以看出,pthread_detach 不是阻塞调用。所以你在堆栈上创建params,启动线程,现在你在pin_thread_functionpin_monitor_create 的其余部分之间有一个竞争条件。一旦pin_monitor_create 返回,params 就不再有效。如果你这样做,你将需要某种同步来确保pin_thread_create 将在返回之前等待pin_thread_function 完成
    • @natenho 酷!线程很快变得棘手。我推荐阅读这个教程,非常好,我一直在参考它:computing.llnl.gov/tutorials/pthreads
    猜你喜欢
    • 2023-03-15
    • 2010-10-26
    • 1970-01-01
    • 2020-09-26
    • 1970-01-01
    • 2014-05-28
    • 1970-01-01
    • 2017-03-18
    • 1970-01-01
    相关资源
    最近更新 更多