您的位置:首页 > 其它

完成变量(一种简单的信号量)

2013-04-19 11:57 113 查看
struct completion:

有的时候我们需要在一个线程里面发起另外一个线程里的某些动作,然后等待另外一个线程的动作完成.这个我们可以用completion.这是信号量的一种简单实现.

完成变量是信号量的一种简单的实现。当一个任务运行需要请求某个资源或条件的情况下, wait_for_completion() 函数将此任务放入等待队列,等待。另外一个任务使用完这个资源通过 complete() 函数发送一个完成变量,通知等待队列中的这个任务继续执行。
 
完成变量的实现函数
 
struct completion {
unsigned int done;
wait_queue_head_t wait;
};
 
void fastcall __sched wait_for_completion(struct completion *x)
{
might_sleep();
 
spin_lock_irq(&x->wait.lock);
if (!x->done) {
DECLARE_WAITQUEUE(wait, current);
 
wait.flags |= WQ_FLAG_EXCLUSIVE;
__add_wait_queue_tail(&x->wait, &wait);
do {
__set_current_state(TASK_UNINTERRUPTIBLE);
spin_unlock_irq(&x->wait.lock);
schedule();
spin_lock_irq(&x->wait.lock);
} while (!x->done);
__remove_wait_queue(&x->wait, &wait);
}
x->done--;
spin_unlock_irq(&x->wait.lock);
}
 
 
void fastcall complete(struct completion *x)
{
unsigned long flags;
 
spin_lock_irqsave(&x->wait.lock, flags);
x->done++;
__wake_up_common(&x->wait, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE,
1, 0, NULL);
spin_unlock_irqrestore(&x->wait.lock, flags);
}
 
 
完成变量的使用举例
 
demo 程序
 
/*
* chardev.c: Creates a read-only char device that says how many times
* you've read from the dev file
*/
 
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
/* for put_user */
#include <linux/completion.h>
 
#if 1
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
#endif
#define SUCCESS 0
#define DEVICE_NAME "chardev"
/* Dev name as it appears in /proc/devices   */
//#define BUF_LEN 80
 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Edwin");
 
static int Major;
//struct completion mr_completion;
//init_completion(&mr_completion);
 
DECLARE_COMPLETION(mr_completion);
 
//st
c94c
ruct completion mr_completion;
 
 
 
static struct file_operations fops = {
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
};
 
/*
* Functions
*/
 
int completion_init(void)
{
Major = register_chrdev(0, DEVICE_NAME, &fops);
 
if (Major < 0) {
printk("Registering the character device failed with %d/n",
Major);
return Major;
}
#if 1
printk("<1>I was assigned major number %d.  To talk to/n", Major);
printk("<1>the driver, create a dev file with/n");
printk("'mknod /dev/hello c %d 0'./n", Major);
printk("<1>Try various minor numbers.  Try to cat and echo to/n");
printk("the device file./n");
printk("<1>Remove the device file and module when done./n");
#endif
return 0;
}
 
void completion_exit(void)
{
/*
* Unregister the device
*/
int ret = unregister_chrdev(Major, DEVICE_NAME);
if (ret < 0)
printk("Error in unregister_chrdev: %d/n", ret);
else
printk("The %s moudle is released./n",DEVICE_NAME);
}
 
module_init(completion_init);
module_exit(completion_exit);
 
/*
* Methods
*/
 
/*
* Called when a process tries to open the device file, like
* "cat /dev/mycharfile"
*/
static int device_open(struct inode *inode, struct file *file)
{
 
try_module_get(THIS_MODULE);
 
return SUCCESS;
}
 
/*
* Called when a process closes the device file.
*/
static int device_release(struct inode *inode, struct file *file)
{
 
/*
* Decrement the usage count, or else once you opened the file, you'll
* never get get rid of the module.
*/
module_put(THIS_MODULE);
 
return SUCCESS;
}
 
/*
* Called when a process, which already opened the dev file, attempts to
* read from it.
*/
static ssize_t device_read(struct file *filp,
/* see include/linux/fs.h   */
 
char *buffer,
size_t length,
loff_t * offset)
{
 
printk("<1>the current process %i %s will sleep at once./n", current->pid, current->comm);
 
 
wait_for_completion(&mr_completion);
printk("<1>the completion sig is released................................./n");
//printk("<1> device_read operation is executed/n");
 
return 0;
 
}
 
/* 
* Called when a process writes to dev file: echo "hi" > /dev/hello
*/
static ssize_t
device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
{
printk("<1>the echo operation is executing /n");
 
complete(&mr_completion);
printk("<1>the completion sig  is launched /n");
 
//printk("<1>Sorry, this operation isn't supported./n");
//return -EINVAL;
}

分享到: 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  cmpletion signal lin