本文已使用 Google Cloud Translation API 自动翻译。
某些文档最好以原文阅读。
系统调用是程序如何从操作系统请求服务。库是程序如何从编程语言请求服务。
在本文中,我们将了解系统调用和库在 Linux 中的工作方式。我们将从对每一个的简要概述开始,然后我们将看一些具体的例子。
系统调用是用户空间和内核空间之间的接口。它们是程序如何从操作系统请求服务。
系统调用是通过调用具有特殊名称的函数来进行的。例如,在 Linux 中,读取文件的系统调用称为 read()。
系统调用是通过将参数传递给函数来进行的。第一个参数总是一个标识系统调用的数字。其余参数取决于正在进行的系统调用。
进行系统调用时,内核会检查调用程序是否具有进行调用的权限。如果允许调用,则内核执行系统调用的代码。
系统调用的代码通常用汇编语言编写。这使得程序员很难理解和调试。
系统调用很慢,因为它们涉及用户空间和内核空间之间的上下文切换。上下文切换是指 CPU 保存一个进程的状态并加载另一个进程的状态。
系统调用也是一种安全风险。有缺陷的系统调用可能会使内核崩溃或允许恶意用户访问特权信息。
库是程序向编程语言请求服务的一种方式。
库由函数的集合组成。每个函数执行一个特定的任务。
例如,C 标准库提供了读写文件、操作字符串和执行数学运算的函数。
库通常是用与使用它们的程序相同的语言编写的。这使得程序员更容易理解和调试。
库比系统调用更快,因为它们不涉及上下文切换。
库也比系统调用更安全,因为它们不太可能包含错误代码。
现在我们已经看到了系统调用和库的简要概述,让我们看一些具体的例子。
以下是如何使用系统调用从文件中读取的示例:
#include <unistd.h>
int main() {
char buf[1024];
int n;
n = read(0, buf, sizeof(buf));
if (n < 0) {
perror("read");
return 1;
}
write(1, buf, n);
return 0;
}
read()
系统调用从文件中读取数据。第一个参数是文件描述符。第二个参数是存储数据的缓冲区。第三个参数是缓冲区的大小。
write()
系统调用将数据写入文件。第一个参数是文件描述符。第二个参数是包含数据的缓冲区。第三个参数是要写入的字节数。
以下是如何使用库写入文件的示例:
#include <stdio.h>
int main() {
FILE *fp;
char buf[1024];
int n;
fp = fopen("test.txt", "w");
if (fp == NULL) {
perror("fopen");
return 1;
}
n = fwrite(buf, 1, sizeof(buf), fp);
if (n < 0) {
perror("fwrite");
return 1;
}
fclose(fp);
return 0;
}
fopen()
函数打开一个文件。第一个参数是文件的路径。第二个参数是模式。模式可以是 "r"
用于读取,"w"
用于写入,或 "a"
用于追加。
fwrite()
函数将数据写入文件。第一个参数是包含数据的缓冲区。第二个参数是每个元素的大小。第三个参数是要写入的元素数。第四个参数是文件指针。
fclose()
函数关闭文件。参数是文件指针。
在本文中,我们看到了系统调用和库的简要概述。我们还看到了一些如何使用它们的具体示例。