使用C中的功能指针重新启动计算机 [英] Restart a computer using function pointers in C

查看:71
本文介绍了使用C中的功能指针重新启动计算机的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我遇到一个程序,该程序在执行时会重新启动计算机时,我正在学习C语言中的函数指针.

I was learning about function pointers in C when I came across a program that restarts the computer upon execution.

void (*f) (void);
f=(void (*)(void) MK_FP(0xFFFF,0x0000);
f();

(void(*)(void))部分不在提供的原始文本中,我必须添加此内容才能编译代码.如何运作?

The (void (*)(void)) portion wasn't in the original text provided, and I had to make this addition to get the code to compile. How does this work?

非常感谢您.

推荐答案

关于从数字文字中手动构造函数指针并调用它们的程序,C标准仅表示行为未定义.这意味着您不能指望该程序在计算机之间的行为相同,甚至无法在同一计算机上运行.

About programs that manually construct function pointers from numeric literals and call them, the C standard says only that the behavior is undefined. That means you can't expect the program to behave the same way from computer to computer, or even from run to run on the same computer.

关于这个特定的程序,我们可以对它的意图以及在何种情况下实际会做出有根据的猜测:

About this particular program, we can make an educated guess about what it was meant to do and under what circumstances it will actually do that:

原始IBM PC的原始操作系统(通常称为MS-DOS)在加电后开始在分段地址FFFF:0000处执行代码. (有些消息来源改为说F000:FFF0-由于太繁琐而无法进入此处,即相同的物理地址,但表示方式不同,并且可能取决于该位置的代码,其行为方式也有所不同.)由于该操作系统非常简陋,因此在计算机启动并运行后跳到该位置将近似执行热重启.

The original operating system for the original IBM PC, commonly known as MS-DOS, started executing code at the segmented address FFFF:0000 upon power-on. (Some sources say F000:FFF0 instead -- for reasons too tedious to get into here, that is the same physical address, but expressed a different way and possibly behaving differently depending on what code is at that location.) Because this OS was so bare-bones, jumping to that location after the machine was up and running would perform an approximation to a warm reboot.

假设您的MK_FP宏根据段和偏移量值构造了分段的函数指针,则在运行MS-DOS的IBM PC上执行程序时,它会跳转到FFFF:0000并近似执行热重启.

On the assumption that your MK_FP macro constructs a segmented function pointer from segment and offset values, then, when your program is executed on an IBM PC running MS-DOS, it jumps to FFFF:0000 and performs an approximation to a warm reboot.

在更现代的操作系统(包括IBM PC子孙的所有当前操作系统)上,保证此程序 not 可以重新启动计算机,因为非特权用户模式程序不是允许重新启动计算机.而且,在现代的32位或64位用户模式程序中,MK_FP()操作本身没有意义,因为它们在平面地址空间中运行.该代码可以编译,但是几乎可以肯定,它最终会调用一个没有映射到内存的地址,因此我希望程序会崩溃.但是其余的操作系统将继续运行,就像什么也没有发生.如果您在DOS模拟器中运行该程序,则它可能会重新启动 emulator ,但是同样,其余的OS仍将继续运行.

On a more modern operating system (including all current OSes for the descendants of the IBM PC) this program is guaranteed not to reboot the computer, because unprivileged user-mode programs are not allowed to reboot the computer. Moreover, the MK_FP() operation itself doesn't make sense in a modern 32- or 64-bit user mode program, because they run in flat address spaces. The code may compile, but it almost certainly winds up calling an address that has no memory mapped to it, so I would expect the program to crash. But the rest of the OS will just keep on going like nothing happened. If you ran the program inside a DOS emulator, it might reboot the emulator, but again, the rest of the OS will just keep on going.

可以 编写重新启动现代OS的程序-实际上,您的计算机上已经至少有一个这样的程序,否则您将无法重新启动它物理电源开关! -但必须使用特殊的系统调用很好地询问内核(Unix系列: ExitWindowsEx ),它必须以特殊特权运行,否则调用将失败.

It is possible to write a program that reboots a modern OS -- indeed, you already have at least one such program on your computer, or you'd have no way of rebooting it short of the physical power switch! -- but it has to ask the kernel nicely, using a special system call (Unix-family: reboot(2); Windows: ExitWindowsEx) and it has to be running with special privileges or the call will fail.

也就是说,跳转到FFFF:0000加上一串辅助的挥舞着鸡的 是当前版本的Linux可能用来触发基于x86的重启的低级操作之一机器.仅在其他几项失败的情况下才尝试使用它,但是它在那里.参见 http://lxr.free-electrons.com/有关整个过程的概述,请参见source/arch/x86/kernel/reboot.c#L484 FFFF:0000.

That said, a jump to FFFF:0000 plus a bunch of ancillary chicken-waving is one of the low-level operations that current versions of Linux may use to trigger a reboot on x86-based machines. It's only tried if several other things fail, but it's in there. See http://lxr.free-electrons.com/source/arch/x86/kernel/reboot.c#L484 for an outline of the overall procedure, and http://lxr.free-electrons.com/source/arch/x86/realmode/rm/reboot.S for the code that actually executes the jump to FFFF:0000 after dropping back to "real" (16-bit segmented) mode.

这篇关于使用C中的功能指针重新启动计算机的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