解析Linux内核的同步与互斥机制(二)

释放双眼,带上耳机,听听看~!

全局或者在栈中定义一个wait_queue_t类型变量的同时对其初始化,这保证了系统的可靠性,避免因用户忘记初始化时导致的问题。通用的初始化宏,tsk为任意指针。分两步:

  1. 内部宏__WAITQUEUE_INITIALIZER初始化相应成员;当wq内嵌在别的结构体中时,此宏很重要,提高了可移植性;

  2. 提供给外部的接口,定义一个变量,并将第一步的结果赋值给该变量。

static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)

{

q->flags = 0;

q->private = p;

q->func = default_wake_function;

}

动态初始化一个等待队列入口项,将其和当前进程关联起来,以便唤醒当前进程。

2.1.3 数据结构设计规则

今后凡遇到新设计一类结构体,若此类结构体变量必须初始化且有相对集中的操作,则应提供以下两个操作接口:

a) 定义新建一个结构体变量,并初始化之;

b) 动态初始化一个已经分配内存的该类变量

为了适应在堆栈及全局等任意地方分配的该变量,其应该接收指向该类变量的指针。

2.2 陈旧sleep_on系列

//初始化一个wait_queue_t

#define SLEEP_ON_VAR \

unsigned long flags; \

wait_queue_t wait; \

init_waitqueue_entry(&wait, current);

//添加到队列中

#define SLEEP_ON_HEAD \

spin_lock_irqsave(&q->lock,flags); \

__add_wait_queue(q, &wait); \

spin_unlock(&q->lock);

//从队列中删除

#define SLEEP_ON_TAIL \

spin_lock_irq(&q->lock); \

__remove_wait_queue(q, &wait); \

spin_unlock_irqrestore(&q->lock, flags);

SLEEP_ON_VAR、 SLEEP_ON_HEAD及SLEEP_ON_ TAIL总是同时出现,不可分割。上述宏不是函数,只是连续的表达式而已,因为函数就将他们隔离开来了,函数他退出后变量就无意义了。也不能写成 do――while的多语句宏,变量定义离开“{}”后就没有意义了。是为了编写代码更清晰明了,同时避免多写字,实际上就是代码封装复用。

void fastcall __sched interruptible_sleep_on(wait_queue_head_t *q)

{

SLEEP_ON_VAR //注意没“;”

current->state = TASK_INTERRUPTIBLE;

SLEEP_ON_HEAD

schedule(); //此处可能出问题

SLEEP_ON_TAIL

}

EXPORT_SYMBOL(interruptible_sleep_on);

添加到队列和从队列中删除由同一个模块做,符合模块设计规则,减小了耦合性。

唤醒的wakeup只负责改变进程状态,进程重新获得cpu后从队列中删除。

long fastcall __sched

interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)

{

SLEEP_ON_VAR

current->state = TASK_INTERRUPTIBLE;

SLEEP_ON_HEAD

timeout = schedule_timeout(timeout);

SLEEP_ON_TAIL

return timeout;

}

EXPORT_SYMBOL(interruptible_sleep_on_timeout);

void fastcall __sched sleep_on(wait_queue_head_t *q)

{

SLEEP_ON_VAR

current->state = TASK_UNINTERRUPTIBLE;

SLEEP_ON_HEAD

schedule();

SLEEP_ON_TAIL

}

EXPORT_SYMBOL(sleep_on);

long fastcall __sched sleep_on_timeout(wait_queue_head_t *q, long timeout)

{

SLEEP_ON_VAR

current->state = TASK_UNINTERRUPTIBLE;

SLEEP_ON_HEAD

timeout = schedule_timeout(timeout);

SLEEP_ON_TAIL

return timeout;

}

EXPORT_SYMBOL(sleep_on_timeout);

给TA打赏
共{{data.count}}人
人已打赏
安全运维

WordPress网站专用docker容器环境带Waf

2020-7-18 20:04:44

安全运维

运维安全-Gitlab管理员权限安全思考

2021-9-19 9:16:14

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索