我需要实现一种方法来睡眠这个线程,直到它有工作要做

lin*_*sek 10 c linux multithreading pthreads embedded-linux

好吧,所以这个问题并不完全是关于线程管理......好吧,等等.我正在寻找这种配置的不同解决方案.我有一些想法,但我正在寻找可以解决问题的任何解决方案.并将权衡利弊,以实现最好的一个.

情况就是这样.

我有一个将生成线程的管理器应用程序.该线程将持续运行并处理通过USB连接到系统的板的串行通信.管理器应用程序促进系统上运行的其他应用程序与此线程之间的通信.线程需要真正执行两件事:

  1. 在可变定时器上通过串行轮询电路板获取样品数据..通常大约每分钟一次(串行总线相当慢,波特率为4800.我无法控制这个)
  2. 促进与经理应用程序的通信.(即其他应用程序将请求样本数据,管理器将请求转发给线程.线程执行操作并返回数据)

我最初的设计很简单,很有效.我使用队列和互斥体来管理经线.所以线程的逻辑如下:

  1. 初始化
  2. 虽然我们没有收到经理的关机命令
  3. 如果我们的计时器已启动,请在电路板上查询数据
  4. 否则,请检查管理器是否有消息发送到队列.如果是这样,请处理它

问题是我没有考虑CPU利用率.99.9%的时间我的线程没有处理任何东西而只是吮吸电源.我需要实现一种方法来睡眠这个线程,直到它有工作要做.所以有几个想法:

使用select()来阻止.这可以基于我需要使用的计时器来阻止,我可以将队列消息传递实现更改为套接字消息传递.相反,线程会打开一个客户端套接字到管理器,管理器会通过套接字将消息传递给线程.然后select()会睡觉,直到fd上有活动或我的计时器启动.

亲:正是我需要的功能.

Con:对于与你共享内存的线程进行通信,套接字是不是有点繁重?

使用信号系统.(在Linux上知识渊博的人可以通过一个实现示例在这里进行管道......我不确定该怎么做.)但是线程可以在计时器的持续时间内休眠,并且如果信号是,则唤醒进行处理收到经理.

Pro:使用共享内存维护当前实现

Con:不确定如何实施.是否有像select()这样的函数可以使用信号而不是fds?

可能是互斥量.我可以阻止,直到经理发布了一个互斥锁.

专业:仍然共享内存

Con:可能需要将计时器处理移动到管理器,这实际上不是一个选项,因为它有其他计时器和关键工作要执行.

请推荐并随意批评.我愿意接受任何有效的选择.请注意,虽然这是在嵌入式系统上运行,但资源使用至关重要.

Jen*_*edt 5

处理这种情况的经典工具是信号量而不是互斥量或条件变量.将它们视为从经理传递给线程的令牌.

线程可以sem_timedwait用来确保偶尔唤醒以检查数据.

注意捕获sem_函数的错误返回,它们是可中断的.所以你可能会有比你想象的更多的唤醒.


Ale*_* C. 4

使用信号量尝试这样的事情:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

static sem_t s_sem;
static int iAlive = 1;

void* thFunc(void *param)
{
    printf("%s : ENTER \n", __FUNCTION__);
    while(iAlive)
    {
        printf("%s : waiting \n", __FUNCTION__);
        sem_wait(&s_sem);

        printf("%s : got a signal - doing something \n", __FUNCTION__);
        sleep(1);
    }

    printf("%s : EXIT \n", __FUNCTION__);
    return 0;
}

int main()
{
    pthread_t thread;
    sem_init(&s_sem, 0, 0);

    if(0 != pthread_create(&thread, NULL, thFunc, NULL))
    {
        printf("%s : pthread_create FAILED \n", __FUNCTION__);
        return -1;
    }

    while ( getchar() != 'q' )
    {
        printf("%s : sending signal \n", __FUNCTION__);
        sem_post(&s_sem);
    }

    iAlive = 0;
    sem_post(&s_sem);
    pthread_join(thread, NULL);
    sem_destroy(&s_sem);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果需要超时,可以替换sem_wait为。sem_timedwait