linux驱动程序中的并发控制-8(完成量(completion))-50

Posted 杨斌并

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux驱动程序中的并发控制-8(完成量(completion))-50相关的知识,希望对你有一定的参考价值。

完成量(completion)

  • 完成量用于一个执行单元等待另一个执行单元执行完成某项工作。也就是说,如果在执行某段代码之前必须要执行另一段代码,就要使用完成量。

完成量(completion)使用

  1. 定义完成量
  • 结构体(#include <linux/completion.h>)
static struct completion my_completion;
struct completion 
	unsigned int done;
	wait_queue_head_t wait;
;

其中done变量非常重要,该变量用于标识任务已经完成的次数。初始化后该变量值为0。后面会介绍如何使done变量加1或减1。

  1. 初始化完成量
init_completion(&my_completion);
//定义和初始化
DECLARE_COMPLETION(my_completion) 
  1. 等待完成量
  • wait_for_completion函数会根据completion. done变量的值决定是否等待一个完成量。该函数的定义如下:
void wait_for_completion(struct completion *c) ;
  • 如果completion.done 变量的值为0,wait form completion会通过阻塞的方式等待一个completion的完成。并且每调用一次 wait_for_completion 函数completion.done 变量的值会减1,直到为0时被阻塞,继续等待completion的完成。
  • 一个等待completion完成的函数是wait_ for_ completion interrupbible, 该函数的定义如下:
int wait_for_completion_interruptible (struct completion *c) ;
  • wait_for_completion和wait_for_completion_interrupbible 的区别是wait_for_completion函数在等待completion完成时不能被中断打断,而wait_for_ completion_inferrupbible 函数在等待completion完成时可以被中断打断。
  1. 唤醒完成量
extern void complete(struct completion *);
extern void complete_all(struct completion *);

complete函数用于唤醒一个 等待的执行单元,complete_all 函数用于唤醒所有等待统一完成量的执行单元。调用compete 函数会使completion.done 变量的值加1, 而complete_all 函数会将completion.done变量值设为int的最大值,也就是2147483647。这也是为什么使用complete_all 函数可以唤醒所有completion的原因。只要被completion阻塞的执行单元不大于2147483647个,就可以都被唤醒。


实例

  • completion_test.c
//
//  completion_test.c
//  seqlock_demo
//
//  Created by lianfei on 2021/7/13.
//


#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>

#define DEVICE_RCU_NAME "completion"

static struct completion my_completion;
static int completion_type = 0;

static ssize_t demo_read(struct file *file, char __user * buf, size_t count, loff_t *ppos)
    
    printk("read start completion.done: %d\\n", my_completion.done);
    wait_for_completion(&my_completion);
    printk("read end completion.done: %d\\n", my_completion.done);
    
    return 0;



static ssize_t demo_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
    printk("write start completion.done: %d\\n", my_completion.done);
    if (completion_type == 0) 
        complete(&my_completion);
    else if (completion_type == 1)
        complete_all(&my_completion);
    
    printk("write end completion.done:%d\\n", my_completion.done);
    return count;


static int demo_release(struct inode *node, struct file *file)
    return 0;


static int demo_open(struct inode *node, struct file *file)
    return 0;


static struct file_operations dev_fops=
    .owner = THIS_MODULE,
    .open = demo_open,
    .release = demo_release,
    .read = demo_read,
    .write = demo_write
;

static struct miscdevice misc=
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_RCU_NAME,
    .fops = &dev_fops
;


static int demo_init(void)

    int ret=misc_register(&misc);
    if(ret < 0 )
        printk("atomic_init is error\\n");
        return -1;
    
    printk("demo_init_success\\n");
    init_completion(&my_completion);
    return ret;


static void demo_exit(void)
    printk("ademo_exit_success\\n");
    misc_deregister(&misc);


module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");
module_param(completion_type, int, S_IRUGO|S_IWUSR);
MODULE_AUTHOR("binbing.Yang");
  • 测试脚本
  • completion_test.sh
#!/system/bin/sh
cat /dev/completion
echo data > /dev/completion

通过completion_type 模块参数可以设置completion驱动使用complete还是complete_all 函数唤醒完成量。当读取/dev/completion设备文件时,会调用demo_ read 函数,在该函数中调用了wait_for_completion函数等待,complete被唤醒。如果首先读取 /dev/completion 设备文件,demo_read函数将被阻塞,向/dev/completion 设备文件写入数据时,会调用demo_read 函数,在该函数中会根据completion_type模块参数的值使用complete或complete_all唤醒完成量。

以上是关于linux驱动程序中的并发控制-8(完成量(completion))-50的主要内容,如果未能解决你的问题,请参考以下文章

linux驱动程序中的并发控制-8(完成量(completion))-50

linux驱动程序中的并发控制-8(完成量(completion))-50

设备驱动中的并发控制

Linux 设备驱动的并发控制 学习笔记

并发控制

Linux 设备驱动的并发控