- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试为 Raspberry Pi 制作一个操作系统(没什么大不了的,只是为了好玩),虽然我可以用汇编语言编写它,但这比用 C 语言编写要困难得多。我想知道是否(以及为什么如果我不能,则不会)我可以将 C 库(文件)包含在操作系统中,这样我就不必重写它们了。因为库本身是用 C 编写的,所以它不会起作用吗?
最佳答案
不,您必须将 C 库移植到您的操作系统,因为该库具有 Hook 到操作系统细节的“ stub ”。 C 标准要求某些 header 以独立模式存在,您始终可以使用该模式。但是像 printf 这样的库函数必须自己实现或通过填写 stub 来移植。看看newlib看看你必须做的工作。它至少需要一个具有系统调用接口(interface)(用于读取、写入等)的工作内核。这些将取决于您的操作系统中可用的功能(例如,文件系统)。摘自常见问题解答:
- What steps do I need to do to port newlib to a new platform?
A basic port needs to alter a number of files and add some directories.
Add a subdirectory to the newlib/libc/machine directory for your platform
In this directory you need to have a setjmp/longjmp implementation. This is required because setjmp/longjmp usually is assembler. Look at the libc/machine/fr30 directory and copy/modify the files in there.
Edit newlib/libc/include/machine/ieeefp.h
This defines the ieee endianness for your platform. The compiler should be defining something that identifies your machine. In some cases, the endianness may be a compiler-option so you may have to check another define in addition to your platform identifier. See examples in the file.
Edit newlib/libc/include/machine/setjmp.h
You need to specify the setjmp buffer characteristics to match up with your setjmp/longjmp implementation. This is just the size of the setjmp buffer. See file for examples.
Edit newlib/libc/include/sys/config.h
This has various defines as needed. Mostly, it defines some max values. There are defaults that may apply to your platform in which case you needn't do anything.
Edit configure.host
You need to add your configuration so newlib can recognize it. You should specify your new machine directory for your platform via the machine_dir variable. If needed, you can add special newlib compile flags. The sys_dir is for OS stuff so you won't need to alter that. Older platforms used the sys_dir to implement syscalls but this is not correct and is a historical nuisance. The syscall_dir is a choice, but I recommend as a default to specify syscall_dir=syscalls. Read the comments in newlib/libc/include/reent.h for an explanation of choices.
Add a platform subdirectory to libgloss
You need to add a bsp for your platform. This is the minimum set of syscalls needed by newlib and any linker scripts needed. This varies from board to board (it can also be a simulator). See the mn10300 or fr30 for examples. You will need to edit configure.in and regenerate configure so it will build your new files. By default you get libnosys which gives you a set of default syscall stubs. The majority of the stubs just return failure.You still need to supply an __exit routine. This can be as simple as generating an exception to stop the program.
Possibly override header files
If you need to override any default machine header files, you can add a machine directory to newlib/libc/machine/ Header files in that subdirectory will overwrite the defaults found in newlib/libc/include/machine. You will likely not need to do this.
This assumes you have already handled adding your new configuration to the top directory files.
Now linux is a different animal. It is an OS that has an extensive set of syscalls. If you look in the newlib/libc/sys/linux directory, you will find a number of syscalls there (e.g. see io.c). There is a set of basic syscall macros that are defined for the particular platform. For the x86, you will find these macros defined in newlib/libc/sys/linux/machine/i386/syscall.h file. At the moment, linux support is only for x86. To add another platform, the syscall.h file would have to be supplied for the new platform plus some other platform-specific files would need to be ported as well.
对于 newlib,请查看 syscall documentation page其中列出了您需要实现的内容以及最小实现的内容。你会很快意识到sbrk
这样的东西如果您还没有实现内存管理,它将变得毫无意义。到移植 C 库时,您可能最终已经编写了大部分内核。
_exit
Exit a program without cleaning up files. If your system doesn't provide this, it is best to avoid linking with subroutines that require it (exit, system).
close
Close a file. Minimal implementation:
int close(int file) {
return -1;
}
environ
A pointer to a list of environment variables and their values. For a minimal environment, this empty list is adequate:
char *__env[1] = { 0 };
char **environ = __env;
execve
Transfer control to a new process. Minimal implementation (for a system without processes):
#include <errno.h>
#undef errno
extern int errno;
int execve(char *name, char **argv, char **env) {
errno = ENOMEM;
return -1;
}
fork
Create a new process. Minimal implementation (for a system without processes):
#include <errno.h>
#undef errno
extern int errno;
int fork(void) {
errno = EAGAIN;
return -1;
}
fstat
Status of an open file. For consistency with other minimal implementations in these examples, all files are regarded as character special devices. The sys/stat.h header file required is distributed in the include subdirectory for this C library.
#include <sys/stat.h>
int fstat(int file, struct stat *st) {
st->st_mode = S_IFCHR;
return 0;
}
getpid
Process-ID; this is sometimes used to generate strings unlikely to conflict with other processes. Minimal implementation, for a system without processes:
int getpid(void) {
return 1;
}
isatty
Query whether output stream is a terminal. For consistency with the other minimal implementations, which only support output to stdout, this minimal implementation is suggested:
int isatty(int file) {
return 1;
}
kill
Send a signal. Minimal implementation:
#include <errno.h>
#undef errno
extern int errno;
int kill(int pid, int sig) {
errno = EINVAL;
return -1;
}
link
Establish a new name for an existing file. Minimal implementation:
#include <errno.h>
#undef errno
extern int errno;
int link(char *old, char *new) {
errno = EMLINK;
return -1;
}
lseek
Set position in a file. Minimal implementation:
int lseek(int file, int ptr, int dir) {
return 0;
}
open
Open a file. Minimal implementation:
int open(const char *name, int flags, int mode) {
return -1;
}
read
Read from a file. Minimal implementation:
int read(int file, char *ptr, int len) {
return 0;
}
sbrk
Increase program data space. As malloc and related functions depend on this, it is useful to have a working implementation. The following suffices for a standalone system; it exploits the symbol _end automatically defined by the GNU linker.
caddr_t sbrk(int incr) {
extern char _end; /* Defined by the linker */
static char *heap_end;
char *prev_heap_end;
if (heap_end == 0) {
heap_end = &_end;
}
prev_heap_end = heap_end;
if (heap_end + incr > stack_ptr) {
write (1, "Heap and stack collision\n", 25);
abort ();
}
heap_end += incr;
return (caddr_t) prev_heap_end;
}
stat
Status of a file (by name). Minimal implementation:
int stat(char *file, struct stat *st) {
st->st_mode = S_IFCHR;
return 0;
}
times
Timing information for current process. Minimal implementation:
int times(struct tms *buf) {
return -1;
}
unlink
Remove a file's directory entry. Minimal implementation:
#include <errno.h>
#undef errno
extern int errno;
int unlink(char *name) {
errno = ENOENT;
return -1;
}
wait
Wait for a child process. Minimal implementation:
#include <errno.h>
#undef errno
extern int errno;
int wait(int *status) {
errno = ECHILD;
return -1;
}
write
Write to a file. libc subroutines will use this system routine for output to all files, including stdout—so if you need to generate any output, for example to a serial port for debugging, you should make your minimal write capable of doing this. The following minimal implementation is an incomplete example; it relies on a outbyte subroutine (not shown; typically, you must write this in assembler from examples provided by your hardware manufacturer) to actually perform the output.
int write(int file, char *ptr, int len) {
int todo;
for (todo = 0; todo < len; todo++) {
outbyte (*ptr++);
}
return len;
}
有关移植 newlib 所需步骤的更全面概述,请参阅 osdev.org .虽然我建议首先阅读网站上与编写内核有关的其他教程,因为移植 C 库绝对不是编写内核时采取的第一步。
关于我可以在编写操作系统时只包含 C 库吗(因为它们是用 C 制作的),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26541882/
如主题所述,是否有可能没有 future 的问题?。基本上我发布此线程以供将来引用,以便人们可以观看该场景。mongodb 被限制为 2Gb 的原因是什么?能否请您指出引用资料,以便像我这样的菜鸟可以
我正在使用 Bootstrap 4 轮播。它适用于所有 Windows 和 Android 操作系统,但不适用于 Mac 和 iPhone 操作系统。有什么解决办法吗?这是我的代码github.com
目录 内存管理硬件结构 早期内存的使用方法 分段 分页 逻辑地址,线性地址(intel架构) 虚拟地址 物理地址
页表的一些术语 现在Linux内核中支持四级页表的映射,我们先看下内核中关于页表的一些术语: 全局目录项,PGD(Page Global Directory) 上级目录项,PUD(
1. 文件路径 绝对路径 绝对路径 (absolute path) : 以一个盘符开头的路径,就是绝对路径 例如这里的 D:\java\IntelliJ IDEA Community Edition
1. 进程介绍 1.1 进程的概念 程序是由指令和数据组成的,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,将数据加载至内存。在指令运行过程中还需要用到磁盘和网络等设备。进程就是用来加载指
1. 文件路径 绝对路径 绝对路径 (absolute path) : 以一个盘符开头的路径,就是绝对路径 例如这里的 D:\java\IntelliJ IDEA Community Edition
我有 REST APIManager 类 - 用于使用服务器 api 的单例。有返回用户Token实体的登录方法; 所有其他 API 方法都使用 token 来发出请求。登录后我应该在哪里存储该 to
当我在学习操作系统类(class)时,我不明白为什么下面代码的输出是这样的 代码: #include #include #include #include int main (int argc
我正在尝试在 C++ 中使用 fork() 和 wait() 系统调用。 我的代码非常简单。但是我收到以下错误: error C3861: 'fork': identifier not found 我
我需要播放不同格式的网络广播。我尝试使用 MPMoviePlayerController 播放广播,但它在 3-4 秒后停止。 var urlAddress = "http://streaming.r
多线程(进阶) 1. 常见的锁策略 1.1 乐观锁 悲观锁 乐观锁 : 总是假设最好的情况,每次去拿数据的时候都认为别人不会修改数据,但是在对数据提交更新的时候,再去判断这个数据在这个期间是否有别人对
如何让内存用起来? 内存使用:将程序放到内存中,PC指向开始地址 那就让首先程序进入内存 让程序从磁盘加载到内存中来,首先需要考虑要将程序代码安放在内存的什么位置 如果把入口地址直接放在0地址处,然后
操作系统 内存 HBase一定需要RAM! 64位 使用64位平台(和64位JVM)。 交换 注意交换,将swappiness设为0。 CPU 确保已将Hadoop设置为使用本机的硬件
我想编写一个脚本,将当前打开的 Windows 移动到某个位置。 理想情况下,我的程序应该是这样的: var window = FindWindow("Winamp"); window.setPos(
以下问题是我对操作系统的测试评论,但我不知道如何回答。我会第一次尝试解决他们的问题,但我也不知道如何开始。 Given the following information for an assembl
在操作系统方面我见过几次这个词。匿名内存 ,但我真的不知道,那是什么。 如果有人问我一些关于它的事情,我真的无法非常确定地说出那是什么。 我也搜索了它的解释,但不幸的是我还没有找到任何令人满意的东西。
在 Abraham Silberschatz 等人的“操作系统概念”第 9 版中,作者说: "Some operating systems support only static linking, i
我知道可用端口有限制(2^16),但我不明白操作系统如何管理这些端口。内部是否有一个微 Controller 可以复用所有打开的端口?端口实际上是如何与操作系统建立连接的?端口是否连接到操作系统中的特
如何激活另一个已最小化的应用程序的窗口? 如果前面有其他窗口,它可以很好地使用 NSRunningApplication 类的 activateWithOptions 方法,但这不适用于最小化的窗口。
我是一名优秀的程序员,十分优秀!