c - 如何正确管理 pthread

标签 c pthreads embedded-linux pthread-join

我有时会遇到一些随机问题来加入 pthread。我只能说,当连接失败时,线程并没有陷入互斥锁的死锁状态。大多数情况下,当连接发生超时时,线程处于空闲状态( sleep 系统调用)。

我的需求是基本的。一种从主线程启动/停止线程的方法。所以我不需要将互斥量放在 pthread 状态变量的启动/停止管理器中。线程大部分时间都在无限循环中工作。我所有的线程都设计有相同的骨架。具有启动和停止功能。线程函数定义。我有一个全局变量 g_event_ctx 来存储线程的当前状态。 运行 知道我需要取消它。 is_joinable 以了解我是否需要加入线程。此外,我的所有线程函数都有 sleep /读/写系统调用(取消点!)

typedef struct pthread_context
{
    pthread_t id;       /*!< pthread_t to be able to stop the thread later */
    int running;        /*!< allow to know if the thread is currently running */
    int is_joinable;    /*!< allow to know if the thread is joinable */
} str_pthread_context;

骨架代码:

   int start_x_manager (void)
    {
        pthread_t t_x;

        if (g_event_ctx.x_thread.is_joinable) return 0;

        PRINT_INFO ("Start x manager");

        // start push x thread
        if (pthread_create (&t_x, NULL, x_loop_thread, NULL))
            PRINT_ERR_GOTO ("error on pthread_create for x thread");
        pthread_setname_np(t_x, "x");
        g_event_ctx.x_thread.id = t_x;
        g_event_ctx.x_thread.is_joinable = 1;
        g_event_ctx.x_thread.running = 1;
        return 0;
    error:
        g_event_ctx.x_thread.running = 0;
        g_event_ctx.x_thread.is_joinable = 0;
        return 1;
    }

    int stop_x_manager (void)
    {
        struct timespec ts;

        if (!g_event_ctx.x_thread.is_joinable) return 0;
        PRINT_INFO ("Stop x manager");

        if (g_event_ctx.x_thread.running)
        {
            CHECK_ERR_GOTO (pthread_cancel(g_event_ctx.x_thread.id) != 0, "Cannot cancel x thread");
            g_event_ctx.x_thread.running = 0;
        }
        CHECK_ERR_GOTO (clock_gettime(CLOCK_REALTIME, &ts) == -1, "Cannot get clock time");
        ts.tv_sec += 5;
        CHECK_ERR_GOTO (pthread_timedjoin_np (g_event_ctx.x_thread.id, NULL, &ts) != 0, "Cannot join x_thread");
        g_event_ctx.x_thread.is_joinable = 0;
        return 0;
    error:
        g_event_ctx.x_thread.running = 0;
        g_event_ctx.x_thread.is_joinable = 0;
        return 1;
    }

线程函数的框架:

void *x_loop_thread (void *arg __attribute__((__unused__)))
{

    CHECK_ERR_GOTO (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0, "Cannot set cancel state");
    CHECK_ERR_GOTO (pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0, "Cannot set cancel state");

    PRINT_INFO ("Start x manager loop thread ...");

    pthread_cleanup_push(x_manager_cleanup, some_stuff);

    while (1)
    {
         // Do some stuff here
    }
    g_event_ctx.x_thread.running = 0;
    pthread_exit (NULL);
  error:
    g_event_ctx.x_thread.running = 0;
    pthread_cleanup_pop(1);
    pthread_exit (NULL);
}

CHECK_ERR_GOTO 是一个宏,它检查条件以了解我是否需要跳转到标签错误

可以解释 pthread_timedjoin_np 超时的原因是什么?另一段破坏了我的线程 ID 的代码?我的骨架设计有问题吗?

最佳答案

您可以通过在上下文结构中放置一个变量来表明您希望后台线程停止,在调用 join 之前在主线程中设置该变量,并在后台线程中定期检查该变量,退出 while( 1)如果为真则循环。 如果您有任何永远休眠的阻塞调用,您可以让它们超时并使用 while(!want_to_stop) 循环它们,或者对于选择循环,添加一个可以从主线程激活的文件描述符当你想停止时(eventfd 或管道)。

关于c - 如何正确管理 pthread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54971443/

相关文章:

Pthreads、MPI 和 OpenMP 中的 C++

embedded-linux - BitBake 中的任务 do_patch() 期间失败

c - C中如何检查服务器端是否建立连接

c++ - 在 C 中嵌入 Ruby 并扩展

c++ - 如何增量更新哈希值?

c - 使用多线程对数字进行平方

c - GCC编译器: error linker command failed using the Make file

c - 在 C 中重新连接线程

c - linux环境下C和C++中的volatile

linux - 为什么我需要两个不同的 wpa_supplicant 连接(wpa_cli - ctrl_conn 和 mon_conn)