为什么设置系统调用不能被任何用户调用?
Why is the setup syscall not callable by any user?
http://linux.die.net/man/2/setup
我在手册页上没有找到任何原因。
首先,该系统调用已不存在:
Since Linux 2.1.121
, no such function exists anymore.
从我在 2.1.120
中看到的情况来看,它被用于内核的初始化(实际上有系统调用号 0
)。它只被调用了两次:第一次调用释放了初始内存(来自 initram),第二次调用设置了设备、文件系统并挂载了根目录。很明显,如果一个程序可以 运行 系统调用(它会导致分段违规或其他不好的事情)。
为什么它首先是一个系统调用是一个很好的问题。为此,我下载了 1.0.0
,并且 即使如此 系统调用也没有被 init 使用(这是我对为什么它会是系统调用的第一个猜测)。即使在 0.01
中,它也只在内核中使用。由于 int 0x80
没有用处,我对 Linus 这样做的原因感到困惑。
我刚刚给 Linus 和 LKML 发了一封电子邮件,并在 IRC 上询问(尽管除了 Linus 之外,其他人不太可能知道,而且他正忙着回复关于 Linux 的线粒体 DNA 的电子邮件).
编辑:好的,所以进一步研究,事实证明内核实际上是从进程上下文调用它(setup
调用实际上充当系统调用,int 0x80
和所有).内核的初始化不是在进程上下文中完成的,并且 (according to Linus):
So the code actually goes into user space, but the very initial user
space is actually shared with the kernel (until the first fork()). We
do the initial user mode transition by just switching to user
segments [...] So in init/main.c, the magic is that
move_to_user_mode();
if (!fork()) { /* we count on this going ok */
init();
}
for(;;) pause(); /* [this is the idle task] */
where that "move_to_user_mode()" will reload all the segments (some by
hand, but CS/SS by doing an "iret"). So that first fork() will
actually be done in user space, and before that happens the kernel
cannot sleep (because there is no idle task). [...] So "setup()" is a
system call because it needs to sleep (to do the IO), and the kernel
couldn't sleep before it got to that user-mode and first fork thing.
Could it have been done differently? Sure. Obviously we don't do it
that way any more, and we create the idle tasks separately and not
with "fork()" any more. But it kind of made sense at the time.
http://linux.die.net/man/2/setup
我在手册页上没有找到任何原因。
首先,该系统调用已不存在:
Since Linux
2.1.121
, no such function exists anymore.
从我在 2.1.120
中看到的情况来看,它被用于内核的初始化(实际上有系统调用号 0
)。它只被调用了两次:第一次调用释放了初始内存(来自 initram),第二次调用设置了设备、文件系统并挂载了根目录。很明显,如果一个程序可以 运行 系统调用(它会导致分段违规或其他不好的事情)。
为什么它首先是一个系统调用是一个很好的问题。为此,我下载了 1.0.0
,并且 即使如此 系统调用也没有被 init 使用(这是我对为什么它会是系统调用的第一个猜测)。即使在 0.01
中,它也只在内核中使用。由于 int 0x80
没有用处,我对 Linus 这样做的原因感到困惑。
我刚刚给 Linus 和 LKML 发了一封电子邮件,并在 IRC 上询问(尽管除了 Linus 之外,其他人不太可能知道,而且他正忙着回复关于 Linux 的线粒体 DNA 的电子邮件).
编辑:好的,所以进一步研究,事实证明内核实际上是从进程上下文调用它(setup
调用实际上充当系统调用,int 0x80
和所有).内核的初始化不是在进程上下文中完成的,并且 (according to Linus):
So the code actually goes into user space, but the very initial user space is actually shared with the kernel (until the first fork()). We do the initial user mode transition by just switching to user segments [...] So in init/main.c, the magic is that
move_to_user_mode();
if (!fork()) { /* we count on this going ok */
init();
}
for(;;) pause(); /* [this is the idle task] */
where that "move_to_user_mode()" will reload all the segments (some by hand, but CS/SS by doing an "iret"). So that first fork() will actually be done in user space, and before that happens the kernel cannot sleep (because there is no idle task). [...] So "setup()" is a system call because it needs to sleep (to do the IO), and the kernel couldn't sleep before it got to that user-mode and first fork thing.
Could it have been done differently? Sure. Obviously we don't do it that way any more, and we create the idle tasks separately and not with "fork()" any more. But it kind of made sense at the time.