linux中断底半部机制对比(任务队列,工作队列,软中断)--由linux RS485引出的血案-ispsubb-ChinaUnix博客

合集下载

Linux中的中断概念以及处理方式--中断上下半部等

Linux中的中断概念以及处理方式--中断上下半部等

Linux中的中断概念以及处理方式--中断上下半部等与Linux设备驱动中中断处理相关的首先是申请与释放IRQ的API request_irq()和free_irq(),request_irq()的原型为:int request_irq(unsigned int irq,void (*handler)(int irq, void *dev_id, struct pt_regs *regs),unsigned long irqflags,const char * devname,void *dev_id);irq是要申请的硬件中断号;handler是向系统登记的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id参数将被传递;irqflags是中断处理的属性,若设置SA_INTERRUPT,标明中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程序不屏蔽;若设置SA_SHIRQ,则多个设备共享中断,dev_id在中断共享时会用到,一般设置为这个设备的device结构本身或者NULL。

free_irq()的原型为:void free_irq(unsigned int irq,void *dev_id);另外,与Linux中断息息相关的一个重要概念是Linux中断分为两个半部:上半部(tophalf)和下半部(bottom half)。

上半部的功能是"登记中断",当一个中断发生时,它进行相应地硬件读写后就把中断例程的下半部挂到该设备的下半部执行队列中去。

因此,上半部执行的速度就会很快,可以服务更多的中断请求。

但是,仅有"登记中断"是远远不够的,因为中断的事件可能很复杂。

因此,Linux引入了一个下半部,来完成中断事件的绝大多数使命。

下半部和上半部最大的不同是下半部是可中断的,而上半部是不可中断的,下半部几乎做了中断处理程序所有的事情,而且可以被新的中断打断!下半部则相对来说并不是非常紧急的,通常还是比较耗时的,因此由系统自行安排运行时机,不在中断服务上下文中执行。

Linux26内核中下半部分分析解析

Linux26内核中下半部分分析解析

目录
• 简介 • 历史&发展 • 实现机制
• • • 软中断 Tasklet 工作队列(new)
• 总结
bottom half(BH)
BH接口非常简单,它提供一个静态创建、 由32个bottom half组成的链表。上半部分 通过一个32位整数中的一位来识出哪个 bottom half可以执行。每个BH都在全局范 围内进行同步。即使分属于不同的处理器, 也不允许两个bottom half同时执行。 使用不灵活,大大降低多处理器的性能。
work quque
从2.5开始,BH接口最终被弃置,任务队列被 工作队列(work queue)接口取代。工作 队列可以把工作推后,交由一个内核线程 去执行—这个下半部分总会在进程上下文 执行。工作队列允许重新调度甚至睡眠。
2.6版本中,内核提供了三种不同形式的下 半部分实现机制:软中断、tasklet和工作队 列。
目录
• 简介 • 历史&发展 • 实现机制
• • • 软中断 Tasklet 工作队列(new)
q_action结构表示,定义在 <include/linux/interrupt.h>中。
Kernel/softirq.c中定义了一个包含有32个 softirq_action数组。每个被注册的软中断都 占据该数组中的一项,最多可有32个软中 断,2.6.24.1内核中可使用其中的8个。
线程的数据结构
• 结构中有一个cpu_workqueue_struct结构 组成的数组,每一项对应一个处理器。由 于每个处理器对应一个工作者线程,所以 对单台计算机来说,每个工作者线程对应 一个这样的cpu_workqueue_struct结构体。
所有的工作者线程都是用普通的内核线程 实现的,它们都要执行worker_tread().在它 初始化完以后,这个函数执行一个列循环 并开始休眠。当有操作被插入到队列里的 时候,线程就会被唤醒,以便执行这些操 作。当没有剩余的操作时,它又会继续休 眠。

Linux内核中断处理机制

Linux内核中断处理机制

Linux内核中断处理机制<什么是中断>计算停下当前处理任务,并保存现场,转⽽去处理其他是任务,当完成任务后再回到原来的任务中去。

<中断的分类>a:软中断软中断时执⾏中断指令产⽣的,软中断不⽤施加中断请求信号,因此中断的产⽣的不是随机的⽽是由程序安排的。

内核线程是实现软中断的助⼿。

