前言
我们给出这样一张计算机的层级图:
可以看到,整个计算机体系分为硬件层和软件层
而在软件层,我们又有内核层与用户层
操作系统是横亘在硬件与用户软件之间的一个软件,对下管理各种硬件,对上为用户软件提供服务。我们可以这样类比
用户 | 校长 |
---|---|
操作系统 | 辅导员 |
硬件 | 学生 |
我们人要管理好硬件,那么就需要一个懂硬件的帮我们管理硬件,那就是操作系统
但是,为了保证安全,操作系统对人只会开放特定的接口,通过特定的接口,人才可以来对硬件进行特定的管理,这样的接口,就叫做系统调用接口
然而,系统调用接口是比较复杂的,让人每次都使用系统调用接口去管理硬件也太烦了吧,于是,便有一些别有用心的人对于系统调用接口进行了二次封装
,封装出了一些更加友好、人性化的接口来供人调用,例如:
- C语言库函数
- 命令行解释器
- 图形化界面
总而言之,这张层级图解释了一切:
接下来,我们就以Linux操作系统为例,分别看一下系统调用接口和经过二次封装的C语言库函数对于读/写
操作的方式
1.系统调用接口
1.考察open, read, write, lseek, close等函数的使用,同时理解文件描述符
2.要求:
2.1 使用代码打开当前路径下的“bite”文件(如果文件不存在在创建文件),向文件当中写入“i like linux!”.
2.2 在从文件当中读出文件当中的内容, 打印到标准输出当中; 关闭文件描述符
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main() {
int fd = open("bite", O_WRONLY|O_CREAT, 0644);
const char* buffer = "i like linux\n";
write(fd, buffer, strlen(buffer));
close(fd);
fd = open("bite", O_RDONLY, 0644);
char output[128] = {
'\0'};
read(fd, output, 127);
write(1, output, strlen(output));
close(fd);
return 0;
}
2.C语言库函数
1.考察fopen, fread, fwrite, fseek, fclose等函数的使用
2.要求:
2.1使用代码打开当前路径下的“bite”文件(如果文件不存在在创建文件),向文件当中写入“linux so easy!”.
2.2 在从文件当中读出文件当中的内容, 打印到标准输出当中; 关闭文件流指针
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main() {
FILE* fp = fopen("bite", "w");
const char* buffer = "linux so easy\n";
fwrite(buffer, 1, strlen(buffer), fp);
fclose(fp);
fp = fopen("bite", "r");
char output[128] = {
0};
fread(output, 1, 128, fp);
fprintf(stdout, "%s", output);
fclose(fp);
return 0;
}
3.总结
我们可以看到,系统调用接口和C语言库函数都能完成读写操作,总的来说:
- 在开发角度,操作系统对外表现成一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用。
- 系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。