Skip to content

Instantly share code, notes, and snippets.

@YaoC
Created May 14, 2017 09:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save YaoC/3c97be3d70f262e5d48ae6e838c65338 to your computer and use it in GitHub Desktop.
Save YaoC/3c97be3d70f262e5d48ae6e838c65338 to your computer and use it in GitHub Desktop.
Linux内核第四次作业
/**
* @Author: ChengYao
* @Created time: 2017年5月14日 下午5:08
* @Email: chengyao09@hotmail.com
* @Description: Linux内核第四次作业
*
*/
/**
* [thread_writer description]
* 每0.1秒向链表插入一个节点
* @param d [description]
* @return [description]
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/rculist.h>
#include <linux/delay.h>
#include <linux/rcupdate.h>
#include <linux/sched.h>
#include <linux/kthread.h>
static struct task_struct *tskwriter;
static struct task_struct *tskreader1;
static struct task_struct *tskreader2;
struct ShareData
{
int data;
struct list_head list;
};
// 初始化头节点
LIST_HEAD(head);
static int thread_writer(void *d)
{
int count = 0;
while( !kthread_should_stop() ){
// 控制打印日志的数量
if(count<=50){
// 为新节点分配内存
struct ShareData *p = kmalloc(sizeof(*p),GFP_KERNEL);
p->data = count;
// 调用 list_add_rcu 将新节点加入链表
list_add_rcu(&p->list,&head);
printk(KERN_EMERG "thread_writer: %d times\n", ++count);
}
// 休眠0.1秒
msleep(100)
}
}
/**
* [thread_reader description]
* 每0.1秒打印一个节点
* @param d [description]
*/
static void thread_reader(void* d)
{
int count = 0;
struct ShareData *p = NULL;
while( !kthread_should_stop() ){
// 控制打印日志的数量
if(count<=50){
count++;
// rcu_read_lock 和 rcu_read_unlock 保持临界区
rcu_read_lock();
// list_for_each_entry_rcu 打印每个节点
list_for_each_entry_rcu(p, &head,list){
if(p){
printk(KERN_EMERG "reader%d :data=:%d\n",current->pid,p->data);
}
}
rcu_read_unlock();
}
// 休眠0.1秒
msleep(100)
}
}
/**
* [start_module description]
* 在模块中创建一个写者线程和两个读者线程
* 写者线程负责向链表中加入节点
* 两个读者线程并发打印链表的所有节点
*/
static int __init start_module(void)
{
// 创建写者线程
tskwriter = kthread_run(thread_writer,NULL,"%s","writer");
if (IS_ERR(tskwriter))
{
printk(KERN_EMERG "create tskwriter kthread failed !\n");
}else{
printk(KERN_EMERG "create tskwriter kthread ok !\n");
}
// 创建第一个读者线程
tskreader1 = kthread_run(thread_reader,NULL,"%s","reader1")
if (IS_ERR(tskreader1))
{
printk(KERN_EMERG "create tskreader1 kthread failed !\n");
}else{
printk(KERN_EMERG "create tskreader1 kthread ok !\n");
}
// 创建第二个读者线程
tskreader2 = kthread_run(thread_reader,NULL,"%s","reader2")
if (IS_ERR(tskreader2))
{
printk(KERN_EMERG "create tskreader2 kthread failed !\n");
}else{
printk(KERN_EMERG "create tskreader2 kthread ok !\n");
}
return 0;
}
/**
* [end_module description]
* 退出模块,结束三个线程
* @return [description]
*/
static void __exit end_module(void)
{
//
if(!IS_ERR(tskwriter)){
kthread_stop(tskwriter);
printk(KERN_EMERG "thread tskwriter end\n");
}
if(!IS_ERR(tskreader1)){
kthread_stop(tskreader1);
printk(KERN_EMERG "thread tskreader1 end\n");
}
if(!IS_ERR(tskreader2)){
kthread_stop(tskreader2);
printk(KERN_EMERG "thread tskreader2 end\n");
}
}
module_init(start_module);
module_exit(end_module);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment