【问题标题】:Linux, C: how can I get return value from thread which greate than 4G in a 32bits OS?Linux,C:如何从 32 位操作系统中大于 4G 的线程获取返回值?
【发布时间】:2016-08-05 21:37:37
【问题描述】:

我正在运行操作系统的32 bits。 现在我创建的线程将返回一个 int 值,它可能大于4G。 如何通过pthread_join() 从我的main() 函数中接收此值? 看起来在32 bits 系统中,(void *) 是 4 个字节。

#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>

void* thread_function(void)
{
    uint64_t nbytes  = 0;
    //assign values to nbytes, it could be larger than 4G.
    return (void *)nbytes;
}

int main()
{
    pthread_t thread_id;
    uint64_t nbytes;

    pthread_create (&thread_id, NULL, &thread_function, NULL);
    pthread_join(thread_id,(void**)&nbytes); 
}

【问题讨论】:

  • 为什么不将 &amp;nbytes 作为您当前的 NULL arg 发送到 pthread_create 并通过函数中的地址简单地转换和设置值?
  • 首先您的thread_function 类型错误。它应该有论据。现在猜猜是什么?您可以使用这些参数来回传递值。 void* 返回类型实际上并不打算转换为非指针类型。

标签: c linux 32-bit


【解决方案1】:

像这样:

void* thread_function(void *)
{
    uint64_t nbytes  = 0;
    //assign values to nbytes, it could be larger than 4G.

    void *retval = malloc (sizeof (nbytes));
    memcpy (retval, &nbytes, sizeof (nbytes));
    return retval;
}

int main()
{
    pthread_t thread_id;
    uint64_t nbytes;

    pthread_create (&thread_id, NULL, &thread_function, NULL);

    void *ret;
    pthread_join(thread_id, &ret); 
    memcpy (nbytes, ret, sizeof (nbytes));
    free (ret);
}

这是将值从一个线程传输到另一个线程的常见模式。发送线程分配内存,复制值,并传递一个指针。接收线程获取指针,复制出值并释放指针。

【讨论】:

  • thread_function 签名无效。作为一种替代方法(并且,我会说更安全),它可以从接收线程获取一个指向预分配缓冲区的指针并填充它。将分配代码和释放代码放在同一级别是更好的做法。
  • @EugeneSh。谢谢,修好了。这是一个非常标准的模式,因为即使接收线程不知道对象有多大,甚至当线程的创建和连接在非常不同的位置时,它也可以工作。我认为在这种情况下,将分配与线程的创建联系起来会更糟糕,因为它在逻辑上与创建或使用结果的位置无关。
  • 嗯,是的。未知对象大小的用例非常有意义。
【解决方案2】:

David Schwartz 的解决方案是众所周知的,但传递一个简单的整数有点过分; malloc() 很昂贵,而且不一定是线程安全的(不太可能,但现在有所有嵌入的东西……)。

采纳 OP 前两位评论者(WhozCraig 和 Eugene Sh.)的想法

#include <stdio.h>
#include <stdint.h>
#include <pthread.h>
#include <stdlib.h>

void *thread_function(void *arg)
{
  /*
     No direct dereferencing
        *arg = 0xdeadbeefcafe;
     would give a compile error. With GCC it would be

     threadargs.c:8:5: warning: dereferencing ‘void *’ pointer [enabled by default]

  */
  uint64_t *nbytes = arg;
  *nbytes = 0xdeadbeefcafe;
  // you can return a simple status here, for example an error
  return 0;
}

int main()
{
  pthread_t thread_id;
  uint64_t nbytes;

  pthread_create(&thread_id, NULL, &thread_function, &nbytes);
  pthread_join(thread_id, NULL);
#define __STDC_FORMAT_MACROS
#include <inttypes.h>  
  printf("nbytes =  %" PRIx64 "\n", nbytes);

  return 0;
}

应该以另一种方式完成这项工作,对于这种用途来说可能更好。

缺点:每个线程都希望自己的变量被填充,所以它更适合固定的少量线程,否则你从堆中分配并且什么都没有,恰恰相反:它会更复杂阻止所有malloc()/free()。在这种情况下,David Schwartz 的方法会更合适。

【讨论】:

  • 如果您使用的是 POSIX 线程,那么 malloc() 将是线程安全的。
  • Also GlibC >= 2.2(至少,我认为甚至更早),但我经常被烧毁,以至于没有提示“无论你多么确定,都要先检查一下”。
猜你喜欢
  • 1970-01-01
  • 2017-07-17
  • 2020-02-13
  • 2013-09-18
  • 2015-09-26
  • 1970-01-01
  • 2011-02-20
  • 2018-04-20
  • 2013-08-29
相关资源
最近更新 更多