鹤壁商城网站建设,正规网站建设服务中心,沈阳男科医院在线咨询免费,怎么制作图片文件文章目录 1.进程的概念①描述进程-PCB②task_struct-PCB的一种③task_ struct内容分类 2.查看进程3.通过系统调用获取进程表示符4.通过系统调用创建进程---fork初识 1.进程的概念 在我们的电脑开机的时候#xff0c;操作系统会被加载到内存中#xff0c;点击多个应用进行时操作系统会被加载到内存中点击多个应用进行时那么将有多个应用的进程会被加载到内存中的操作系统上。说明一个操作系统不仅仅可以运行一个进程而且可以运行多个进程既然有多个进程了那么就需要将这些进程有条不紊地管理起来那操作系统是如何管理进程的呢先描述在组织任何一个进程加载到内存中形成真正的进程时操作系统要创建描述进程的结构体对象接下来便是将这些进程信息块组织起来使用双链表的数据结构进行管理 在很多人的理解中一个加载到内存中的程序叫做进程或者正在运行的程序叫做进程其实这些都是片面的理解假如你被复旦大学录取了难道就可以说你是复旦大学的学生了吗当然不是的你被录取了表明你的档案信息已经被该大学收录了而要想真正成为该大学的学生到开学的时候你要拿着录取通知书到复旦大学入学报到这个时候你才真正成为了复旦大学的学生同理进程应该包括描述进程的信息和需要处理的代码和数据 ①描述进程-PCB
进程信息被放在一个叫做进程控制块的数据结构中可以理解为进程属性的集合进程内核PCB数据结构对象自己的数据和代码
②task_struct-PCB的一种 在Linux中描述进程的结构体叫做task_struct。课本上称之为PCBprocess control blockLinux操作系统下的PCBtask_struct ③task_ struct内容分类 标示符描述本进程的唯一标示符用来区别其他进程。状态任务状态退出代码退出信号等。优先级相对于其他进程的优先级。程序计数器程序中即将被执行的下一条指令的地址。内存指针包括程序代码和进程相关数据的指针还有和其他进程共享的内存块的指针上下文数据进程执行时处理器的寄存器中的数据[休学例子要加图CPU寄存器]。IO状态信息包括显示的I/O请求分配给进程的I/O设备和被进程使用的文件列表。记账信息可能包括处理器时间总和使用的时钟数总和时间限制记账号等。其他信息 2.查看进程 PID为子进程标志相当于学生的学号。进程的信息可以通过 /proc 系统文件夹查看 输入ls /proc/指令可以看到不同PID的文件 大多数进程信息同样可以使用top和ps这些用户级工具来获取 创建myprocess.c文件如下
#includestdio.h
#includeunistd.h
int main()
{ while(1) { printf(我是一个进程....\n); sleep(1); } return 0;
} 创建自动化构建文件Makefile文件如下
myprocess:myprocess.c gcc -o $ $^
.PHONY:clean
clean: rm -rf myprocess Xshell代码运行的结果如下 在另一个窗口输入如下指令
$ ps ajx | head ps ajx | grep myprocess//获取含myprocess的进程PID指令运行的结果如下 ./myprocess为正在运行的可执行程序grep --colorauto myprocess为刚才我们运行的获取PID指令中包含了myprocess说明输入的指令在系统中变成了进程运行。 可以使用如下指令过滤掉grep myprocess进程
$ ps ajx | head -1 ps ajx | grep myprocess | grep -v grep关闭进程的指令
$ ps -9 进程的PID//杀进程查看进程文件
$ ls /proc/4356/ -l //获取PID为4356的进程文件详细信息进程文件详细信息部分截图如下
3.通过系统调用获取进程表示符
在前面操作系统的学习中操作系统通过数据结构将描述的进程信息组织起来管理我们作为普通用户很难和操作系统打交道所以不能直接获取当前进程PID但是可以通过操作系统上层封装的系统调用接口获取PCB结构描述的信息接下来让我们认识两个系统调用接口 getpid()获取子进程PID的信息。 getppid()获取父进程PPID的信息。 创建proc.c文件写入如下代码
#includestdio.h
#includesys/types.h
#includeunistd.h
int main()
{ printf(我是一个子进程pid为:%d\n,getpid()); printf(我是一个父进程ppid为:%d\n,getppid()); return 0;
} 代码运行的结果为 重新运行./proc文件其子进程一直在变比如某学生高考失利进入复旦大学时他可以获得一个学号当他第二年复读再次考入复旦大学时他又获得一个学号而这两个学号是不同的而父进程一直都不变。 $ ps ajx | head -1 ps ajx | grep 3216 //父进程父进程ppid为bash命令行进程给我们输入指令的 4.通过系统调用创建进程—fork初识
使用man指令查找fork函数的信息 解释 fork函数创建一个新的进程让当前的父进程返回当前的子进程创建新的子进程返回0。 eg1
#includestdio.h
#includesys/types.h
#includeunistd.h int main()
{ printf(我是使用fork()之前的语句\n); pid_t retfork(); printf(我是使用fork()之后的语句\n); return 0;
} 代码运行的结果为 可以发现fork()函数创建新的子进程当前的进程执行了printf语句创建的进程执行了一遍的printf语句所以fork()后面的语句被执行两遍。 eg2
#includestdio.h
#includesys/types.h
#includeunistd.h
int main()
{ printf(begin: 我是一个进程,pid:%d,ppid:%d\n,getpid(),getppid()); pid_t retfork(); if(ret0) { while(1) { printf(我是子进程pid:%d,ppid:%d\n,getpid(),getppid()); sleep(1); } } else if(ret0) { while(1) { printf(我是父进程pid:%d,ppid:%d\n,getpid(),getpid()); sleep(1); } } return 0;
} 代码运行的结果为 指令
while :; do ps ajx | head -1 ; ps ajx | grep proc |grep -v grep;sleep 1;done在另一个窗口执行该指令 使用fork函数创建新的进程使用if语句根据父进程返回当前的子进程返回的值大于0旧的子进程返回0实现分流执行不同的代码。 问题1为什么fork函数返回子进程父进程返回当前的子进程 一般而言fork函数之后的代码父子进程共享返回不同的值让不同的执行流执行不同的代码 问题2fork函数如何做到返回两次 ①创建子进程PCB②填充PCB的内容③让父子进程共享同一份代码④父子进程的task_struct可以被CPU调用…最后执行return语句返回return语句之前fork函数的主要工作已经完成了即创建新的子进程所以return语句为父子进程共享的语句所以父进程返回一次子进程返回一次。 问题3fork干了什么事 进程之间是不会相互影响相互独立①fork创建了子进程子进程依据父进程为模板PCB模板创建自己的PCB指向父进程的代码②那指向的数据是否相同呢子进程和父进程刚开始指向的数据相同当操作系统检测到子进程要修改数据时会开空间会发生写时拷贝但不是把父进程的数据全部拷贝子进程只会拷贝自己能使用的数据避免造成资源浪费。 问题4一个变量怎么会有不同的内容 我们已经知道了fork函数可以返回两次并且同一个变量可以接收两次不同的值即访问不同的内存那是怎么做到一块地址空间是怎么接收呢我们后面再进行学习 问题5如果父子进程被创建好fork往后哪个进程被先运行呢 哪个进程先运行是由调度器挑选进程决定的我们是不能确定的 问题6执行不同命令时子进程不同但这些子进程的父进程都为bash进程为什么呢 bash内部也是通过fork函数创建子进程的bash进程执行接收新的命令、打印出命令行提示符等任务而bash创建的子进程执行解释新的命令所以我们当前运行的所有的命令都是bash的进程。