Linux内核多线程与中断处理

本文深入探讨Linux下线程创建方法,包括kernel_thread()和kthread_run()的使用,并详细解析Linux同步机制,如semaphore、mutex、spinlock、rwlock及atomic变量等,同时介绍timer和中断上下文处理机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Linux创建线程使用kernel_thread(),kthread_run()

#include <linux/kthread.h>
#include <linux/module.h>

#ifndef SLEEP_MILLI_SEC
#define SLEEP_MILLI_SEC(nMilliSec)  \
do { \
	long timeout = (nMilliSec) * HZ / 1000; \
	while(timeout > 0) \
	{ \
		timeout = schedule_timeout(timeout); \
	} \
}while(0);
#endif


static struct task_struct * MyThread = NULL;

static int MyPrintk(void *data)
{
	char *mydata = kmalloc(strlen(data)+1,GFP_KERNEL);
	memset(mydata,'\0',strlen(data)+1);
	strncpy(mydata,data,strlen(data));
	while(!kthread_should_stop())
	{
		SLEEP_MILLI_SEC(1000);
		printk("%s\n",mydata);
	}
	kfree(mydata);
	return 0;
}
static int __init init_kthread(void)
{
	MyThread = kthread_run(MyPrintk,"hello world","mythread");
	return 0;
}
static void __exit exit_kthread(void)
{
	if(MyThread)
	{
		printk("stop MyThread\n");
		kthread_stop(MyThread);
	}
}
module_init(init_kthread);
module_exit(exit_kthread);
MODULE_AUTHOR("MallocFree");

sudo cat /proc/kmsg

Linux的同步

struct semaphore,struct mutex,completion(event),spinlock_t,rwlock_t,atomic variables

semaphore

void sema_init(struct semaphore *sem,int val);
DEFINE_SEMAPHORE(name)

void down(struct semaphore *sem);
down_interruptible()//可以唤醒
down_trylock()//不会睡眠

void up(struct semaphore *sem)

mutex

static DEFINE_MUTEX(mymutex);
mutex_lock(&mymutex);
g_i++;
mutex_unlock(&mymutex);
mutex_lock_interruptible()//可以唤醒
mutex_trylock()//不会睡眠

SPINLOCK

spinlock_t my_lock=SPIN_LOCK_UNLOCKED;
spin_init(&my_lock);
spin_lock(&my_lock);
g_i++;
spin_unlock(&my_lock);

rwlock

与SPINLOCK用法一样

rwlock_t my_lock=RW_LOCK_UNLOCKED;
rwlock_t my_lock;
spin_init(&my_lock);
read_lock(&my_lock);
g_i++;
read_unlock(&my_lock);

 struct completion

类似windows的event

//定义和初始化
struct completion my_completion;
init_completion(&my_completion);
//1.wait
wait_for_completion(&my_completion);
//2.完成
complete(&my_completion);//唤醒一个
complete_all(&my_completion);

原子操作

atomic_t v;
void atomic_set(atomic_t ,int i);//v=i
atomic_t v=ATOMIC_INIT(0);//v=0
int x=atomic_read(v);
......

timer

timer_list s_timer;
init_timer(&s_timer);

内核中断上半部与下半部机制

为了最大程度避免中断处理时间过长,而导致中断丢失,把一些在中断处理中不是非常紧急的任务放在后面执行,让中断尽快返回。

下半部机制
softirq
Tasklets
Workqueues

上半部与下半部区别

指中单处理程序,下半部是可以延后执行任务。

static void tasklet_handler(unsigned logn value)
{
    printk("tasklet_handler");
}

tasklet_stuct my_tasklet;
static unsigned long data=0;
tasklet_init(&my_tasklet,tasklet_handler,data);
tasklet_schedule(&my_tasklet);//放入调度队列
//依然处于中断上下文,但是开中断可以响应其他中断

还有工作队列workqueues,不是中断上下文

软中断和tasklet,workqueue

软中断不是马上可以执行,必须内核调度,不能被自己打断,只能被硬件中断打断

可以并发运行在多个cpu上,所以必须可重入,需要使用自旋锁来保护。

tasklet:

因为软中断必须可重入,有时候应用只需要单核,没必要设计重入,所以设计了tasklet

tasklet只能运行在一个cpu上,不能并行,只能串行

多个不同tasklet可以运行在多个cpu

软中断静态分配。

workqueue:

上面两个运行在中断上下文,导致不能睡眠阻塞,中断上下文在内核态,没有进程切换,所以如果中断睡眠阻塞无法退出,导致内核僵死,但可阻塞函数不能在中断上下文实现,必须在进程上下文,所以2.6版后内核,出现在内核运行的工作队列。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值