- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
从this链接粘贴的副本:
线程切换不需要内核模式特权。
用户级线程可以快速创建和管理。
内核线程通常比用户线程创建和管理慢。
在同一进程中将控制权从一个线程转移到另一个线程需要将模式切换到内核。
在阅读标准操作系统参考书时,我从未遇到过这些问题。尽管这些观点听起来合乎逻辑,但我想知道它们如何反映在Linux中。准确地说:
有人可以给出涉及用户线程和内核线程之间的上下文切换的详细步骤,以便我可以找到两者之间的步骤差异。
有人可以解释与实际上下文切换示例或代码的区别。可能涉及系统调用(在内核线程之间进行上下文切换的情况下)和涉及线程库的调用(在用户线程之间进行上下文切换的情况下)。
有人可以将我链接到处理上下文切换的Linux源代码行(例如github)。
我也怀疑为什么内核线程之间的上下文切换需要更改为内核模式。我们不是已经在内核模式下使用第一个线程了吗?
最佳答案
有人可以给出涉及用户线程和内核线程之间的上下文切换的详细步骤,以便我可以找到两者之间的步骤差异。
假设一个线程需要从文件中读取数据,但是该文件没有缓存在内存中,并且磁盘驱动器很慢,因此该线程必须等待。为了简单起见,我们还假设内核是整体的。
对于内核线程:
线程在库等中调用“ read()”函数;至少必须切换到内核代码(因为这将涉及设备驱动程序)。
内核将IO请求添加到磁盘驱动程序的“可能有许多未决请求的队列”中;意识到线程将需要等待直到请求完成,将线程设置为“阻塞的等待IO”并切换到其他线程(取决于全局线程优先级,该线程可能属于完全不同的进程)。内核返回到它切换到的任何线程的用户空间。
后来;磁盘硬件导致IRQ,IRQ导致切换回内核代码中的IRQ处理程序。磁盘驱动程序完成了对(当前被阻止的)线程所做的工作,并取消了对该线程的阻止。在这一点上,内核可能决定切换到“现在不受阻塞”的线程。然后内核返回到“现在不受阻塞”线程的用户空间。
对于用户线程:
线程在库等中调用“ read()”函数;至少必须切换到内核代码(因为这将涉及设备驱动程序)。
内核将IO请求添加到磁盘驱动程序的“可能有许多未决请求的队列”中;意识到线程将需要等待直到请求完成,但是无法解决这个问题,因为某些傻瓜决定通过在用户空间中进行线程切换来使一切变得更糟,因此内核返回“ IO请求已排队,并返回用户空间” “ 状态。
切换回用户空间无意义的额外开销之后;用户空间调度程序执行内核可能完成的线程切换。此时,用户空间调度程序将告诉内核它无事可做,并且您将有更多无意义的额外开销切换回内核。或用户空间调度程序将线程切换到同一进程中的另一个线程(这可能是错误的线程,因为不同进程中的线程具有更高的优先级)。
后来;磁盘硬件导致IRQ,IRQ导致切换回内核代码中的IRQ处理程序。磁盘驱动程序完成了对(当前阻塞的)线程必须执行的工作;但是内核无法执行线程切换来解除线程阻塞,因为一些傻瓜决定通过在用户空间中进行线程切换来使一切变得更糟。现在我们有一个问题-内核如何通知用户空间调度程序IO已经完成?为了解决这个问题(没有任何“运行零线程的用户空间调度程序不断轮询内核”的混乱),您必须具有某种“内核将IO完成的通知放在某种队列中,并且(如果进程处于空闲状态)唤醒进程” ”(单独)将比仅在内核中执行线程切换要昂贵。当然,如果进程不是空闲的,那么用户空间中的代码将不得不轮询其通知队列,以了解“ IO完成通知”是否到达/何时到达,这将增加延迟和开销。无论如何,经过大量愚蠢的,毫无意义的和可避免的开销之后;用户空间调度程序可以执行线程切换。
有人可以解释与实际上下文切换示例或代码的区别。可能涉及系统调用(在内核线程之间进行上下文切换的情况下)和涉及线程库的调用(在用户线程之间进行上下文切换的情况下)。
实际的低级上下文切换代码通常以以下内容开头:
根据堆栈上的调用约定保存被“调用者保留”的寄存器
将当前堆栈顶部保存在属于旧线程的某种“线程信息结构”中
从属于新线程的某种“线程信息结构”中加载新的堆栈顶部
根据调用约定弹出“保留调用者”的寄存器
返回
然而:
通常(对于现代CPU)有相对大量的“ SIMD寄存器状态”(例如,对于支持AVX-512的80x86,我认为它的容量超过4 KiB)。 CPU制造商通常有一种机制来避免保留状态的一部分(如果未更改),并且(可选)将状态的(部分)加载推迟到实际使用为止(如果不实际使用,则完全避免使用)。所有这些都需要内核。
如果这是一个任务切换器,而不仅仅是用于线程切换,则可能需要在其顶部添加某种“如果虚拟地址空间需要更改{更改虚拟地址空间}”
通常,您希望跟踪统计信息,例如线程已使用了多少CPU时间。这需要某种“ thread_info.time_used += now() - time_at_last_thread_switch;
”;当“进程切换”与“线程切换”分开时,这变得困难/难看。
通常,在线程切换期间可能需要保存/加载其他状态(例如,指向线程本地存储的指针,用于性能监控和/或调试的特殊寄存器等)。通常,无法在用户代码中直接访问此状态。
通常,您还希望将计时器设置为在线程使用过多时间时到期;要么是因为您正在执行某种“时间多路复用”(例如,循环调度程序),要么是因为它需要一个协作的调度程序,在这种情况下,您需要某种“在无响应的情况下5秒钟后终止此任务,以防它进入无限循环永远”的安全防护。
这仅仅是隔离中的低级任务/线程切换。几乎总是有更高级别的代码来选择要切换的任务,处理“线程使用了过多的CPU时间”等。
有人可以将我链接到处理上下文切换的Linux源代码行(在github上说)
有人可能做不到。这不是一行。每个不同的体系结构都有很多行汇编,外加额外的高级代码(用于计时器,支持例程,“选择要切换到的任务”代码,用于异常处理程序以支持“惰性SIMD状态加载”的...) ;大概所有这些加起来大约有1万行代码,分布在50个文件中。
我也怀疑为什么内核线程之间的上下文切换需要更改为内核模式。我们不是已经在内核模式下使用第一个线程了吗?
是;当您发现需要进行线程切换时,通常您已经在内核代码中。
很少/有时(主要是由于属于同一进程的线程之间的通信-例如,同一进程中的2个或多个线程试图同时获取相同的互斥体/信号量;或者线程互相发送数据并等待数据互相到达)内核不参与;在某些情况下(这几乎总是大规模的设计失败,例如极端的锁争用问题,无法使用“工作线程池”来限制所需的线程数等),这可能是导致线程切换的主要原因,因此在用户空间中进行线程切换可能是有益的(例如,作为大规模设计失败的解决方法)。
关于linux - 内核线程与用户线程之间的上下文切换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57410024/
在为 Web 应用程序用例图建模时,为用户可以拥有的每个角色创建一个角色是否更好?或拥有一个角色、用户和一个具有特权的矩阵? guest < 用户 < 版主 < 管理员 1: guest 、用户、版主
我无法使用 Elixir 连接到 Postgres: ** (Mix) The database for PhoenixChat.Repo couldn't be created: FATAL 28P
这个问题已经有答案了: Group by field name in Java (7 个回答) 已关闭 7 年前。 我必须编写一个需要 List 的方法并返回 Map> . User包含 Person
感谢您的帮助,首先我将显示代码: $dotaz = "Select * from customers JOIN contracts where customers.user_id ='".$_SESS
我只想向所有用户中的一个用户显示一个按钮。我尝试了 orderByKey() 但没有成功! 用户模型有 id 成员,我尝试使用 orderByChild("id") 但结果相同! 我什至尝试了以下技巧
我们在工作中从 MongoDB 切换到 Postgres,我正在建立一个 BDR 组。 在这一步,我正在考虑安全性并尽可能锁定。因此,我希望设置一个 replication 用户(角色)并让 BDR
export class UserListComponent implements OnInit{ users; constructor(private userService: UserS
我可以使用 Sonata User Bundle 将 FOS 包集成到 sonata Admin 包中。我的登录功能正常。现在我想添加 FOSUserBundle 中的更改密码等功能到 sonata
在 LinkedIn 中创建新应用程序时,我得到 4 个单独的代码: API key 秘钥 OAuth 用户 token OAuth 用户密码 我在 OAuth 流程中使用前两个。 的目的是什么?最后
所以..我几乎解决了所有问题。但现在我要处理另一个问题。我使用了这个连接字符串: SqlConnection con = new SqlConnection(@"Data Source=.\SQLEX
我有一组“用户”和一组“订单”。我想列出每个 user_id 的所有 order_id。 var users = { 0: { user_id: 111, us
我已经为我的Django应用创建了一个用户模型 class User(Model): """ The Authentication model. This contains the u
我被这个问题困住了,找不到解决方案。寻找一些方向。我正在用 laravel 开发一个新的项目,目前正致力于用户认证。我正在使用 Laravels 5.8 身份验证模块。 对密码恢复 View 做了一些
安装后我正在使用ansible配置几台计算机。 为此,我在机器上本地运行 ansible。安装中的“主要”用户通常具有不同的名称。我想将该用户用于诸如 become_user 之类的变量. “主要”用
我正在尝试制作一个运行 syncdb 的批处理文件来创建一个数据库文件,然后使用用户名“admin”和密码“admin”创建一个 super 用户。 到目前为止我的代码: python manage.
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 6 年前。 Improv
我已在 Azure 数据库服务器上设置异地复制。 服务器上运行的数据库之一具有我通过 SSMS 创建的登录名和用户: https://learn.microsoft.com/en-us/azure/s
我有一个 ionic 2 应用程序,正在使用 native FB Login 来检索名称/图片并将其保存到 NativeStorage。流程是我打开WelcomePage、登录并保存数据。从那里,na
这是我的用户身份验证方法: def user_login(request): if request.method == 'POST': username = request.P
我试图获取来自特定用户的所有推文,但是当我迭代在模板中抛出推文时,我得到“User”对象不可迭代 观看次数 tweets = User.objects.get(username__iexact='us
我是一名优秀的程序员,十分优秀!