《博学谷C++》四.1-4Linux文件和系统调用
这一节只学习了一部分,放弃了一些文件操作函数。因为感觉自己目前最需要学的是系统等相关的东西(进程间通信、线程、soket等),学怎么用这些函数也不难。
1.系统调用
程序等,通过统一系统调用接口来进行对内核资源的使用。这样做是为了保护系统资源。
shell、库函数、应用程序都可以进行系统调用。但不是所有操作都需要进行系统调用,例如字符串处理,不需要系统调用即可实现。
为了实现权限控制和资源保护,操作系统分为了两种运行级别:用户态和内核态。用户态下的进程访问受限,而内核态没有限制,如驱动程序等。通过系统中断,实现用户态和内核态之间的切换。
2.系统调用和库函数
同:库函数和系统调用都是函数;
异:一些库函数不需要进行系统调用;另一些需要。
3.C库中IO函数工作流程
为什么需要缓冲区?
读写机械硬盘很慢,使用缓冲区可以减少对机械硬盘的读写、减少IO系统调用次数,提高访问效率。
3.1 errno变量
errno变量是定义在#include <errno.h>
中的全局变量,可以直接使用,用于出错之后打印错误日志,方便排查错误。
全部错误号位于/usr/include/asm-generic/errno.h
3.2 strerror(errno)函数
输入errno变量,输出对应的错误信息。
3.3 perror()函数
类似于strerror,但不需要输入错误号,直接输出最后一次的错误信息。
1 |
|
4.虚拟地址空间
32位机器中,进程虚拟地址空间为4G(= 2^32 ),实际内存地址空间没有这么大。
MMU:将虚拟的地址转化为物理地址。
这样做的好处在于:
- 进程隔离,更好的保护系统安全运行
- 屏蔽物理差异带来的麻烦,方便操作系统和编译器安排进程地址
静态局部变量放在.data区。
栈区:超出作用域范围后,变量消亡;
堆区:动态分配内存。
上面两个都不符合静态局部变量的特点。
查看栈空间大小:(一般10M左右)
- 递归测试;
- 使用命令查看。
栈地址是从高到低,而堆地址相反,从低到高。
只读数据段即常量区。
运行程序时,会将程序加载到内核区中。因此程序运行中即使强制(从硬盘)删除文件,程序也仍然还在运行。
内核区中,用户无权进行操作。
5. 文件描述符
打开现存文件或新建文件时,系统(内核)会返回一个文件描述符。
文件描述符用来指定已打开的文件。这个文件描述符相当于这个已打开文件的标号,文件描述符是非负整数,是文件的标识,操作这个文件描述符相当于操作这个描述符所指定的文件。
每个进程都有一张文件描述符的表,默认会打开标准输入、输出、错误输出。打开新的文件会打开新的文件描述符,最多打开1024个文件。
6.阻塞和非阻塞
读写常规文件是不会阻塞的,不管读写多少字节,一定会在有限时间内返回。
而向终端设备或网络写则不一定:如读数据时,如果终端没有输入的数据、没有接收到数据包,那么将会一直等待数据;如果写满后没有及时获得新的写入空间,那么写数据也会阻塞。阻塞时间不确定。
【注意】阻塞与非阻塞是对于文件而言的,而不是指read、write等的属性。