b:硬中断硬中断时由外部硬件产⽣的,具有随机性。

<中断的实现>int request_irq(unsigned int irq,irq_handler_t handler,unsigned long intflags,const char devname, void *dev_id)解释:irq:申请的中断号。

handler:中断处理函数指针irqflags:中断处理属性,与上半段和下半段有关系devname:中断设备名字dev_id:与共享中断号有关系。

注:该函数的主要作⽤是在内核中的⼀个重要的结构体"irq_desc"中注册中断号与对应的中断处理函数。

<释放中断线>void free_irq(unsigned int irq ,void dev_id);注:⼀般操作硬件的端⼝都会调⽤ioremap()函数,该函数⽤来将计算实际的物理地址映射成虚拟地址,这样系统才能访问。

<中断处理机制之上半部分和下半部>a:Linux中中断处理是⼀种很霸道的东西,只要没有屏蔽中断,CPU就会⽴即相应。

为了加开处理的数据,Linux中通常将中断处理中的硬件相关的操作放在上半部分,耗时的操作放在下半部分——linux 内核⼀般将中断处理分为两不份:上半部(top_half)和下半部(bottom_half)。

b:上半部分⼀般调⽤中断处理函数,⼀进⼊中断处理函数就是进⾏相应的硬件操作,这些都是放在上半部分。

然后将耗时的操作放在下半部分中。

c:下半部分Linux中实现下半部分的处理有:softirq机制,tasklist机制(⼩任务⽚段),workqueue机制----tasklet将任务延迟到安全时间执⾏,每个tasklet都和⼀个函数相关联,当tasklet运⾏时,----该函数就被调⽤,并且tasklet可以调度⾃⼰。

linux中断处理上半部下半部实例

linux中断处理上半部下半部实例

linux中断处理上半部下半部实例Linux中断处理是操作系统中的重要概念之一,它负责处理外部设备发出的中断信号。

中断处理分为上半部和下半部,两者分别对应着紧急任务和延后处理任务。

本文将通过一个实例来详细介绍Linux中断处理的上半部和下半部。

在Linux系统中,中断是指外部设备向处理器发出的请求,要求处理器立即暂停当前的工作,转而去执行与该中断相关的处理程序。

中断的发生可以是硬件产生的,也可以是软件产生的。

无论是硬件中断还是软件中断,处理方式都遵循相同的原则,即中断处理程序分为上半部和下半部。

上半部是中断处理程序的核心部分,也是最紧急的部分。

当中断发生时,处理器首先执行上半部的代码。

上半部主要负责处理与中断直接相关的任务,如保存寄存器状态、处理中断请求、更新相关数据等。

上半部的执行时间应尽量短,因为在中断期间,处理器无法执行其他任务。

如果上半部执行时间过长,会导致系统响应缓慢,甚至影响其他紧急任务的执行。

下半部是中断处理程序的延后处理部分。

当上半部完成后,处理器会立即执行下半部的代码。

下半部主要负责一些较为复杂或耗时较长的任务,如更新数据结构、发送信号、唤醒进程等。

相比于上半部,下半部的执行时间可以更长一些,因为在执行下半部的同时,处理器可以继续执行其他任务。

为了更好地理解上半部和下半部的关系,我们可以以网络设备驱动程序为例。

当网络设备接收到数据包时,会触发一个中断信号。

操作系统会立即执行中断处理程序,即上半部。

在上半部中,操作系统会将接收到的数据包拷贝到内存中,并更新相关的数据结构。

然后,操作系统会调度一个延后处理的任务,即下半部,来进一步处理接收到的数据包。

下半部可以对数据包进行进一步的解析、处理和分发。

通过上下半部的协作,网络设备驱动程序可以高效地处理接收到的数据包,并及时地通知上层应用程序。

除了网络设备驱动程序,中断处理也广泛应用于其他领域。

比如,在实时系统中,中断处理可以用于处理实时事件,如传感器数据的采集、控制信号的发送等。

软中断—tasklet—工作队列

软中断—tasklet—工作队列

软中断/tasklet/工作队列______整理软中断、tasklet和工作队列并不是Linux内核中一直存在的机制,而是由更早版本的内核中的“下半部”(bottom half)演变而来。

