写到一半,发现一个好贴,哈哈
https://www.cnblogs.com/zzb-Dream-90Time/p/6476018.html
与工作队列相关的主要数据结构是名为 workqueue_struct的描述符,它包含一个有NR_CPUS(CPU最大数量)个元素的数组。
每个元素都是cpu_workqueue_struct类型的描述符:
cpu_workqueue_struct结构 | |
字段名 | 描述 |
lock | 保护该数据结构的自旋锁 |
remove_sequence | flush_workqueue()使用的序列号 |
insert_sequence | flush_workqueue()使用的序列号 |
worklist | 挂起链表(双向链表)的头结点 |
more_work | 等待队列,其中的工作者线程因等待更多的工作而处于睡眠状态 |
work_done | 等待队列,其中的进程由于等待工作队列被刷新而处于睡眠状态 |
wq | 指向 workqueue_struct结构的指针,其中包含该描述符 |
thread | 指向结构中工作者线程的进程描述符指针 |
run_depth | run_workqueue()当前的执行深度(当工作队列链表中的函数阻塞时,这个字段的值会变得比1大) |
worklist字段是双向链表的头,该链表集中了工作队列中的所有挂起函数,挂起函数用work_struct数据结构表示:
work_struct结构 | |
---|---|
字段名 | 描述 |
pending | 如果函数已经在工作队列链表中,该字段值设为1,否则设为0 |
entry | 指向挂起函数链表前一个或后一个元素的指针 |
func | 挂起函数的地址 |
data | 传递给挂起函数的参数,是一个指针 |
wq_data | 通常是指向cpu_workqueue_struct描述符的父结点的指针 |
timer | 用于延迟挂起函数执行的软定时器 |
create_workqueue("foo")函数接收一个字符串作为参数,返回新创建工作队列的workqueue_struct描述符的地址。该函数还创建n个工作者线程(n是当前系统中有效运行的CPU的个数),并根据传递给函数的字符串为工作者线程命名,如:foo/0,foo/1等等。 create_singlethread_workqueue()函数与之相似,但不管系统中有多少个cpu, create_singlethread_workqueue()函数都只创建一个工作者线程。内核调用 destroy_workqueue()函数撤消工作队列,它接收指向 workqueue_struct数组的指针作为参数。
struct semaphore
{
count //大于0:资源空闲;等于0:资源忙,没有等待进程;小于0:资源忙,至少有一个等待进程。
wait //存放等待队列(等待进程队列)链表的地址。
sleepers //存放是否有一些进程在信号量上睡眠的标志:如果没有进程在信号量等待队列上睡眠,
//则改值为0,否则置为1。
}
init_MUTEX() 函数把count字段设置成1
init_MUTEX_LOCKED() 函数把count字段设置成0
释放内核信号量:调用up()函数,增加count字段的值,如果count小于等于0,调用__up()函数换新一个睡眠进程。
获取内核信号量:调用down()函数,减少count字段的值,如果count大于等于0,当前进程获得信号量,否则,当前进程挂起。把一些寄存器内容保存在栈中,然后调用__down()函数。
down()函数的主要任务是挂起当前进程,直到信号量被释放。几种典型的情况:
MUTEX 信号量打开(count等于1,sleepers等于0)
MUTEX 信号量关闭,没有睡眠进程(count等于0,sleepers等于0)
MUTEX 信号量关闭,有其他睡眠进程(count等于-1,sleepers等于1)
down_trylock()函数在资源忙时会立即返回。
down_interruptible()函数广泛用于设备驱动中,睡眠进程在获得需要的资源之前被另一个信号唤醒,则该函数会增加count字段的值并返回-EINTR,而正常结束时返回0;因此,在返回值为-EINTR时,驱动程序可以放弃I/O操作。
struct rw_semaphore
{
count // 两个16位计数器。高16位以二进制补码形式存放非等待写者进程的总数和等待的
// 写内核控制路径数。低16位存放非等待读者和写者进程的总数。
wait_list // 指向等待进程的链表
wait_lock // 一个用于保护等待队列链表喝rw_semaphore结构的自旋锁
}
inti_rwsem()函数初始化rw_semaphore结构,把count字段置为0,wait_lock自旋锁置为未锁,把wait_list置为空链表。
down_read() 获取读信号量;
down_write()获取写信号量;
up_read()释放读信号量;
up_write()释放写信号量;
down_read_trylock()非阻塞式获取读信号量;
down_write_trylock()非阻塞式获取写信号量;
downgrade_write()自动把写锁转换成读锁。
疑问:
“如果eflags寄存器的IF标志被清0,宏irqs_disabled()返回1;如果IF标志被设置,改宏也返回1。”
为什么都返回1呢?
timer_opts数据结构
字段名 | 说明 |
name | 标识定时器源的一个字符串 |
mark_offset | 记录上一个节拍的准确时间,由时钟中断处理程序调用 |
get_offset | 返回自上一个节拍开始所经过的时间 |
monotonic_clock | 返回自内核初始化开始所经过的纳秒数 |
delay | 等待指定数目的“循环” |