Linux系统提供了一种比信号量更好的同步机制,即completion,它用于一个执行单元等待另一个执行单元执行完某事。 Linux系统中与completion相关的操作主要有以下4种: (1) 定义completion struct completion my_completion; (2) 初始化completion init_completion(&my_completion); 对my_completion的定义和初始化可以通过如下快捷方式实现 DECLEARE_COMPLETION(my_completion); (3) 等待completion void wait_for_completion(struct completion *c); (4) 唤醒completion void complete(struct completion *c); void complete_all(struct completion *c); 前者只唤醒一个等待的执行单元,后者唤醒所有等待同一completion的执行单元。
二、作用:
虽然信号量可以用于实现同步,但往往可能会出现一些不好的结果。例如:当进程A分配了一个临时信号量变量,把它初始化为关闭的MUTEX, 并把其地址传递给进程B,然后在A之上调用down(),进程A打算一旦被唤醒就撤销给信号量。随后,运行在不同CPU上的进程B在同一个信号量 上调用up()。然而,up()和down()的目前实现还允许这两个函数在同一个信号量上并发。因此,进程A可以被唤醒并撤销临时信号量,而进程B 还在运行up()函数。结果up()可能试图访问一个不存在的数据结构。这样就会出现错误。为了防止发生这种错误就专门设计了completion机制 专门用于同步。信号量在多cpu的时候效果不好。
SD卡中表现为:
void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq) { DECLARE_COMPLETION_ONSTACK(complete);//创建一个completion结构体放在内核堆栈中,如果不加ONSTACK就是静态申请,会存放在全局变量区 mrq->done_data = &complete; mrq->done = mmc_wait_done; mmc_start_request(host, mrq); wait_for_completion(&complete); } static void mmc_wait_done(struct mmc_request *mrq) { complete(mrq->done_data); //mrq->done_data = &complete }