gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 06:37:59 29 4
gpt4 key购买 nike

我正在编写一个 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);
}

但是,如果有多个消费者,这看起来会在消费者函数中出现竞争条件,即在非空列表上唤醒然后重新获取互斥量。同时,我必须在等待之前释放互斥量,否则无法将任何内容添加到列表中。

我考虑过编写一个锁定 request_list 的函数,并且只有在它仍然为空时才将其解锁,并将其用作 wait_event 的条件...但是谷歌搜索我已经看到很多人写 wait_event(... ., !list_empty(...)) 所以我一定是遗漏了什么?

最佳答案

完全不需要其他人建议的辅助函数:

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);

关于multithreading - Linux 内核等待队列和列表之间的正确交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23484730/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com