众所周知计算机其实都是由一个个的硬件组成的输入设备包括键盘、鼠标、扫描仪等输出设备显示器、打印机等存储器主要指的是内存中央处理器就是CPU含有运算器和控制器等从这个体系结构图中我们能看出在数据层面上CPU不会和外设输入输出设备进行交互CPU只会和内存打交道。外设要输入或输出数据只能写入内存中或从内从中读取。数据可以提前加载到内存中所以计算机处理数据可以认为主要就是CPU和内存之间的交互。总结就是所有设备只能直接和内存打交道所以计算机的效率主要取决于内存。而它们之间的数据流动过程本质都是拷贝也就是计算机的效率由拷贝效率决定二、操作系统的基础概念任何一个计算机系统都包含一个基本的程序集合称为操作系统OS。广义上理解它包含操作系统内核、其他程序函数库、shell程序等操作系统的内核是它的核心内核有四大功能内存管理、文件管理、驱动管理、进程管理。在整个计算机软硬件架构中操作系统是一款软件专门用于软硬件资源管理想象这样一个场景用户到银行取钱用户是上层软件金库是计算机硬件。如果让上层软件直接操控底层硬件就像让用户直接去金库拿钱管理起来就十分麻烦所以就需要有操作系统进行中间管理——操作系统就像银行柜员用户与柜员沟通存取钱柜员再负责向金库中存取钱。这样一来从整个银行行长角度看管理软硬件资源就很方便了。在程序员开发角度操作系统对外会表现为一个整体暴露部分接口给上层开发使用这部分操作系统提供的接口称为系统调用。三、初识进程1. 进程的概念与描述1.1 基本概念进程是操作系统学科中一个很重要的知识操作系统的进程管理、内存管理、文件管理、设备管理等核心功能都围绕进程展开。一般的教科书上可能讲进程的概念是程序的一个执行实例、正在执行的程序、是程序的一次执行过程等。或者从内核层面来看进程是担当分配系统资源CPU时间、内存等的实体是操作系统进行资源分配和调度的基本单位等没有错。我认为更精辟的总结是进程 内核数据结构对象 程序的代码和数据这个概念需要我们在后面的学习中慢慢体会。1.2 描述进程的数据结构PCBLinux系统的内核主要是由C语言写的。一个进程的信息被存放在一个叫做进程控制块的数据结构中是进程属性的集合。在操作系统学科中这个数据结构统称为PCBprocess control block。具体在Linux系统中它是一个C语言结构体名字是task_struct task_struct中有很多的信息在接下来我们学习进程会不断了解的。2. 查看进程在Windows系统下双击启动应用、手机上启动app、Linux中执行命令和程序本质都是启动了进程我们也有相应的方法去查看进程。命令ps axj查看系统中所有进程的部分信息在这里插入图片描述当前系统中还有很多隐藏的进程为了方便查看到我们想要的进程可以搭配head和grep命令使用。为了方便演示我写一个这样的程序test.exe在这里插入图片描述这个程序可以一直运行除非ctrl c中断。我把它运行起来然后新开一个终端页面执行代码语言javascriptAI代码解释ps axj | head -1 ps axj | grep test.exe(head -1是为了保留第一行列名grep是为了查询有test.exe文本的进程)结果是在这里插入图片描述可以看到查询结果有两行第二行是上面ps命令的进程因为说过执行命令也是启动了进程不用在意。重点是第一行这就是我们正在一直运行的test.exe程序的进程信息2.1 pid和ppid有一列名是PID是进程id用来描述本进程的唯一标识符用来区别其他进程。 一个进程可以获取到自己的pidOS提供了一个系统调用getpid返回当前进程的pid在这里插入图片描述使用它需要包含头文件#includesys/types.h和#includeunistd.h返回类型pid_t其实就是一个整型。可以证明一下在test.exe中加一句printf(%d\n, getpid());在这里插入图片描述还有一列为PPID是父进程idLinux中新的进程往往是通过其他进程创建的这就是父进程。ppid就是一个进程的父进程id。 刚才说过执行命令也是创建了进程那么这个进程的父进程是谁呢在上图中第二行是执行的命令它的ppid是8059那么我们就可以查看一下谁的pid是8059ps axj | head -1 ps axj | grep 8059在这里插入图片描述进程id是8059的是一个叫-bash的东西-bash是Linux系统的命令行解释器是所有命令行执行命令的进程的父进程也就是说我们执行Linux的命令本质都是-bash创建了子进程也有一个叫做getppid()的系统调用可以获取到当前进程的ppid用法和getpid一样不再赘述。3. fork创建子进程刚才说一个进程是由父进程创建的。我们自己写的程序启动后也是一个进程按理说也能创建子进程。Linux就有这样一个系统调用fork在这里插入图片描述fork函数的返回值很有意思在这里插入图片描述调用fork后会创建一个子进程。在父进程中fork的返回值是子进程的pid在子进程中fork的返回值是0如果子进程创建失败则在父进程中返回-1默认条件下fork后父子进程是共享代码和数据的举个栗子代码语言javascriptAI代码解释#includestdio.h #includeunistd.h #includesys/types.h int main() { // 创建子进程 pid_t id fork(); while(1) { if(id -1) { //子进程创建失败一般不会失败 return 1; } else if(id 0) { //子进程中执行 printf(子进程,pid%d\n, getpid()); } else { //父进程中执行 printf(父进程,pid%d\n, getpid()); } sleep(1); } return 0; }执行后在这里插入图片描述为什么fork的返回值是这样规定的呢这是因为一个子进程只会有一个父进程而一个父进程可以创建出多个子进程为了标识特定的子进程父进程需要得到子进程的pid。