- 论坛徽章:
- 0
|
完成变量的工作机制
完成变量是信号量的一种简单的实现。当一个任务运行需要请求某个资源或条件的情况下,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
#include
#include
#include
/* for put_user */
#include
#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);
//struct 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 printk("Registering the character device failed with %d\n",
Major);
return Major;
}
#if 1
printk("I was assigned major number %d. To talk to\n", Major);
printk("the driver, create a dev file with\n");
printk("'mknod /dev/hello c %d 0'.\n", Major);
printk("Try various minor numbers. Try to cat and echo to\n");
printk("the device file.\n");
printk("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 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("the current process %i %s will sleep at once.\n", current->pid, current->comm);
wait_for_completion(&mr_completion);
printk("the completion sig is released.................................\n");
//printk(" 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("the echo operation is executing \n");
complete(&mr_completion);
printk("the completion sig is launched \n");
//printk("Sorry, this operation isn't supported.\n");
//return -EINVAL;
}
注:
具体参照
[1]
http://hi.baidu.com/phenix_yw/blog/item/4757f6243dcd83004c088dd9.html
[2]
http://aoqingy.spaces.live.com/blog/cns!153c2d72af27eb1c!308.entry
/* buffer to fill with data */
/* length of the buffer
*/
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/43047/showart_401611.html |
|