天天看點

4.6 中斷篇-代碼應用:實作一個可多線程同時删除,增加的連結清單

功能:實作一個多線程同時删除,增加的連結清單

要點:同時使用鎖,消息隊列,定時器,原子操作

#include<linux/init.h>
#include<linux/module.h>
#include<linux/list.h>
#include<linux/semaphore.h>
#include<linux/sched.h>
#include<linux/timer.h>
#include<linux/spinlock_types.h>
#include<linux/workqueue.h>
#include<linux/slab.h>
#include<linux/kthread.h>
#include<linux/kallsyms.h>
#include<linux/atomic.h>

typedef struct mystruct{
	  struct list_head list;
	  int id;
	  int pid;
}my_str,*my_pstr;

static LIST_HEAD(head);
static DEFINE_SPINLOCK(my_lock);
static struct work_struct queue;
static DEFINE_SEMAPHORE(sem);
static struct timer_list mytimer;
static unsigned int list_len = 0;
static atomic_t my_count = ATOMIC_INIT(0);
static int count = 0;

static int sharelist(void *data)
{
	  my_pstr m_list;

	  if(count++ % 4 == 0)
		   printk("\n");

	  spin_lock(&my_lock);
	  
	  if(list_len < 50){
			if((m_list = kmalloc(sizeof(my_str),GFP_KERNEL)) == NULL )
				  return -ENOMEM;

			m_list->id = atomic_read(&my_count);
			atomic_inc(&my_count);
			m_list->pid = current->pid;
			list_add(&m_list->list, &head);
			list_len++;
			printk("thread add :%5d\n",m_list->id);
	  }else{
			m_list = list_entry(head.prev,my_str,list);
			list_del(&m_list->list);

			list_len--;
			printk("Thread del %5d\n",m_list->id);
			kfree(m_list);
	  }

	  spin_unlock(&my_lock);

	  return 0;
}


static void start_kthread(void)
{
	  down(&sem);
	  schedule_work(&queue);
}

static void kthread_launcher(struct work_struct *q)
{
	  kthread_run(sharelist,NULL,"%d",count);
	  up(&sem);
}

void qt_task(unsigned long data)
{
	  spin_lock(&my_lock);
	  
	  if(!list_empty(&head)){
			my_pstr my_list;
			if(count++ % 4 == 0)
				  printk("\n");

			my_list = list_entry(head.next, my_str, list);
			list_del(&my_list->list);
			list_len--;

			printk("timer del : %5d\n",my_list->id);
			kfree(my_list);
	  }
	  spin_unlock(&my_lock);

	  mod_timer(&mytimer,jiffies + msecs_to_jiffies(1000));
}

static int __init share_init(void)
{
	  int i;

	  printk("shar init\n");

	  INIT_WORK(&queue,kthread_launcher);
	  setup_timer(&mytimer,qt_task,0);
	  add_timer(&mytimer);
	  for(i = 0; i < 200; i++)
			start_kthread();

	  return 0;
}

static void __exit share_exit(void)
{
	  struct list_head *n= NULL;
	  struct list_head *p =NULL;

	  my_pstr my;

	  printk("\n share list exit\n");
	  del_timer(&mytimer);
	  spin_lock(&my_lock);
	  list_for_each_safe(p,n,&head){
			if(count++ % 4 == 0)
				  printk("\n");

			my = list_entry(p,my_str,list);
	  
			list_del(p);
			printk("exit:del %d\n",my->id);
			kfree(my);
	  }
	  spin_unlock(&my_lock);
	  printk("all exit");
}

module_init(share_init);
module_exit(share_exit);
MODULE_LICENSE("GPL");