实验代码:
share.c :
#include <linux/module.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/sched.h>
#include <linux/list.h>
#include <linux/semaphore.h>
#include <linux/slab.h>
#include <linux/kthread.h>
#define NTHREADS 200 //线程数
struct my_struct {
struct list_head list;
int id;
int pid;
};
static struct work_struct queue;
static struct timer_list mytimer;
static LIST_HEAD(mine);
static unsigned int list_len = 0;
static DEFINE_SEMAPHORE(sem);
static DEFINE_SPINLOCK(my_lock);
static atomic_t my_count = ATOMIC_INIT(0);
static long count = 0;
static int timer_over = 0;
static int sharelist(void *data);
static void kthread_launcher(struct work_struct *q);
static void start_kthread(void);
void qt_task(unsigned long data);
static int __init share_init(void)
{
int i;
printk(KERN_INFO"share list enter\n");
INIT_WORK(&queue, kthread_launcher);//初始化工作队列
setup_timer(&mytimer, qt_task, 0);//设置定时器
add_timer(&mytimer);//添加定时器
for (i = 0; i < NTHREADS; i++)//再启动200个内核线程来添加节点
start_kthread();
return 0;
}
static int sharelist(void * data)
{
struct my_struct *p;
if (count++ % 4 == 0)
printk("\n");
spin_lock(&my_lock); /*添加锁,保护共享资源*/
if (list_len < 100)
{
if ((p = kmalloc(sizeof(struct my_struct), GFP_KERNEL)) == NULL)
return -ENOMEM;
p->id = atomic_read(&my_count); /*原子变量操作*/
atomic_inc(&my_count);
p->pid=current->pid;
list_add(&p->list,&mine); /*向队列中添加新节点*/
list_len++;
printk("THREAD ADD:%-5d\t",p->id);
}
else
{/*队列超过定长则删除节点*/
struct my_struct *my = NULL;
my = list_entry(mine.prev, struct my_struct, list);
list_del(mine.prev); /*从队列尾部删除节点*/
list_len--;
printk("THREAD DEL:%-5d\t", my->id);
kfree(my);
}
spin_unlock(&my_lock);
return 0;
}
void kthread_launcher(struct work_struct *q)
{
kthread_run(sharelist,NULL,"hello_1"); /*创建内核线程*/
up(&sem);
}
static void start_kthread(void)
{
down(&sem);
schedule_work(&queue); /*调度工作队列*/
}
void qt_task(unsigned long data)
{
if(!list_empty(&mine)){
struct my_struct *i;
if(count++ % 4 == 0)
printk("\n");
i = list_entry(mine.next , struct my_struct ,list); /*取下一个结点*/
list_del(mine.next); /*删除结点*/
list_len --;
printk("TIMER DEL:% -5d\t", i->id);
kfree(i);
}
mod_timer(&mytimer,jiffies+1); /*修改定时器时间*/
}
static void __exit share_exit(void)
{
struct list_head *n , *p = NULL;
struct my_struct *my = NULL;
printk("\nshare list exit\n");
del_timer(&mytimer);
spin_lock(&my_lock); /*上锁,以保护临界区*/
list_for_each_safe(p,n,&mine){ /*删除所有节点,销毁链表*/
if(count++ %4 == 0)
printk("\n");
my = list_entry(p, struct my_struct,list); /*取下一个结点*/
list_del(p);
printk("SYSCALL DEL: %d\t",my->id);
kfree(my);
}
spin_unlock(&my_lock); /*开锁*/
printk(KERN_INFO"Over\n");
}
module_init(share_init);
module_exit(share_exit);
MODULE_LICENSE("GPL");
Makefile :
ifneq ($(KERNELRELEASE),)
obj-m := share.o
#obj-m 指编译成外部模块
else
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules:
make -C $(KERNELDIR) M=$(PWD) modules
endif
clean:
make -C $(KERNELDIR) M=$(PWD) clean
上面的代码是参考了一些问题解决方案之后成功运行的版本,常见的问题解决方案为:
- 在2.6.36版本后的内核就没有DECLARE_MUTEX这个宏了,取而代之的是DEFINE_SEMAPHORE宏
- SPIN_LOCK_UNLOCKED已被弃用自2.6.19,在2.6.39中删除。将static spinlock_t my_lock = SPIN_LOCK_UNLOCKED;
改为static DEFINE_SPINLOCK(my_lock); - kernel_thread没有EXPORT_SYMBOL
换成kthread_run
感谢阅读~~