如何在Linux上的C中立即使poll()退出?

时间:2014-03-03 06:15:40

标签: c++ linux multithreading posix-api

我正在使用函数 poll()(我认为它可能是POSIX的一部分?)C函数在我的C ++类中,以便在文件更改时获取事件。这似乎工作得很好 - 但现在我也希望能够在我需要关闭线程时立即退出该函数。

我对此进行了研究,并提出了一些我尝试过的想法 - 比如试图发送信号,但我无法弄清楚如何让它发挥作用。

在下面的代码中(不是100%完成,但应该足以说明问题),我有一个C ++类,它从构造函数中启动一个线程,并希望在析构函数中清理该线程。线程调用 poll(),它在文件更改时返回,然后通知委托对象。监视线程循环,直到 FileMonitor 对象指示它可以退出(使用返回bool的方法)。

在析构函数中,我喜欢要做的是翻转bool,然后做一些导致 poll()立即退出的事情,然后调用* pthread_join( )*。那么,关于如何让 poll()立即退出的任何想法?

此代码针对Linux(特别是debian),但我也在Mac上进行处理。理想情况下,poll()API应该基本相同。

void * manage_fm(void *arg)
{
    FileMonitor * theFileMonitor = (FileMonitor*)arg;
    FileMonitorDelegate * delegate;

    unsigned char c;
    int fd = open(theFileMonitor->filepath2monitor(), O_RDWR);

    int count;

    ioctl(fd, FIONREAD, &count);
    for (int i=0;i<count;++i) {
       read(fd, &c, 1);
    }

    struct pollfd poller;
    poller.fd = fd;
    poller.events = POLLPRI;


    while (theFileMonitor->continue_managing_thread()) {
        delegate = theFileMonitor->delegate;
        if (poll(&poller, 1, -1) > 0) {
            (void) read(fd, &c, 1);
            if (delegate) {
                delegate->fileChanged();
            }
        }
    }
}

FileMonitor::FileMonitor( )
{
    pthread_mutex_init(&mon_mutex, NULL);

    manage_thread = true;

    pthread_mutex_lock (&mon_mutex);

    pthread_create(&thread_id, NULL, manage_fm, this);

    pthread_mutex_unlock(&pin_mutex);

}

FileMonitor::~FileMonitor()
{
    manage_thread = false;

    // I would like to do something here to force the "poll" function to return immediately.

    pthread_join(thread_id, NULL);
}

bool FileMonitor::continue_managing_thread()
{
    return manage_thread;
}

const char * FileMonitor::filepath2monitor()
{
    return "/some/example/file";
}

2 个答案:

答案 0 :(得分:2)

将管道添加到文件监视器类并切换轮询以获取原始文件描述符和管道读取描述符以进行轮询。如果要唤醒文件监视器类以检查退出,请通过管道的写入描述符发送一个字节,这将唤醒您的线程。

如果您拥有大量这些文件监视器,则可能会达到进程的最大文件描述符数(有关详细信息,请参阅Check the open FD limit for a given process in Linux,在我的系统上,它是1024 soft,4096 hard)。你可以让多个监控类共享一个管道,如果你不介意它们一次醒来检查它们的退出指示器。

答案 1 :(得分:-1)

你应该在poll - 循环内部(和之前)使用pthread condition variable,让其他线程调用pthread_cond_signal

您可能会认为pipe(7)是自我欺骗(例如,一个字符write(2)一个字节 - 可能就在pthread_cond_signal之前 - 到一个管道poll(2) - 由另一个线程编辑)。另请参阅signal-safety(7)calling Qt functions from Unix signal handlers。两者都可以激励你。