【问题标题】:How is syscall typically implemented系统调用通常是如何实现的
【发布时间】:2016-03-04 14:41:30
【问题描述】:

我正在实现与简单操作系统非常相似的东西,但我很难掌握系统调用的实际含义:
首先 - 在进程系统中哪个线程通常 *执行中断例程(系统调用内核函数) - 内核线程之一或用户空间线程被赋予临时特权和例程地址?
如何在用户空间中实现系统调用机制 - 以下任何一项是否与引擎盖下发生的情况大致匹配?
实施 A:

//equivalent to assembly
//MOV EAX sys_call_no
//INT 0x80
void* interrupt(int service, void* args)
{
   return kernel::int_vector[service](args);
}

实施 B:

//equivalent to assembly
//MOV EAX sys_call_no
//INT 0x80
void* interrupt(int service, void* args, void* ret)
{
   kernel::intr_queue.push_back_syncd(interrupt_context(){kernel::int_vector[service], args, ret});
   waitForServiceCompleted();
   return ret;
}
//in kernel thread
while(true)
{
  while(!intr_queue.isEmpty())
  {
    auto context = intr_queue.pop();
    context.ret = context.func(context.args);
    notifyDone();
  }
}

C:我完全不明白——它的工作方式完全不同。
* 通常我指的是当前最常见的桌面系统,例如 window 7/8 或最新的 Ubuntu 发行版
注意:抱歉,如果这不是发布此问题的正确 SE 网站 - 请评论我以移动它

【问题讨论】:

    标签: linux windows multithreading operating-system


    【解决方案1】:

    实施 A 通常是如何工作的。操作系统主要将自己的线程仅用于不涉及直接响应特定进程请求的任务。当一个进程进行典型的系统调用时,该线程会切换到内核堆栈并开始在内核上下文中运行内核代码。

    【讨论】:

    • 谢谢 - 所以没有像系统调用队列这样的东西吗? (甚至不是例如从硬盘读取?)我很困惑存储在寄存器中的系统调用参数是如何传递给内核的,这很好地解释了线程只保留它们。
    • @wondra 肯定有各种各样的请求队列。但是像这样的系统调用被分成几部分。首先,发出请求。然后,当且仅当需要时,线程将在内核空间中等待请求完成。例如,磁盘中断可能会在它劫持的任何线程中得到服务,然后它可能会释放由于read 系统调用而暂时阻塞在内核空间中的线程。这使得不需要阻塞的系统调用尽可能便宜。
    • 所以他们被阻塞在内部内核空间?很高兴知道-它确实可以解决问题。但这又带来了另一个问题,如果另一个线程得到磁盘中断,什么机制会通知原来的线程?查找文件描述符 PCB 的所有者,如果它被阻塞,它会唤醒它(这也意味着在 PCB 中有互斥锁)?
    • 操作系统有一个线程在内核空间阻塞并被另一个线程解除阻塞的机制。通常情况下,只需获取调度程序锁,将线程的状态更改为“准备运行”,然后,如果有任何空闲 CPU,就向它们发出信号。
    猜你喜欢
    • 2010-10-04
    • 1970-01-01
    • 2021-04-23
    • 2012-09-28
    • 2018-04-04
    • 2016-05-25
    • 2011-11-29
    • 2014-10-15
    • 2016-01-18
    相关资源
    最近更新 更多