Analysis of completion interface in Linux driver (wait_for_complete example, very good) "turn"

Source: Internet
Author: User
Tags system log

Transferred from: http://blog.csdn.net/batoom/article/details/6298267

Completion is a lightweight mechanism that allows a thread to tell another thread that the work has been done. You can create completion statically using the following macro:
Declare_completion (my_completion);

If the runtime creates completion, it must be dynamically created and initialized in the following ways:
struct Compltion my_completion;
Init_completion (&my_completion);

The relevant definitions of completion are included in the Kernel/include/linux/completion.h:

struct Completion {
unsigned int done;
wait_queue_head_t wait;
};


#define COMPLETION_INITIALIZER (Work)/
{0, __wait_queue_head_initializer (work). WAIT)}

#define DECLARE_COMPLETION (Work)/
struct Completion work = Completion_initializer (work)

static inline void init_completion (struct completion *x)
{
X->done = 0;
Init_waitqueue_head (&x->wait);
}

To wait for completion, the following calls can be made:
void Wait_for_completion (struct completion *c);

To trigger the completion event, call:
void complete (struct completion *c); Wake up a waiting thread
void Complete_all (struct completion *c);//Wake Up all waiting threads

To illustrate how the completion is used, the code for the complete module in the Linux device driver book is summarized below:
/*
* COMPLETE.C--The writers awake the readers
*
* Copyright (C) 2003 Alessandro Rubini and Jonathan Corbet
* Copyright (C) 2003 O ' Reilly & Associates
*
* The source code in this file can be freely used, adapted,
* and redistributed in source or binary form, so long as an
* acknowledgment appears in derived source files. The citation
* Should list, the code comes from the "Linux Device
* Drivers "by Alessandro Rubini and Jonathan Corbet, published
* by O ' Reilly & Associates. No warranty is attached;
* We cannot take responsibility for errors or fitness for use.
*
* $Id: Complete.c,v 1.2 2004/09/26 07:02:43 Gregkh EXP $
*/

#include <linux/module.h>
#include <linux/init.h>

#include <linux/sched.h> * * Current and everything */
#include <linux/kernel.h>/* PRINTK () */
#include <linux/fs.h>/* Everything ... * *
#include <linux/types.h>/* size_t */
#include <linux/completion.h>

Module_license ("Dual BSD/GPL");

static int complete_major = 253;//Specifies the main device number

Declare_completion (comp);

ssize_t complete_read (struct file *filp, char __user *buf, size_t count, loff_t *pos)
{
     ;     PRINTK (kern_debug "Process%i (%s) going to sleep/n",
          current->pid, Current->comm);
         wait_for_completion (&comp);
         PRINTK (kern_debug "Awoken%i (%s)/n", Current->pid, current- >COMM);
         return 0;/* EOF */
}

ssize_t complete_write (struct file *filp, const char __user *buf, size_t count,
loff_t *pos)
{
PRINTK (kern_debug "Process%i (%s) awakening the readers.../n",
Current->pid, Current->comm);
Complete (&COMP);
return count; /* Succeed, to avoid retrial */
}


struct File_operations complete_fops = {
. Owner = This_module,
. Read = Complete_read,
. write = Complete_write,
};


int complete_init (void)
{
int result;

/*
* Register your major, and accept a dynamic number
*/
result = Register_chrdev (Complete_major, "complete", &complete_fops);
if (Result < 0)
return result;
if (Complete_major = = 0)
Complete_major = result; /* Dynamic */
return 0;
}

void Complete_cleanup (void)
{
Unregister_chrdev (Complete_major, "complete");
}

Module_init (Complete_init);
Module_exit (Complete_cleanup);


The module defines a simple completion device: Any process that attempts to read from the device waits until the other device writes to the device. The makefile for compiling this module are as follows:
Obj-m: = COMPLETE.O
Kdir: =/lib/modules/$ (Shell uname-r)/build
PWD: = $ (shell pwd)
Default
$ (make)-C $ (Kdir) m=$ (PWD) modules
Clean
Rm-f *.ko *.O *.MOD.C

Execute the following command in the Linux terminal, compile the build module, and load it dynamically.
#make
#mknod completion C 253 0
#insmod Complete.ko
Open three more terminals, one for the read process:
#cat completion
One for the write process:
#echo >completion
Another view system log:
#tail-F/var/log/messages

It is worth noting that when we use the Complete_all interface, if you want to reuse a completion structure, you must perform a init_completion (struct completion c) to reinitialize it. The definition of this macro can be found in Kernel/include/linux/completion.h:
#define INIT_COMPLETION (x) ((x). done = 0)

The following code makes some changes to the code in the book, the wake-up interface from the original complete to Complete_all, and in order to reuse the completion structure, all the read process is completed after the initialization of the completion structure, the specific code is as follows:
#include <linux/module.h>
#include <linux/init.h>

#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/completion.h>

Module_license ("Dual BSD/GPL");

#undef Kern_debug
#define KERN_DEBUG "<1>"

static int complete_major=253;
static int reader_count = 0;

Declare_completion (comp);

ssize_t complete_read (struct file *filp,char __user *buf,size_t count,loff_t *pos)
{
            PRINTK (kern_debug "Process%i (%s) going to sleep,waiting for writer/n", CURRENT->PID,CURRENT->COMM);
           reader_count++;
           PRINTK (kern_debug "in Read, before Comletion: Reader count =%d/n ", reader_count);
           wait_for_completion (&comp);
           reader_count--;
           PRINTK (kern_debug "awoken%s (%i)/n",current-> COMM,CURRENT->PID);
           PRINTK (kern_debug "in Read,after completion: Reader count =%d/n ", reader_count);

/* If you use Complete_all, the completion structure can only be used once, and you must call this macro to reinitialize when you use it again */
            if (Reader_count = = 0)
                        init_completion (comp);

           return 0;
}

ssize_t complete_write (struct file *filp,const char __user *buf,size_t count,loff_t *pos)
{
            PRINTK (kern_debug "Process%i (%s) awoking the readers.../n", CURRENT->PID,CURRENT->COMM);
           PRINTK (kern_debug "in write, before do Complete_all : Reader count =%d/n ", reader_count);

           if (reader_count! = 0)   
                    Complete _all (&comp);

           PRINTK (kern_debug "in write, after do Complete_ All:reader count =%d/n ", reader_count);

           return count;
}

struct File_operations complete_fops={
. Owner = This_module,
. Read = Complete_read,
. write = Complete_write,
};

int complete_init (void)
{
int result;

Result=register_chrdev (Complete_major, "complete", &complete_fops);
if (result<0)
return result;
if (complete_major==0)
Complete_major =result;

PRINTK (kern_debug "complete driver test init! complete_major=%d/n ", complete_major);
PRINTK (kern_debug "static initialization completion/n");

return 0;
}

void Complete_exit (void)
{
Unregister_chrdev (Complete_major, "complete");
PRINTK (kern_debug "complete driver is removed/n");
}

Module_init (Complete_init);
Module_exit (Complete_exit);

Here the test steps are the same as above, except that you need to open several terminals to perform multiple simultaneous read operations.

____________

Resources:
1.Jonathan Corbet Wait, Wei Yongming, etc. linux device Drivers (third edition)
2.Linux Kernel

Analysis of completion interface in Linux driver (wait_for_complete example, very good) "turn"

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.