下半部的机制实际上包括五种,但2.6版本的内核中,下半部和任务队列的函数都消失了,只剩下了前三者。

本文重点在于介绍这三者之间的关系。

(函数细节将不会在本文中出现,可以参考文献,点这里)(1)上半部和下半部的区别上半部指的是中断处理程序,下半部则指的是一些虽然与中断有相关性但是可以延后执行的任务。

举个例子:在网络传输中,网卡接收到数据包这个事件不一定需要马上被处理,适合用下半部去实现;但是用户敲击键盘这样的事件就必须马上被响应,应该用中断实现。

两者的主要区别在于:中断不能被相同类型的中断打断,而下半部依然可以被中断打断;中断对于时间非常敏感,而下半部基本上都是一些可以延迟的工作。

由于二者的这种区别,所以对于一个工作是放在上半部还是放在下半部去执行,可以参考下面四条:a)如果一个任务对时间非常敏感,将其放在中断处理程序中执行。

b)如果一个任务和硬件相关,将其放在中断处理程序中执行。

c)如果一个任务要保证不被其他中断(特别是相同的中断)打断,将其放在中断处理程序中执行。

d)其他所有任务,考虑放在下半部去执行。

(2)为什么要使用软中断?软中断作为下半部机制的代表,是随着SMP(share memory processor)的出现应运而生的,它也是tasklet实现的基础(tasklet实际上只是在软中断的基础上添加了一定的机制)。

软中断一般是“可延迟函数”的总称,有时候也包括了tasklet(请读者在遇到的时候根据上下文推断是否包含tasklet)。

它的出现就是因为要满足上面所提出的上半部和下半部的区别,使得对时间不敏感的任务延后执行,而且可以在多个CPU上并行执行,使得总的系统效率可以更高。

它的特性包括:a)产生后并不是马上可以执行,必须要等待内核的调度才能执行。

softirq(软中断)下半部中tasklet与workqueue的区别

softirq(软中断)下半部中tasklet与workqueue的区别

softirq(软中断)下半部中tasklet与workqueue的区别一、中断处理的tasklet(小任务)机制中断服务程序一般都是在中断请求关闭的条件下执行的,以避免嵌套而使中断控制复杂化。

但是,中断是一个随机事件,它随时会到来,如果关中断的时间太长,CPU就不能及时响应其他的中断请求,从而造成中断的丢失。

因此,Linux内核的目标就是尽可能快的处理完中断请求,尽其所能把更多的处理向后推迟。

例如,假设一个数据块已经达到了网线,当中断控制器接受到这个中断请求信号时,Linux内核只是简单地标志数据到来了,然后让处理器恢复到它以前运行的状态,其余的处理稍后再进行(如把数据移入一个缓冲区,接受数据的进程就可以在缓冲区找到数据)。

因此,内核把中断处理分为两部分:上半部(tophalf)和下半部(bottomhalf),上半部(就是中断服务程序)内核立即执行,而下半部(就是一些内核函数)留着稍后处理,首先,一个快速的“上半部”来处理硬件发出的请求,它必须在一个新的中断产生之前终止。

通常,除了在设备和一些内存缓冲区(如果你的设备用到了DMA,就不止这些)之间移动或传送数据,确定硬件是否处于健全的状态之外,这一部分做的工作很少。

下半部运行时是允许中断请求的,而上半部运行时是关中断的,这是二者之间的主要区别。

但是,内核到底什时候执行下半部,以何种方式组织下半部?这就是我们要讨论的下半部实现机制,这种机制在内核的演变过程中不断得到改进,在以前的内核中,这个机制叫做bottomhalf(简称bh),在2.4以后的版本中有了新的发展和改进,改进的目标使下半部可以在多处理机上并行执行,并有助于驱动程序的开发者进行驱动程序的开发。

下面主要介绍常用的小任务(Tasklet)机制及2.6内核中的工作队列机制。

小任务机制这里的小任务是指对要推迟执行的函数进行组织的一种机制。

