生产者消费者模型

实现共享环形缓冲区的生产消费者模型,包含用户层生产者 内核层生产者 内核层消费者

用户层

#include <fcntl.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>

int total_lost_count;

void *uthread_producer(void *arg) {
  int fd = open("/dev/ring_test_drv", O_RDWR);
  uint32_t seq_num = 1;
  while (1) {
    write(fd, &seq_num, sizeof(uint32_t));
    read(fd, &total_lost_count, sizeof(int));
    if(total_lost_count != 0){
      printf("data is lose ! stop thread");
      close(fd);
      break;
    }
    seq_num++;
  }
}

int main() {
  pthread_t producer_thread;
  if (pthread_create(&producer_thread, NULL, uthread_producer, NULL) != 0) {
    perror("Failed to create thread");
    return 1;
  }
  pthread_join(producer_thread, NULL);
  return 0;
}

内核层

#include <linux/init.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/spinlock.h>
#include <linux/sunyu_buffer.h>

static int producer_thread(void *data)
{
	int num = 1;
	while (!kthread_should_stop()) {
		spin_lock(&rb.lock);
		while (!kthread_should_stop() && is_full(&rb)) {
			spin_unlock(&rb.lock);
			wait_event_interruptible(rb.producer_wq, !is_full(&rb));
			spin_lock(&rb.lock);
		}
		produce_data(&rb, KTHREAD, num);
		printk("kernel_thread create num %d at index %d", num, rb.head);
		num = num + 1;
		spin_unlock(&rb.lock);
		wake_up_interruptible(&rb.consumer_wq);
	}
	return 0;
}

static int consumer_thread(void *data)
{
	while (!kthread_should_stop()) {
		struct data *current_data = &rb.buffer[rb.tail];
		wait_event_interruptible(rb.consumer_wq, !is_empty(&rb));
		check_data(current_data);
		consume_data(&rb, current_data);
		wake_up_interruptible_all(&rb.producer_wq);
	}
	return 0;
}

static int ring_drv_open(struct inode *node, struct file *file)
{
	wake_up_process(kthread_producer);
	wake_up_process(kthread_consumer);
	return 0;
}

static ssize_t ring_drv_read(struct file *file, char __user *buffer,
			     size_t length, loff_t *offset)
{
	int ret;
	ret = copy_to_user(buffer, &total_lost_count, sizeof(int));
	return sizeof(int);
}

static ssize_t ring_drv_write(struct file *file, const char __user *num,
			      size_t size, loff_t *offset)
{
	struct data user_data;
	int ret;
	spin_lock(&rb.lock);
	while (is_full(&rb)) {
		spin_unlock(&rb.lock);
		wait_event_interruptible(rb.producer_wq, !is_full(&rb));
		spin_lock(&rb.lock);
	}
	ret = copy_from_user(&user_data.seq_num, num, size);
	produce_data(&rb, USER, user_data.seq_num);
	printk("user_thread create num %d in index%d",
	       rb.buffer[rb.head].seq_num, rb.head);
	spin_unlock(&rb.lock);
	wake_up_interruptible(&rb.consumer_wq);
	return size;
}

static int ring_drv_close(struct inode *node, struct file *file)
{
	kthread_stop(kthread_producer);
	kthread_stop(kthread_consumer);
	return 0;
}

static struct file_operations ring_fops = {
	.owner = THIS_MODULE,
	.open = ring_drv_open,
	.read = ring_drv_read,
	.write = ring_drv_write,
	.release = ring_drv_close,
}

static int __init ring_init(void)
{
	rb.head = 0;
	rb.tail = 0;
	spin_lock_init(&rb.lock);
	kthread_consumer =
		kthread_create(consumer_thread, NULL, "kthread_consumer");
	kthread_producer = kthread_create(producer_thread, (void *)KTHREAD,
					  "kthread_producer");
	init_waitqueue_head(&rb.producer_wq);
	init_waitqueue_head(&rb.consumer_wq);
	major = register_chrdev(0, "ring_drv", &ring_fops);
	ring_class = class_create(THIS_MODULE, "ring_class");
	device_create(ring_class, NULL, MKDEV(major, 0), NULL, "ring_test_drv");
	return 0;
}

static void __exit ring_exit(void)
{
	device_destroy(ring_class, MKDEV(major, 0));
	class_destroy(ring_class);
	unregister_chrdev(major, "ring_drv");
}

module_init(ring_init);
module_exit(ring_exit);
MODULE_LICENSE("GPL");

内核层包含的头文件

#define RING_BUFFER_SIZE 32
static int major = 0;
static struct class *ring_class;
enum producer { KTHREAD, USER };
struct data {
	enum producer p;
	uint32_t seq_num;
};
struct ring_buffer {
	struct data buffer[RING_BUFFER_SIZE];
	int head;
	int tail;
	struct spinlock lock;
	wait_queue_head_t consumer_wq;
	wait_queue_head_t producer_wq;
};
static int lost_count_kernel = 0;
static int lost_count_user = 0;
static int total_lost_count = 0;
static uint32_t last_seq_num_kernel = 0;
static uint32_t last_seq_num_user = 0;
static struct task_struct *kthread_consumer;
static struct task_struct *kthread_producer;
static struct ring_buffer rb;

static int is_empty(struct ring_buffer *rb)
{
	return rb->head == rb->tail;
}

static int is_full(struct ring_buffer *rb)
{
	return (rb->head + 1) % RING_BUFFER_SIZE == rb->tail;
}

static void check_data(struct data *current_data)
{
	total_lost_count = lost_count_kernel + lost_count_user;
	if (current_data->p == KTHREAD) {
		if (current_data->seq_num != last_seq_num_kernel + 1) {
			lost_count_kernel += current_data->seq_num -
						last_seq_num_kernel - 1;
			printk("Producer Kernel Data lost detected! Lost count: %d %d\n",
			       lost_count_kernel, last_seq_num_kernel);
		}
		last_seq_num_kernel = current_data->seq_num;
	} else if (current_data->p == USER) {
		if (current_data->seq_num != last_seq_num_user + 1) {
			lost_count_user += current_data->seq_num -
						last_seq_num_user - 1;
			printk("Producer User Data lost detected! Lost count: %d %d\n",
			       lost_count_user, last_seq_num_user);
		}
		last_seq_num_user = current_data->seq_num;
	}
}

static void produce_data(struct ring_buffer *rb, enum producer p,
			 uint32_t seq_num)
{
	rb->buffer[rb->head].p = p;
	rb->buffer[rb->head].seq_num = seq_num;
	rb->head = (rb->head + 1) % RING_BUFFER_SIZE;
}

static void consume_data(struct ring_buffer *rb, struct data *current_data)
{
	printk("Consumer: Producer %s, Seq: %u\n",
	       current_data->p == KTHREAD ? "Kernel" : "User",
	       current_data->seq_num);
	rb->tail = (rb->tail + 1) % RING_BUFFER_SIZE;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值