4. 创建并唤醒一个内核线程:
t = kthread_run(thread_main, NULL, 'my_kthread%d', 0);
5. kthread接口实例Demo:
...
struct task_struct *t;
int thread_main(void *data)
{
printk('pid = %dn', t->pid);
while(1)
{
if(kthread_should_stop())
break;
/*printk('thread running.n');*/
msleep(3000);
}
return 123;
}
int __init test_init(void)
{
/**
* t = kthread_create(thread_main, NULL, 'my_thread%d', 0);
* if(IS_ERR(t))
* return PTR_ERR(t);
*
* wake_up_process(t);
*/
t = kthread_run(thread_main, NULL, 'my_thread%d', 0);
if(IS_ERR(t))
return PTR_ERR(t);
return 0;
}
void __exit test_exit(void)
{
int ret;
ret = kthread_stop(t);
printk('ret = %dn', ret);
}
...
五. workqueue接口:
1. 两种创建工作队列方式:
1. struct workqueue_struct *wq = create_workqueue('my_wq');
2. struct workqueue_struct *wq = create_singlethread_workqueue('my_wq');
2. 两种工作任务:
1. 普通工作任务: struct work_struct t; INIT_WORK(&t, fn);
2. 延时工作: struct delayed_work t; INIT_DELAYED_WORK(&t[i], work_main);
3. 两种提交普通工作的队列方式,返回值如果是0,表示任务已经在工作队列上了,还没有处理:
1. 将任务t放到wq工作队列上处理: queue_work(wq, &t);
2. 将任务t放到系统工作队列(系统已经建立的工作队列)上处理: schedule_work(&t);
4. 提交延时工作队列的方式: queue_delayed_work(wq, &t[i++], 3 * HZ));
5. 让工作队列尽快执行完: flush_workqueue(wq);
6. 销毁工作队列: destroy_workqueue(wq);
7. workqueue接口实例Demo:
...
#define NUM 2
//定义延时工作
struct delayed_work t[NUM];
struct workqueue_struct *wq;
void work_main(struct work_struct *work)
{
int i;
static int cnt;
for(i = 0; i < 3; i++)
{
printk('work, count = %dn', cnt++);
//在进程上下文执行,可以sleep
msleep(1000);
}
}
static irqreturn_t irq_handler(int irq, void *arg)
{
/*printk('key1 down.n');*/
static int i;
if(i == NUM)
i = 0;
/*if(!schedule_work(&t[i++]))*/
/*if(!queue_work(wq, &t[i++]))*/
if(!queue_delayed_work(wq, &t[i++], 3 * HZ))
printk('work is already in the queue.n');
return IRQ_HANDLED;
}
int __init test_init(void)
{
int ret, i;
//初始化工作结构
for(i = 0; i < NUM; i++)
/* INIT_WORK(&t[i], work_main); */
INIT_DELAYED_WORK(&t[i], work_main);
//创建工作队列
/*wq = create_workqueue('my_workqueue');*/
//只创建一个工作者线程
wq = create_singlethread_workqueue('my_workqueue');
if(!wq)
{
printk('workqueue create failed!n');
ret = -ENOMEM;
goto err0;
}
ret = request_irq(IRQ_EINT(26), irq_handler,
IRQF_TRIGGER_FALLING, 'KEY1', NULL);
if(ret)
{
printk('request_irq failed!n');
goto err1;
}
return ret;
err1:
destroy_workqueue(wq);
err0:
return ret;
}
void __exit test_exit(void)
{
free_irq(IRQ_EINT(26), NULL);
/*flush_workqueue(wq);*/
destroy_workqueue(wq);
}
...
六. tasklet接口:
1. 定义并初始化: struct tasklet_struct t; tasklet_init(&t, fn, data);
2. 提交任务, 提交的工作在软中断上下文执行: tasklet_schedule(t);
3. 对应加锁,解锁方法:
spin_lock_bh();
spin_unlock_bh();
4. tasklet接口实例Demo:
#include <linux/module.h>
#include #include #include #include #define DEV_NAME 'test' struct test_s { struct file_operations fops; struct tasklet_struct task; spinlock_t lock; int major; }; typedef struct test_s test_t; static int test_open(struct inode *inode, struct file *file) { test_t *p; p = container_of(file->f_op, test_t, fops); file->private_data = p; return 0; } static int test_close(struct inode *inode, struct file *file) { /*test_t *p = file->private_data;*/ return 0; } int critical(const char *s, spinlock_t *lock) { int i; unsigned long flag; static int cnt = 0; /*spin_lock(lock);*/ /*local_irq_disable();*/ /*local_irq_save(flag);*/ /*spin_lock_irq(lock);*/
上一篇:Samsung_tiny4412(驱动笔记09)----alloc_pages,kmalloc,vmalloc,kmem_cache,class
下一篇:Samsung_tiny4412(驱动笔记07)----spinlock,semaphore,atomic,mutex,completion,interrupt
推荐阅读最新更新时间:2026-03-13 00:32



Linux内核驱动笔记
三星2410开发板ALLEGRO BRD原文件
非常经典的关于LLC的杨波博士论文
XC6406PP60DL






京公网安备 11010802033920号