其数据结构为tasklet_struct,每个结构代表一个独立的小任务,其定义如下:[cpp] view plain copy&lt;spanstyle="font-weight: normal;"&gt;struct tasklet_struct { struct tasklet_struct *next; /*指向链表中的下一个结构*/ unsignedlong state; /* 小任务的状态*/ atomic_tcount; /* 引用计数器*/ void(*func) (unsigned long); /* 要调用的函数*/ unsignedlong data; /* 传递给函数的参数*/ };&lt;/span&gt; 结构中的func域就是下半部中要推迟执行的函数,data是它唯一的参数。

linux中断处理上半部下半部实例

linux中断处理上半部下半部实例

linux中断处理上半部下半部实例Linux中断处理是操作系统中非常重要的一个功能,它负责处理硬件设备的中断请求。

中断处理过程可以分为上半部和下半部两个阶段。

本文将通过一个实例来详细介绍Linux中断处理的上半部和下半部。

让我们来了解一下什么是中断。

在计算机系统中,中断是指硬件设备向CPU发送信号,通知CPU需要进行处理的事件。

当CPU接收到中断信号时,会暂停当前正在执行的任务,并转而处理中断请求。

这样可以提高系统的响应速度和效率。

在Linux中,中断处理分为上半部和下半部。

上半部是指中断处理程序的第一阶段,它需要尽快地完成一些关键的任务,以确保系统的稳定性。

下半部是指中断处理程序的第二阶段,它可以在上半部完成的基础上进行更复杂、耗时的操作。

下面我们通过一个实例来说明中断处理的上半部和下半部。

假设我们有一个网络设备,它负责接收和发送网络数据包。

当有数据包到达时,设备会发送一个中断请求给CPU,通知CPU有数据包需要处理。

在中断处理的上半部,首先需要读取网络设备的状态寄存器,以确定中断的原因。

然后,根据中断的原因,执行相应的处理操作。

例如,如果是接收到数据包的中断,那么上半部需要将数据包从设备的接收缓冲区中读取出来,并且进行一些必要的校验和处理。

上半部的任务还包括更新设备的状态、清除中断标志等。

这些任务需要尽快完成,以确保系统的稳定性和实时性。

因此,在上半部的处理过程中,需要尽量避免长时间的延迟和阻塞操作。

当上半部的任务完成后,中断处理程序就会进入下半部。

下半部的任务可以是一些比较耗时的操作,例如将数据包交给上层协议栈进行处理、更新网络设备的缓冲区等。

由于下半部的任务可能会比较耗时,所以通常会通过软中断或工作队列的方式来延迟执行。

在Linux中,可以使用软中断来实现下半部的延迟执行。

软中断是一种由内核触发的中断,它可以在合适的时机执行下半部的任务。

通过软中断,可以将下半部的任务延迟到合适的时间点执行,以避免对系统的影响。

浅析Linux内核中的Bottom Half机制

浅析Linux内核中的Bottom Half机制

