【问题标题】:Why is this code blocking?为什么这段代码会阻塞?
【发布时间】:2011-05-04 03:32:45
【问题描述】:

我有一些代码需要很短的时间才能完成。我希望它在一个单独的线程上处理,因为它主要被 IO 阻塞。为此,我实现了以下内容,但是当调用线程运行background_picture_save() 时,它似乎被阻塞了。为什么?

我正在尝试让 save_picture() 函数作为后台进程工作。

static void * threaded_save_picture(void * p);
static void * threaded_save_picture(void * p) 
{
    char optarg[512];

    strncpy(optarg, p, sizeof optarg);  optarg[sizeof optarg - 1] = '\0';
    fprintf(stderr,"%s()::%s\n",__FUNCTION__,optarg);
    save_picture(optarg);
    pthread_detach(pthread_self());
    return(p);
} /* threaded_save_picture() */

extern void background_picture_save(const char * const optarg);
void background_picture_save(const char * const optarg)
{
    pthread_t thrd;
    (void)pthread_create(& thrd, NULL, threaded_save_picture, (void *) optarg);
} /* background_picture_save() */

【问题讨论】:

  • 你为什么使用pthread_detach?如果您不想加入线程,只需在分离状态下创建它即可。
  • 如果您要求“分离”,返回 p 有什么意义?
  • 您应该检查来自pthread_create() 的错误返回,尽管这不太可能导致程序阻塞。另一个可能的问题是传递给线程的字符串参数必须有足够的持续时间——在某处是静态的,或者是动态分配的——以允许线程的任意调度。如果它是调用background_picture_save()的代码中某处的局部变量,那么它可以在线程有机会复制它之前被修改或释放。
  • @EmeryBerger:因为我不知道你可以这样做。
  • @ydroneaud:因为函数原型;只是为了避免警告。

标签: c linux pthreads


【解决方案1】:

消除您的观察中的歧义。

使用 gdb 运行程序,当主线程块打印带有“where”的回溯时。

使用 strace 显示阻塞时正在进行的系统调用。

使用 systemtap http://sourceware.org/systemtap/ 显示被阻塞进程的内核回溯(尽管我看到 pthreads 支持只是最近才进入 http://www.cygwin.com/ml/libc-alpha/2011-01/threads.html#00010)。

【讨论】:

    【解决方案2】:

    我认为你必须按这个顺序做:

    pthread_detach(pthread_self());
    save_picture(optarg);
    

    【讨论】:

    • 我想,但考虑 EmeryBerger 的 cmets 和来自 opengroup websitepthread_detach 的描述: pthread_detach() 函数应向实现表明线程线程的存储可以回收当该线程终止时。没有提到导致线程调度程序运行。
    • 老实说,我无法弄清楚它为什么被阻止。也许您应该尝试替换“save_picture(optarg);”与其他东西(例如睡眠循环)对齐,看看会发生什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-30
    • 1970-01-01
    • 2017-07-14
    • 2017-01-26
    • 2015-11-03
    • 2011-10-16
    相关资源
    最近更新 更多