有意义的是像操作系统这样的东西会用C编写.但它有多少,以及什么样的C?我的意思是,在C中,如果你需要一些堆内存,你可以调用malloc.但是,操作系统甚至有堆吗?据我所知,malloc 向操作系统询问内存,然后将其添加到链表,二叉树或其他内容.调用堆栈怎么样?操作系统负责设置其他应用程序使用的所有内容,但它是如何做到的?如果要在C中打开或创建文件,相应的函数会向操作系统询问该文件.所以...那个电话的另一边有什么样的C?或者在内存分配的另一端?
另外,实际上用C编写了多少操作系统?所有的?架构相关代码怎么样?那些更高级别的抽象怎么样?是否用高级语言编写,比如C++?
我的意思是,我只是出于纯粹的好奇而问这个问题.我现在正在下载最新的Linux内核,但这需要永远.我不确定我是否能够遵循代码 - 或者我是否会陷入一个我从未见过的不可避免的复杂网络中.
所有的优秀问题.答案是:用于编写操作系统的C语言"方言"中几乎没有标准C库可用.例如,在Linux内核中,标准内存分配函数malloc,nmalloc,free等被替换为特殊的内核 - 内部内存分配函数kmalloc和kfree,对它们的使用有特殊限制.操作系统必须提供自己的"堆" - 在Linux内核中,为内核使用而分配的物理内存页必须是不可分页的,并且通常是物理上的连接.请参阅关于kmalloc和kfree的这篇Linux期刊文章.类似地,操作系统内核维护自己的特殊调用堆栈,其使用需要来自内存的GCC编译器的特殊支持.
另外,实际上用C编写了多少操作系统?所有的?
据我所知,操作系统绝大部分是用C语言编写的.一些特定于体系结构的特性是用汇编语言编写的,但通常很少能提高可移植性和可维护性:Linux内核有一些汇编程序,但试图将其最小化.可能.
架构相关代码怎么样?那些更高级别的抽象怎么样?是否用高级语言编写,比如C++?
通常内核将使用纯C编写,但有时更高级别的框架和API是用更高级别的语言编写的.例如,MacOS上的Cocoa框架/ API是用Objective C编写的,而BeOS更高级别的API是用C++编写的.Microsoft的.NET框架大部分是用C#编写的,"公共语言运行时"是用C++和汇编语言编写的.Linux上最常用的QT小部件集是用C++编写的.当然,这引入了关于什么算作"操作系统"的哲学问题.
Linux内核绝对值得关注,但是,必须要说的是,任何人从头开始阅读都是巨大的,令人生畏的.
什么样的C?
大部分是ANSI C,很多时候都在查看它生成的机器代码.
但是,操作系统甚至有堆吗?
Malloc向操作系统询问指向允许使用的某些内存的指针.如果在OS(用户模式)上运行的程序试图访问它不拥有的内存,则会产生分段错误.允许操作系统直接访问系统上的所有物理内存,不需要malloc,不存在任何存在的地址上的seg-fault.
调用堆栈怎么样?
调用堆栈实际上通常在硬件级别上工作,具有链接寄存器.
对于文件访问,操作系统需要访问磁盘驱动程序,磁盘驱动程序需要知道如何读取磁盘上的文件系统(有很多不同类型)有时操作系统内置了一个,但我认为它更常见引导装载程序将它从一个开始,然后加载另一个(更大的).磁盘驱动程序可以访问物理磁盘的硬件IO,并从中构建.
C是一种非常低级的语言,你可以直接做很多事情.需要首先实现任何C库方法(如malloc,printf,crlscr等),以便从C调用它们(例如,查看libc概念).我将在下面给出一个例子.
让我们看看C库方法是如何在幕后实现的.我们将以一个clrscr为例.实现此类方法时,您将直接访问系统设备.例如,对于clrscr(清除屏幕),我们知道视频内存驻留在0xB8000.因此,要写入屏幕或清除它,我们首先指定一个指向该位置的指针.
在video.c
void clrscr() { unsigned char *vidmem = (unsigned char *)0xB8000; const long size = 80*25; long loop; for (loop=0; loop现在让我们编写我们的迷你内核.当控件从引导加载程序移交给我们的"内核"时,这将清除屏幕.在main.c
void main() { clrscr(); for(;;); }要编译我们的'内核',您可以使用gcc将其编译为纯bin格式.
gcc -ffreestanding -c main.c -o main.o gcc -c video.c -o video.o ld -e _main -Ttext 0x1000 -o kernel.o main.o video.o ld -i -e _main -Ttext 0x1000 -o kernel.o main.o video.o objcopy -R .note -R .comment -S -O binary kernel.o kernel.bin如果您注意到上面的ld参数,您会看到我们将内核的默认加载位置指定为0x1000.现在,您需要创建一个引导加载程序.从您的引导加载程序逻辑,您可能希望将控制权传递给您的内核,例如
jump 08h:01000h您通常在Asm中编写引导加载程序逻辑.在此之前,您可能需要了解一下PC Boots的方式 - 点击这里.
最好从一个更小的操作系统开始探索.请参阅此自行操作系统教程
http://www.acm.uiuc.edu/sigops/roll_your_own/
4> Unknown..:但它有多少,以及什么样的C?
某些部件必须用汇编语言编写
我的意思是,在C中,如果你需要一些堆内存,你可以调用malloc.但是,操作系统甚至有堆吗?据我所知,malloc向操作系统询问内存,然后将其添加到链表,二叉树或其他内容.
有些操作系统有堆.在最低级别,它们是被称为页面的内存块.然后,您的C库使用malloc以可变大小的方式使用自己的方案进行分区.您应该了解虚拟内存,这是现代操作系统中常见的内存方案.
如果要在C中打开或创建文件,相应的函数会向操作系统询问该文件.所以...那个电话的另一边有什么样的C?
您调用汇编例程,使用IN和OUT等指令查询硬件.对于原始内存访问,有时您会有专门用于与硬件进行通信的内存区域.这称为DMA.
我不确定我是否能够遵循代码 - 或者我是否会陷入一个我从未见过的不可避免的复杂网络中.
是的你将会.你应该先拿起一本关于硬件和操作系统的书.