目录
1. Windows上用return 0结束程序~ Linux上用头文件stdlib.h中的exit(0)正常退出进程。
2. <unistd.h>为Linux专有的头文件,包含一些可用的函数(如sleep())。
3. 用方向键可以将执行过的指令调出来。
4. 所有的头文件包含在哪里呢? cd/ -> cd usr -> cd include
/bin~命令 /lib库文件 /usr/include头文件
1. 关于printf 刷缓冲区
分析下面两个程序printf()函数的不同:
程序1会在打印出Hello World!之后睡眠三秒才结束进程。
程序2会在睡眠三秒后才打印Hello World!结束进程。由于执行printf时将Hello World!放在缓冲区,直到睡眠3秒结束后调用exit(0)程序要结束因此刷新缓冲区才打印出Hello World!
打印:将数据交给内核(操作系统),再由操作系统打印出来。由于我们会不断的进行用户态->内核态的切换,为了减少开销提升效率,因此有了缓冲区的存在。
程序结束exit(0):第一步刷新缓冲区、第二步调用_exit()直接结束进程
printf 刷缓冲区满足条件:
1.缓冲区放满,自动刷缓冲区
2.缓冲区未满,强制刷新缓冲区: \n 或 fflush(stdout)
2. 主函数的参数(3个)
int main(int argc , char* argv[] , char* envp[])
int argc:参数个数(数组argv[]元素个数)
char* argv[]:参数内容(其中argv[0]=./main 运行程序名)
char* envp[]:环境变量
(1)打印参数个数及内容
(2)打印环境变量(环境变量是从父进程中继承过来的)
由于环境变量末尾为空指针,所以循环条件即为*envp!=NULL。
环境变量中有PATH,打印环境变量:echo $PATH
3. 修炼内功
1.冯诺依曼体系将计算机分成了五大部件:运算器、控制器、存储器、输入设备、输出设备。
2.CPU集成了运算器和控制器。
3.存储器~内存(RAM,易失性:一旦关机、断电即消失)。硬盘~I/O设备。
eg:main.c在磁盘(硬盘)中存放、编译后的可执行程序main也在磁盘中。 执行程序./main:将磁盘中的main通过总线传输到内存中并占用部分空间,执行完后内存空间释放。
程序:由一条条指令构成;进程:正在执行的程序。
4.内存由内核(操作系统)来管理。
操作系统:管理计算机上的软硬件资源(主要管理内存、进程、文件),为用户提供交互的接口。
操作系统通过进程控制块PCB(实际为一个结构体struct,其中pid进程号唯一标识一个进程)来管理进程(进程三状态:就绪、运行、阻塞)。
struct task_struct
{
int pid; //唯一标识一个进程的进程号
int status; //进程当前所处的状态:就绪、运行、阻塞
//.....
{
Windows上的可执行程序为PE格式,Linux上为ELF格式。
5.如何管理内存?
页表:记录物理页(内存,4K、4K划分)和逻辑页的对应关系,即页号对应物理块号。
通常逻辑页首页地址不为0。
对应关系不是固定的,每次在分配(运行程序)的时候是操作系统看内存哪里有位置就分配。
调试程序时看到的地址均为逻辑地址!是由于我们不知道物理内存哪里是空闲的,所以无法直接指定使用物理内存。
问:如何根据逻辑地址对应物理地址(逻辑页->物理页)? 通过页表:1.找对应关系(页号~物理块号);2.根据页面偏移量(即物理块偏移量)计算确定。
4. 进程、fork()复制进程(子进程)
1)父进程中执行fork()复制当前进程(父进程)的PCB,但进程号pid不同
2)子进程从fork()语句后接着往下执行,父进程也从fork()返回处接着往下执行。
注意:唯一区别为fork()返回值。
父进程中:fork()返回值为子进程的id号。
规定子进程中:fork()返回值为0。