1然后 返 回 , 下 的工作 交 . 剩
给相 应的 B H来处 理 。当 内核每次 执行 完 d —R ( oIQ )
中的中断服务程序之后 , 或者 每次系统调用 结束之时 ,
o 函数 d b t m h l )得 到 触 发 ,它将 执 行相 应 的 o ot af(
_ _
b at e和 b _ s h cv i h ma 。 的 H
格。 因此它通 常是在 C U 开 中断 的条件下执 行的 。 P 但
是 .iu Ln x早期 实现 的 B t m H l机 制 B 函数接 口 ot a o f H
B 函数 接 口实 现 简 单 , 有 严 重 的 缺 陷 , 重 要 H 但 最
的两 个就是 :严 格 串行 化不 能利 用 S MP:只有 3 2个
较为严格 . 须在 中断请 求发生 后立 即或至 少在一 定 必
素 , 以确定 是否开 启/ 用 关闭 B 函数 。当执行 某硬 件 H
中断 服务 程 序 时 。 如果 需 要 执 行一 个 B 函数 , 件 H 硬 中断 服 务 的 T pHa o l 需 通 过 函数 mak b ( 将 f只 r— h )
用, 为此 , 早期 的 20内核后 续版 本义 对 B . H进 行 了扩 二 展, 引入 了 T s u u , 是一个 双 向队列链 表 。 akQ e e 它



队列的每个元 素都 有一 个 函数指 针及 其参 数 , 它 九
b at e h c v 中的相应 位设成 i
_
的 时间 限制 内完成 .为 了保 证这 种 处理 能原 子地 完 成 ,o a T pH l 常是在 C U 关 中断的 条件 下执 行的 。 f通 P
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1 / 7
b l o g . c h i n a u n i x . n e t / u i d 2 0 7 6 8 9 2 8 i d 5 0 7 7 4 0 1 . h t ml
1 5 6 1 6l i n u x
-l i n u x R S 4 8 5
i s p s u b b C h i n a U n i x
lwfbibi
D2002
chunhui_
2 / 7
b l o g . c h i n a u n i x . n e t / u i d 2 0 7 6 8 9 2 8 i d 5 0 7 7 4 0 1 . h t ml
1 5 6 1 6l i n u x
-l i n u x R S 4 8 5
i s p s u b b C h i n a U n i x
考/angle_birds/article/details/8448070
yzj_1988
64492407
紫易幼南
点击(此处)折叠或打开 1 . 2 . 3 . 4 . 5 . 6 . 7 . 8 . 9 . 1 0 . 1 1 . 1 2 . 1 3 . 1 4 . D E C L A R E _ W O R K ( s t r u c tw o r k _ s t r u c t,w o r k _ f u n c _ tf u n c ) ; I N I T _ W O R K ( s t r u c tw o r k _ s t r u c t* w o r k ,w o r k _ f u n c _ tf u n c ) ; I N I T _ D E L A Y E D _ W O R K ( s t r u c td e l a y e d _ w o r k* w o r k ,w o r k _ f u n c _ tf u n c ) ; i n ts c h e d u l e _ w o r k ( s t r u c tw o r k _ s t r u c t* w o r k ) ; i n ts c h e d u l e _ d e l a y e d _ w o r k ( s t r u c td e l a y e d _ w o r k* w o r k ,u n s i g n e dl o n gd e l a y ) ; i n ts c h e d u l e _ d e l a y e d _ w o r k _ o n ( s t r u c td e l a y e d _ w o r k* w o r k ,u n s i g n e dl o n gd e l a y ) ; s t r u c tw o r k q u e u e _ s t r u c t* c r e a t e _ w o r k q u e u e ( c o n s tc h a r* n a m e ) ; i n tq u e u e _ w o r k ( s t r u c tw o r k q u e u e _ s t r u c t* w q ,s t r u c tw o r k _ s t r u c t* w o r k ) ; i n tq u e u e _ d e l a y e d _ w o r k ( s t r u c tw o r k q u e u e _ s t r u c t* w q ,s t r u c td e l a y e d _ w o r k* w o r k , u n s i g n e dl o n gd e l a y ) ; v o i df l u s h _ s c h e d u l e d _ w o r k ( v o i d ) ; v o i df l u s h _ w o r k q u e u e ( s t r u c tw o r k q u e u e _ s t r u c t* w q ) ; i n tc a n c e l _ d e l a y e d _ w o r k ( s t r u c td e l a y e d _ w o r k* w o r k ) ; v o i dd e s t r o y _ w o r k q u e u e ( s t r u c tw o r k q u e u e _ s t r u c t* w q ) ;
文章存档 2015年 (4) 2014年 (4) 2012年 (7)
我的朋友
最近访客
liuyingj
yadunhah
headstro
工作队列,任务队列,软中断
工作队列 :Linux kernel中将工作推后执行的一种机制。这种机制和BH或Tasklets不同之处在于工作队 列是把推后的工作交由一个内核线程去执行,因此工作队列的优势就在于它允许重新调度甚至睡眠。工作 队列是2.6内核开始引入的机制,在2.6.20之后,工作队列的数据结构发生了一些变化。可以参
1 5 6 1 6l i n u x
-l i n u x R S 4 8 5
i s p s u b b C h i n a U n i x
Chinaunix首页 | 论坛 | 认证专区 | 博客
登录 | 注册
博文
ispsubb的ChinaUnix博客
After all ,tomorrow is another day !
在LINUX RS485的使用过程中,由于各种原因,最后不得不使用中断底半部机制的方法来进行实现此 功能。先讲两个小故事来描述一下,遇到的问题。也是因为自己对底半部机制理解得不透彻。这些故事的 前提都是在串口中断中,一定条件后去完成某件事情,但时间上不能超过5ms。 故事一,最开始想到的是用workqueue 。印象中workqueue 就是用来做这种事的,并且还记得可以延时 一段时间再来做。
点击(此处)折叠或打开 1 . 2 . 3 . I N I T _ W O R K ( & m y _ w q , ( v o i d( * )( v o i d * ) ) m y _ w q _ f u n c ) ; s c h e d u l e _ w o r k ( & m y _ w q ) ; / / s c h e d u l e _ d e l a y e d _ w o r k ( & m y _ w q , d e l a y ) ;
故事二,工作队列不行后,感觉底半部机制就实现不了,满足不了我们的要求。上网翻了一些资料,觉 得任务队列时效性应该比工作队列更好。就像买药的做广告一样,抱着试一试的态度尝试了一下。
最终这种方法实现了。但过程也是相当曲折。tasklet_schedule时效性可以达到,hi_schedule 更是完 美,感觉会牺牲系统性能。那么过程曲折在哪呢?刚开始以为搞好了,回家睡大觉,等我九点半到家,同 事打电话说不行,出问题了。单个串口没有问题,多个串口同时用的时候,前面打开的串口对应 的rs485 都不能正常使用。GPIO拉高后,就不低。而my_wq_func就是实现GPIO拉低的动作。最后的原因 是my_wq_func被多次调用,而其只响应最后一次。这个地方还得感谢这位老兄, /goodluckwhh/article/details/9003353 。tasklet 是一个特殊的函数, 它在软 中断上下文被调度。它可能被调度运行多次,但是tasklet调度不累积,也就是即使在tasklet被执行之前 请求了多次来执行该tasklet,它也只运行一次。不会有同一个tasklet的多个实例同时运行。但 是tasklet可以与SMP系统上的其他tasklet并行运行。因此, 如果多个tasklet会使用相同的资源, 它们必 须采取某类加锁来避免彼此冲突。除非tasklet重新激活自己,否则每次tasklet激活只会运行一次。最后 的解决方法就是将my_wq_func一个函数可以实现的内容,复制成了四个函数,问题就解决了。 故事讲完了,这时候该来分析分析理论上的底半部机制。前面的曲折,主要是因为自己对底半部机制的 一知半解。这里来着重分析一下任务队列,工作队列的区别,同时也COPY一些别人对软中断的理解,以备 后续查看
情况,我们要求小于5ms。
文章分类 全部博文 (15) translate (0) job and life (0) bootloader (0) android (0) C ASM …… (0) linux (15) arm (0) 未分配的博文 (0) 点击(此处)折叠或打开 1 . 2 . 3 . t a s k l e t _ i n i t ( & m y _ t a s k 0 , m y _ w q _ f u n c , ( u n s i g n e dl o n g )m y _ w q _ a r g ) ; t a s k l e t _ s c h e d u l e ( & m y _ t a s k 0 ) ; t a s k l e t _ h i _ s c h e d u l e ( & m y _ t a s k 0 ) ;
点击(此处)折叠或打开 1 . 2 . 3 . 4 . 5 . 6 . 7 . 8 . D E C L A R E _ T A S K L E T ( n a m e ,f u n c ,d a t a ) ; v o i dt a s k l e t _ i n i t ( s t r u c tt a s k l e t _ s t r u c t* t , v o i d( * f u n c ) ( u n s i g n e dl o n g ) ,u n s i g n e dl o n gd a t a ) ; v o i dt a s k l e t _ s c h e d u l e ( s t r u c tt a s k l e t _ s t r u c t* t ) ; v o i dt a s k l e t _ h i _ s c h e d u l e ( s t r u c tt a s k l e t _ s t r u c t* t ) ; v o i dt a s k l e t _ d i s a b l e ( s t r u c tt a s k l e t _ s t r u c t* t ) ; v o i dt a s k l e t _ d i s a b l e _ n o s y n c ( s t r u c tt a s k l e t _ s t r u c t* t ) ; v o i dt a s k l e t _ e n a b l e ( s t r u c tt a s k l e t _ s t r u c t* t ) ; v o i dt a s k l e t _ k i l l ( s t r u c tt a s k l e t _ s t r u c t* t ) ;
相关文档
最新文档