资讯中心

Linux操作 系统编程【笔记】

📅 2026/7/4 10:02:33
Linux操作 系统编程【笔记】
学习目标1、计算机的基本组成2、进程概述3、简单分页的内存管理4、C程序两个问题学习内容1、计算机的基本组成冯·诺依曼体系 计算机有五大部件组成计算器控制器存储器 – 内存、主存输出设备 – 磁盘、显示器 -output输入设备 – 磁盘、键盘、鼠标 -inputIO 输入、输出。读取或写入的效率相对于内存操作是比较低的 CPU - 一级缓存 - 二级缓存 - 内存 - IO系统总线类型控制总线 由于各个连接数据总线和控制总线的部件都是共享这两个总线的所以他是用来指定某一时刻由谁来控制总线的数据总线 : 用于在各个功能部件间传输数据的是双向传输总线地址总线 用于支出数据总线上的源数据或目的数据在主存单元的地址或者IO设备的地址 --》 地址总线决定了CPU的寻址能力扩充32位机器 CPU的计算能力一次能够计算的数据的数据宽度ALU的宽度一次能处理的数据的最大位数32位 – 最大的处理数字- x8632位 指针都是4字节 x6464位指针都是8字节 - 指令地址码操作码2、进程概述进程的概念一个正在运行的程序。程序二进制可执行文件​ - 进程是一组有序指令数据资源内存资源、CPU资源的一个集合。执行一个程序使之成为一个进程操作系统先得分配一个PCB变量再需要将二进制文件加载到内存上操作系统使用调度策略来分配CPU去执行加载到内存上的指令和数据。操作系统如何管理进程将进程相关的一些属性信息一组保存到一个地方内存 — 通过C语言的结构体将这些属性信息组织在一块 — PCB进程控制块task_structPCB即是进程控制块是进程存在的唯一标志用来描述进程的属性信息。操作系统维护管理所有的PCB是通过双向循环链表任务队列 task list有优先级的队列进程结束时操作系统先释放进程主体再释放PCB。孤儿进程父进程拥有子进程子进程还在运行但是父进程提前结束了此时子进程就成了孤儿进程。孤儿进程会被init进程(进程号为1)所收养并由init进程对它们完成状态收集工作。僵尸进程PCB 还在进程实体已经释放了。僵尸进程的处理当子进程终止时内核就会向它的父进程发送一个SIGCHLD信号父进程可以选择忽略该信号也可以提供一个接收到信号以后的处理函数。系统默认动作是忽略该信号。所以可以在父进程接收到SIGCHLD信号后就应该调用wait 或 waitpid函数对子进程进行处理就可以释放子进程占用的资源不过有些时候当有很多个子进程都结束了的时候内核都会向父进程发送SIGCHLD信号而父进程此时有可能仍然处于接受该信号并进行处理的函数中那么在处理完之前中间接收到的SIGCHLD信号就会丢失内核并没有使用队列等方式来存储同一种信号所以为了解决这一问题我们需要调用waitpid函数来清理子进程进程的状态就绪所有的条件资源都准备完成只等CPU空间来调度执行。执行正在被CPU执行的其中的命令阻塞所需要某些事件条件还没好并发与并行更多是并发编程。3、简单分页的内存管理简单分页将内存空间划分为大小相等的相对于内存大小而言这个大小很小比较经典的就是4k区块将其称为页帧。对所有的页帧可以编号。4G内存有2^20个页帧。操作系统为每一个进程维护一个页表。页表中记录了该页加载到内存上的那个页帧还有一些控制信息。编译链接连接过程合并所有的段调整段的大小和起始位置合并符号表进行符号解析给符号分配虚拟地址符号重定位。程序中的地址都是虚拟地址在程序运行时需要通过虚拟地址找到内存上的一个确定位置。除了与这个虚拟地址有关还与进程的页表有关。交换分区在磁盘上开辟一块空间作为对内存的补充。一个进程并不需要所有的页都在内存上驻留。可以执行比内存空间还大的一些进程。也可以执行更多的进程。操作系统发展史操作系统管理计算机上的软硬件资源为用户提供一个交互的窗口。串行处理 — 批处理 — 多道程序设计 — 分时系统 — 实时系统4、C程序两个问题主函数的参数主函数默认至少接受一个参数就是执行程序命令本身。传递参数时按照空格来区分各个参数。传递的参数的类型都是字符串与用户给定的参数的类型无关。#includestdio.h#includestring.h#includestdlib.h/* envp:是一个字符指针数组环境变量 */intmain(intargc,char*argv[],char*envp[]){inti0;while(envp[i]!NULL){printf(%s\n,envp[i]);i;}return0;}#if0/* argc:整形 传递的参数个数 argv:字符指针数组每一个数组都是一个字符指针字符串 传递的参数列表 */intmain(intargc,char*argv[]){printf(%d\n,argc);intnum0;sscanf(argv[1],%d,num);printf(num%d , num*num %d\n,num,num*num);for(inti0;iargc;i){printf(%d:%s\n,i,argv[i]);}return0;}#endif输出缓冲区在Linux系统上一个进程默认打开第三个文件标准输入stdin 标准输出 stdout 标准错误输出stderrprintf函数仅仅是将内容写到标准输出缓冲区中等满足一定条件才会将内容输出到界面上遇到 “\n”进程结束时主动刷新 fflush(stdout);缓冲区满#includestdio.h#includeunistd.h#includestdlib.hintmain(){printf(hello);//printf仅仅是将内容写到输出缓冲区中sleep(3);printf(world);//结果是一块输出exit(0);}exit和_exit的区别exit会刷新缓冲区的内容_exit不会刷新缓冲区直接结束进程。atexit函数atexit注册函数向操作系统注册一个函数这个函数当前不会被调用程序结束时调用exit之后exit函数退出之前调用之前注册的函数。#includestdio.h#includeunistd.h#includestdlib.hvoidfunc1(){printf(func1...\n);}intmain(){atexit(func1);atexit(func2);printf(main start\n);sleep(2);printf(main end\n);exit(0);}若遇到_exit则不会调用也可以使用atexit调用多个函数最多注册32个函数进程结束时按照出栈的顺序来调用