【问题标题】:Context switch in the middle of a system call系统调用中间的上下文切换
【发布时间】:2020-11-01 18:47:06
【问题描述】:

假设我们在进程中有 2 个线程。 现在我们运行以下代码:

read(fd, buf, 10);

其中 fd 是线程间共享的文件描述符(比如静态),buf 是线程间不共享的数组(局部变量)。

现在,假设文件为 1KB,文件中的前 10 个字符是“AAAAAAAAAA”,其余的都是“B”。 (“BBBBBB……”)。

现在如果我们只有一个处理器,如果在每个线程中打印它们,buf 的输出是什么?

我知道答案是其中一个数组总是只有 A 而另一个只有 B,但我不完全理解为什么,因为我认为在这个系统的中间可能有一个上下文切换 -调用(读取),然后两个 buf 中都会有 A。

上下文切换甚至可能发生在系统调用的中间吗?如果是这样,您认为 buf 在执行结束时会发生什么?

【问题讨论】:

  • 通过内核、I/O 请求块、驱动程序、硬件接口、驱动控制器和缓存的路径是漫长而曲折的。此外,应用了足够的锁定来管理此类“重叠”请求。在我工作过的每个系统上,无论何时发生任何可能改变正在运行的线程集的中断,用户线程都会认为调用是序列化的。
  • 请记住,大多数磁盘读取的字节粒度要大得多。即使您读取了 10 个字节,也很可能读取了 512 个字节或更多。
  • @MartinJames 你能否发表一个完整的解释,说明为什么这个调用会在中断的情况下被序列化?
  • 我不知道read这个函数,但是貌似the write function was not thread-safe在2006年的linux中。我不知道现在是什么情况。
  • 这能回答你的问题吗? C read and thread safety (linux)

标签: c linux-kernel operating-system


【解决方案1】:

现代磁盘无法以 10 字节粒度执行读取和写入,而是以扇区为单位执行读取和写入,传统上硬盘驱动器 (HDD) 为 512 字节。
将 10 个字符复制到线程缓冲区的速度非常快,但不能保证在上下文切换之前。

一个简单的程序可以让两个线程打印到同一个控制台,一个打印+,另一个打印-。在第一个 - 之前检查有多少 +。 无论如何,对于最初的问题,将数组的大小更改为 1024 并从 1024 A 开始,您很可能会看到不同之处。

【讨论】:

    猜你喜欢
    • 2012-02-11
    • 1970-01-01
    • 2021-11-18
    • 2016-11-06
    • 2023-03-03
    • 1970-01-01
    • 2021-12-22
    • 2015-03-16
    • 1970-01-01
    相关资源
    最近更新 更多