completion
1.completion(补充?完成量?)
一个执行路径等待另一个执行路径完成某事。可用于解决多处理器上发生的一种微妙的竞争条件。类似于线程同步中的条件变量,一个线程在pthread_cond_wait()上等待,另一个线程通过pthread_cond_signal()或pthread_cond_broadcast()唤醒等待的一方。当然使用的环境是绝然不同的。
2.linux内核中的completion
定义:
struct
completion comple;
初始化:
init_completion(&comple)
DECLARE_COMPLETION(comple)
等待
wait_for_completion(struct
competion *comple)
唤醒
complete(struct
completion *comple) //唤醒一个等待的执行单元
complete_all(struct
completion *comple) //唤醒全部等待同一个的执行单元
-----------------------------------------------------------------------------------------
简单例子一个
1. 环境
2. 代码
test.c
-
#include <linux/module.h>
-
#include <linux/init.h>
-
#include <linux/kernel.h>
-
#include <linux/miscdevice.h>
-
#include <linux/sched.h>
-
#include <linux/completion.h>
-
-
-
#include <linux/uaccess.h>
-
#include <linux/fs.h>
-
#include <linux/cdev.h>
-
-
MODULE_LICENSE("GPL");
-
MODULE_AUTHOR("zl");
-
-
//char buffer[512];
-
//struct cdev my_dev;
-
//struct timer_list timer;
-
//struct completion comple;
-
DECLARE_COMPLETION(comple);
-
-
ssize_t my_write(struct file *fp, const char __user *buf, size_t count, loff_t *off)
-
{
-
complete(&comple);
-
//complete_all(&comple);
-
printk("[kernel: write] count = %ld.\n", count);
-
return count;
-
}
-
-
ssize_t my_read(struct file *fp, char __user *buf, size_t count, loff_t *off)
-
{
-
printk("[kernel: read] goto sleep .\n");
-
//wait_for_completion_interruptible_timeout(&comple, jiffies + 10 * HZ);
-
//wait_for_completion_timeout(&comple, jiffies + 10 * HZ);
-
wait_for_completion(&comple);
-
printk("[kernel: read] wake up. count = %ld.\n", count);
-
return count;
-
}
-
-
int my_open(struct inode *no, struct file *fp)
-
{
-
//fp->private_data = buffer;
-
//init_completion(&comple);
-
printk(" kernel: open.\n");
-
return 0;
-
}
-
-
int my_release(struct inode *no, struct file *fp)
-
{
-
printk(" kernel: release.\n");
-
return 0;
-
}
-
-
struct file_operations my_ops = {
-
.open = my_open,
-
.release = my_release,
-
.read = my_read,
-
.write = my_write,
-
};
-
-
struct miscdevice mydevice = {
-
.minor = MISC_DYNAMIC_MINOR,
-
.name = "myDevice",
-
.fops = &my_ops,
-
};
-
-
int test_init(void)
-
{
-
int ret = 0;
-
#if 0
-
ret = register_chrdev_region(MKDEV(52,0), 5, "my dev");
-
if (ret) {
-
printk(" register device number failed.\n");
-
return ret;
-
}
-
#endif
-
if(misc_register(&mydevice)) {
-
ret = -1;
-
}
-
-
return ret;
-
}
-
-
void test_exit(void)
-
{
-
misc_deregister(&mydevice);
-
//unregister_chrdev_region(MKDEV(52,0), 5);
-
}
-
-
module_init(test_init);
-
module_exit(test_exit);
Makefile
-
#KERNEL = /home/zl/linux-2.6.30.4
-
KERNEL = /lib/modules/$(shell uname -r)/build
-
-
-
default:
-
make -C $(KERNEL) M=$(shell pwd) modules
-
-
clean:
-
make -C $(KERNEL) M=$(shell pwd) modules clean
-
-
modules_install:
-
make -C $(KERNEL) M=$(shell pwd) modules_install INSTALL_MOD_PATH=/home/zl/tftpboot
-
-
obj-m += test.o
read.c
-
#include <stdio.h>
-
#include <fcntl.h>
-
#include <sys/types.h>
-
#include <unistd.h>
-
-
int main(int argc, char **argv)
-
{
-
int fd, ret;
-
char buf[512] = {0};
-
-
if (argc < 3 ) {
-
printf("Usage: %s \n", argv[0]);
-
return 0;
-
}
-
-
fd = open(argv[1], O_RDWR);
-
if (fd < 0) {
-
perror("open failed");
-
return 0;
-
}
-
-
ret = read(fd, buf, atoi(argv[2]));
-
buf[atoi(argv[2])] = 0;
-
-
printf("read %d Bytes: %s\n", ret, buf);
-
-
close(fd);
-
return 0;
-
}
write.c
-
#include <stdio.h>
-
#include <fcntl.h>
-
#include <sys/types.h>
-
#include <unistd.h>
-
-
int main(int argc, char **argv)
-
{
-
int fd, ret;
-
char buf[10] = {0};
-
-
if (argc < 4 ) {
-
printf("Usage: %s \n", argv[0]);
-
return 0;
-
}
-
-
fd = open(argv[1], O_RDWR);
-
if (fd < 0) {
-
perror("open failed");
-
return 0;
-
}
-
-
ret = write(fd, argv[2], atoi(argv[3]));
-
-
printf("write %d Bytes.\n", ret);
-
-
close(fd);
-
return 0;
-
}
3. 编译及加载模块
make clean;
make;
make write read
sudo insmod test.ko;
加载成功后有/dev/myDevice文件生成
混杂字符设备的设备号及设备名,第一行就是。
4.
执行
先执行read
上面的read一直没以返回,直到后面的write执行成功
后执行write(在另一个终端执行)
执行完成后,前面的read执行完成返回
阅读(1168) | 评论(0) | 转发(0) |