假网站连接怎么做的,本地wordpress数据,企业专业网站设计公,seo工资#x1f440;樊梓慕#xff1a;个人主页 #x1f3a5;个人专栏#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》
#x1f31d;每一个不曾起舞的日子#xff0c;都是对生命的辜负 目录
前言
1.基本概念
2.描述进程-PCB…
樊梓慕个人主页 个人专栏《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》
每一个不曾起舞的日子都是对生命的辜负 目录
前言
1.基本概念
2.描述进程-PCB
2.1task_struct-Linux中的PCB
2.2task_struct内容分类成员
3.查看进程
3.1通过系统目录查看
3.2通过用户级工具ps查看
4.通过系统调用获取进程标识符PID
4.1PCB是属于操作系统的还是属于进程的 4.2使用getpid和getppid
5.通过系统调用创建进程fork初识
5.1fork函数创建子进程
5.2fork的返回值
5.3使用if进行分流 前言
上篇文章我们说学习系统我们要翻越三座大山进程周边、文件周边以及线程周边。
那今天我们就对第一座大山进程周边开启攀登之旅
本篇文章主要讲解有关进程的基本概念以及Linux系统下是如何管理进程的还记得学习管理的六字真言么没错对于进程的管理也是先描述再组织。
之后我们再来学习下如何查看进程以及进程的标识符PID、父进程的标识符PPID。
最后我们初步的认识下fork函数并利用fork函数实现创建子进程等。
话不多说直接进入我们今天的学习✍ 欢迎大家收藏以便未来做题时可以快速找到思路巧妙的方法可以事半功倍。 GITEE相关代码fanfei_c的仓库 1.基本概念
较为官方的说法
课本概念 程序的一个执行实例正在执行的程序等。内核观点 担当分配系统资源CPU时间内存的实体。
辅助理解
对代码进行编译链接产生的文件我们称之为可执行程序.exe执行该程序该程序会被加载到内存中此时便称之为进程。 2.描述进程-PCB
上节课我们学习了管理的概念并总结为六字真言先描述再组织。
那对于操作系统来说管理进程的方式仍然归结于这六字真言中。
我们也可以将进程描述起来描述得到的就是进程控制块PCBprocess control block。
PCB就是进程属性的集合数据结构里面存储的是进程信息。 管理不是直接管理人而是管理人的信息 管理不是直接管理进程而是管理进程的信息PCB。 此时操作系统对进程的管理就转化为对PCB对象的管理。
那对于某个数据结构的管理我们是很熟悉的假如我们利用链表的方式进行组织那对于进程的管理说白了就是对链表的增删查改。 换句话说进程PCB内核数据结构可执行程序 未来所有对进程的控制和操作都只和进程的PCB有关和进程的可执行程序没有关系。 如果愿意你可以把PCBNode节点放到任意数据结构中去。 2.1task_struct-Linux中的PCB
task_struct就是在Linux中描述进程的结构体Linux是C语言编写。 你可以理解为PCB是操作系统学科抽象的叫法而在Linux中具体为task_struct。 即task_struct是Linux内核的一种数据结构它会被装载到RAM内存里并且包含进程的信息。 2.2task_struct内容分类成员
标示符PID 描述本进程的唯一标示符用来区别其他进程每次启动都会变化。状态 任务状态退出代码退出信号等。优先级 相对于其他进程的优先级。程序计数器(pc) 程序中即将被执行的下一条指令的地址。内存指针 包括程序代码和进程相关数据的指针还有和其他进程共享的内存块的指针。上下文数据 进程执行时处理器的寄存器中的数据。I/O状态信息 包括显示的I/O请求分配给进程的I/O设备和被进程使用的文件列表。记账信息 可能包括处理器时间总和使用的时钟总和时间限制记账号等。其他信息。 3.查看进程
3.1通过系统目录查看
根目录下的proc目录/proc下存储着进程信息。 目录名为数字的即为进程信息的目录每个目录内存储着他们对应的进程信息。
而这些数字对应着该进程的标识符PID。
比如查看标识符PID1的进程信息 当我们新建一个普通的进程并进入该进程所在目录时 我们可以利用chdir系统调用接口修改工作目录。 3.2通过用户级工具ps查看 实例ps ajx/ps aux 该命令可以查看所有系统进程。 现在我们来写一段代码并生成可执行程序执行后变成进程我们如何查看呢
1代码
#includestdio.h
#includeunistd.h int main()
{while(1){printf(I am a process!\n);sleep(1);}return 0;
} 2编译后执行 3打开多窗口方便我们观察 4如何查看单个进程
首先我们已经知道如何查看系统中所有进程了即ps ajx那我们可以利用Linux之前学习的一些指令来显示我们想要查看的单个指令。 实例ps ajx | head -1 ps ajx | grep test 对以上指令的解释 我们来观察一下是否是我们想要的结果 我们发现test进程利用刚才的指令我们得到了该进程的相关信息但是黄色框内是什么
其实是grep命令 这里也侧面反映出几乎所有独立的指令就是程序运行起来也是进程。
这里grep实际也是进程且该进程内包含有test的信息所以也显示出来了。
如何去掉这多余信息呢 实例ps ajx | head -1 ps ajx | grep test | grep -v grep -v选项是反向搜索的意思即过滤掉包含有grep内容的信息。 另外我们也可以通过指令对进程进行检测检测他是否运行 实例while :; do ps ajx | head -1 ps ajx | grep test | grep -v grep; sleep 1;done 观察进程创建和销毁的过程 所以我们发现进程是有生命的 4.通过系统调用获取进程标识符PID
4.1PCB是属于操作系统的还是属于进程的
答案是属于操作系统的虽然PCB记录的是进程的相关信息但是PCB是由操作系统创建并维护的。
那既然PCB是属于操作系统的那我们如何查看PCB的信息呢
在操作系统的那篇文章中我们提到过用户想要获取操作系统的信息需要调用系统接口。
所以获取进程标识符(PID)等PCB的信息我们需要通过系统调用来获得所以我们来认识下getpid()。
首先我们利用man getpid查看下命令手册 我们发现getpid是在2号手册中利用man man我们知道2号手册中记录的就是系统调用接口。 4.2使用getpid和getppid
1编写代码
#includestdio.h
#includeunistd.h
#includesys/types.h
int main()
{pid_t id getpid();while (1){printf(I am a process!pid:%d\n, id);sleep(1);}return 0;
}2执行可执行程序并观察 那我们再来学习一下getppid获取父进程的进程标识符。
一般在Linux中普通进程都有他的父进程。 每一个子进程都是由父进程创建出来的。 子进程只能有一个父进程父进程可以有多个子进程。
每次执行可执行程序进程标识符会改变因为每次都是新的进程。 那我们来观察一下他的父进程
3编写代码
#includestdio.h
#includeunistd.h
#includesys/types.h
int main()
{pid_t id getpid();pid_t fid getppid();while (1){printf(I am a process!pid:%d ppid:%d\n, id, fid);sleep(1);}return 0;
}4执行可执行程序并观察 我们来查询一下该进程的父进程究竟是什么 我们发现该进程的父进程是bash命令行解释器。 在命令行启动的进程都是bash的子进程。 5.通过系统调用创建进程fork初识
./可执行程序的方式是一种手动创建进程的方式。fork则是通过系统调用创建进程。
5.1fork函数创建子进程
#includestdio.h
#includesys/types.h
#includeunistd.hint main()
{printf(before fork : I am a process,pid:%d,ppid:%d\n, getpid(), getppid());fork();printf(after fork : I am a process,pid:%d,ppid:%d\n, getpid(), getppid());sleep(2);return 0;
}
现象 确实如我们所料fork执行后创建出了一个子进程。 并且我们发现fork后面的语句执行了两次。
也就是说fork之后代码共享从一个进程分为两个分支一为父一为子。 那我们如何知道谁是父谁是子呢
这就要研究一下fork函数的返回值问题了。
5.2fork的返回值 意思是返回给父进程的是子进程的PID返回给子进程的是0. 为什么 因为父子 1n子找父是很容易的而父找子必须有子的pid。 两个返回值么
我们来验证一下 执行结果
也就是说父进程使用该变量就返回子进程的pid子进程使用就返回0。 提问fork函数为什么会返回两次 当一个函数运行到了最后执行return的时候这个函数的核心逻辑已经执行完成了 而fork函数中必然会有创建子进程这一操作所以在fork函数返回值之前子进程已经存在了。 所以fork函数会返回两次值写入到变量中。 提问id怎么可能同一个变量既等于0又等于pid 一个进程崩溃会不会影响其他进程呢答案是不会。 注任意进程之间是具有独立性的互相不能影响即便是父子进程。 子进程被创建时会继承大部分父进程的属性即子进程的创建是以父进程为模板的。 模拟场景父进程或子进程对一共享数据进行修改会发生什么 前面我们刚说到任意进程之间具有独立性互相不能影响所以操作系统必须保证这一点。 假如为子进程修改该数据子进程会从父进程那拷贝一份到自己这里进行修改这一行为称之为写时拷贝。 父进程修改该数据也如此。 id就是这一共享数据返回的本质就是写入。 linux中可以使用同一变量名表示不同的内存。 提问我们创建子进程的目的是什么 一般而言我们想让父子做不同的工作。 所以我们就可以利用返回值的不同使用if进行分流。 5.3使用if进行分流
#include stdio.h
#include sys/types.h
#include unistd.h
int main()
{int ret fork();if (ret 0) {perror(fork);return 1;}else if (ret 0) { //child的工作代码段}else { //father的工作代码段}sleep(1);return 0;
} 本篇内容就到这里其中有些知识需要学习到进程地址空间才能深入研究博主会持续更新Linux系列文章欢迎大家关注哈 如果你对该系列文章有兴趣的话欢迎持续关注博主动态博主会持续输出优质内容
博主很需要大家的支持你的支持是我创作的不竭动力
~ 点赞收藏关注 ~