目录
一:什么是API
API:
谁来提供API?
大体上有两个,库和OS。
(1)库(c/c++/java等的库):调用库API,可以获取库函数提供的功能。
(2)OS:调用OS API(系统API),可以获取OS函数提供的功能。
80%库API(库函数)都是基于OS API(系统函数)实现的,你调用库API时,基本都是间接调用了OS API的.
库的意义何在?
1.实现不同OS平台的兼容(不同OS的系统API是不一样的)
2.库函数在系统函数的基础上,还叠加了一些额外的功能
比如:你调用Linux C库提供的printf函数时,其实printf最终调用的还是Linux OS的write这个系统API,我们知道printf函数有%d %s等格式化的输出,这种格式化的输出并不是write系统API提供的,其实是printf对write做二次封装时,叠加一些性的更加人性化的功能。
学的就是Linux OS所提供的各种API,学会使用这些OS API后,在编程时直接调用这些系统API,直接获取OS提供的各种功能(服务)。
- 学习OS API,有助于理解OS这个东西
- 帮助我们理解文件读写、进程、进程间通信、线程、信号、锁等概念
库都是基于系统API实现的,只不过做了一层封装而已
操作系统可以给应用程序提供的服务:
- 读写文件---文件IO
- 获取文件属性---文件属性
- 标准io----读写文件的库函数
- 获取系统信息---时间
- 进程环境(应用程序运行依赖于进程的环境)
- 进程控制
- 进程关系(父子关系。。。)
- 本机进程间的通信(同一台电脑)
- 网络通信----跨机通信
课程大纲
(1)文件io
(2)操作文件属性
(3)c库提供标准io
- 基于文件io实现
- Linux的c库的标准io函数基于Linux的文件io实现。
- 对比文件io和标准Io的异同
(4)获取OS的系统信息------ 比如获取时间。
(5)进程相关内容
- 进程环境
- 进程控制
- 进程关系
- 进程间通信(ipc)
(6)高级io-----读写文件的一些高级用法。
(7)网络编程------建议先看《计算机体系结构》网络篇的网络基础知识
当有OS的时候,应用程序基于OS运行,必须通过OS的API才能操作底层硬件
打开文件,读写文件,关闭文件
#include #include #include #include #include #include int main(){ int fd =0; fd= open("./fff.txt",O_RDWR); if (fd==-1) { printf("open fail\n"); return 0; } else{ printf("open suc!\n"); } char buf1[]="hello world"; write(fd,(void*)buf1,strlen(buf1)); //ssize_t write(int fd, const void *buf, size_t count); lseek(fd,SEEK_SET,0); //off_t lseek(int fd, off_t offset, int whence); char buf2[30]={0}; read(fd,buf2,sizeof(buf2)); //ssize_t read(int fd, void *buf, size_t count); printf("buf2=%s\n",buf2); close(fd); return 0; }用 man 2 open//write//read----找到库文件原型和需要的头文件
读文件前,把写指针移动最前方------lseek(SEEK_SET)
open将文件打开成功的话:
1:记录打开文件的信息
a)程序运行起来后就是一个进程了,OS会创建一个task_struct的结构体,记录进程运行时的各种信息---------所打开文件的相关信息
b)open将文件成功打开后,在task_struct中又会创建一些结构体(数据结构),用于记录当前进程目前所打开文件的信息
后续所有的文件操作,都需要依赖于这些信息,其中就包括指向打开文件的文件描述符。2:open函数会申请一段内存空间(内核缓存),后续读写文件时,用于临时缓存数据
缓存-----开辟的一段内存空间
内核缓存-----open是OS所提供的系统函数,属于OS内核的一部分,所以open函数所开辟的缓存空间,就是内核缓存
open为什么要开内核缓存空间?
内存读写速度 > 磁盘读写速度的,有了在内存中开辟的内核缓存后,上层读写数据时,会直接读写缓存,速度会很快,至于缓存与磁盘上文件数据的交换,就留给下层去做,这样可以节省上层操作的时间。open时只是开辟了内核缓存空间,里面并没有数据,只有当进行读写数据时,才会缓存读写的数据。
写:应用缓存的数据os写到内核缓存,然后下层通过驱动程序写到硬件磁盘,其中驱动程序里面也有驱动缓存,进行数据流动
重点:flag参数
flags 之 O_RDONLY、O_WRONLY、O_RDWR、O_TRUNC、O_APPEND
flags用于指定文件的打开方式,这些宏还可以使用|组合,比如O_RDONLY | O_APPEND
三个参数:
三个参数mode,用于指定新创建文件的原始权限----- O_CREAT、O_EXCL
当O_EXCL与O_CREAT同时被指定,打开文件时,如果文件之前就存在的话,就报错。
文件描述符(0~1023)
open成功就会返回一个非负整数(0、1、2、3...)的文件描述符,文件描述符指向了打开的文件,后续的read/write/close等函数的文件操作,都是通过文件描述符来实现的。
open返回的数字是当前最小没用的哪一个
文件关闭后,当前文件符会被释放,等着下一次open时,被重复利用
open-----Linux 的系统函数(文件io函数);fopen----C库的标准io函数
errno和错误号
错误号代表了一种错误,产生这个错误时,会自动的将错误号赋值给errno这个全局变量
错误号和errno全局变量被定义在了errno.h头文件,使用errno时需要包含这个头文件
perror是一个C库函数,不是一个系统函数perror函数可以自动将“错误号”换成对应的文字信息,并打印出来