Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading Linux内核等待队列和列表之间的正确交互_Multithreading_Linux Kernel - Fatal编程技术网

Multithreading Linux内核等待队列和列表之间的正确交互

Multithreading Linux内核等待队列和列表之间的正确交互,multithreading,linux-kernel,Multithreading,Linux Kernel,我正在编写一个Linux内核模块,其中包含一个从不同进程上下文读取/写入的列表,我觉得在用户空间中缺少了相当于pthread_cond_wait()和co.的功能 天真地,我可能会这样写: static LIST_HEAD(request_list); static DEFINE_MUTEX(request_list_mutex); static DECLARE_WAIT_QUEUE_HEAD(request_list_post_wq); static void post_request(re

我正在编写一个Linux内核模块,其中包含一个从不同进程上下文读取/写入的列表,我觉得在用户空间中缺少了相当于pthread_cond_wait()和co.的功能

天真地,我可能会这样写:

static LIST_HEAD(request_list);
static DEFINE_MUTEX(request_list_mutex);
static DECLARE_WAIT_QUEUE_HEAD(request_list_post_wq);

static void post_request(request_t *request)
{
    mutex_lock(request_list_mutex);
    list_add(request, request_list);
    mutex_unlock(request_list_mutex);
    wake_event(request_list_post_wq);
}

static void wait_and_consume_request()
{
    mutex_lock(request_list_mutex);
    if(list_empty(request_list)) {
        mutex_unlock(request_list_mutex);
        wait_event(request_list_post_wq, !list_empty(request_list));
        mutex_lock(request_list_mutex);
    }

    // do something with request

    mutex_unlock(request_list_mutex);
}
然而,这看起来像是在消费者函数中有一个竞争条件,即在非空列表中唤醒,然后在有多个消费者的情况下重新获取互斥。同时,我必须在等待之前释放互斥锁,否则将无法向列表中添加任何内容


我考虑编写一个函数来锁定请求列表,只有当它仍然为空时才解锁,并将其用作等待事件的条件。。。但是在谷歌上我看到了很多人写wait_event(…..,!list_empty(…)的例子,所以我肯定遗漏了什么?

另一个人建议的helper函数根本不需要:

static int list_is_not_empty()
{
    int rv = 1;
    mutex_lock(request_list_mutex);
    rv = !list_empty(request_list);
    mutex_unlock(request_list_mutex);
    return rv;
}
没有必要仅仅为了查看列表是否为空而锁定列表。简单地说:

static void wait_and_consume_request()
{
    wait_event(request_list_post_wq, !list_empty(request_list));
    mutex_lock(request_list_mutex);
    if(!list_empty(request_list)) {
        // do something with request
    }
    mutex_unlock(request_list_mutex);
}
但这并不能保证您实际使用了一个请求。如果我们确实希望确保只使用一个请求,那么:

static void wait_and_consume_request()
{
    mutex_lock(request_list_mutex);            
    while(list_empty(request_list)) {
        mutex_unlock(request_list_mutex);
        wait_event(request_list_post_wq, !list_empty());
        lock_mutex();
     }
     // do something with request
     mutex_unlock(request_list_mutex);
}
这里是drivers/misc/carma/carma fpga.c中内核的一个真实示例(我刚刚使用了我看到的第一个示例)

      spin_lock_irq(&priv->lock);

      /* Block until there is at least one buffer on the used list */
      while (list_empty(used)) {
              spin_unlock_irq(&priv->lock);

              if (filp->f_flags & O_NONBLOCK)
                      return -EAGAIN;

              ret = wait_event_interruptible(priv->wait, !list_empty(used));
              if (ret)
                      return ret;

              spin_lock_irq(&priv->lock);
      }

      /* Grab the first buffer off of the used list */
      dbuf = list_first_entry(used, struct data_buf, entry);
      list_del_init(&dbuf->entry);

      spin_unlock_irq(&priv->lock);