Linux—深入理解进程的概念,PCB,父子进程及查看进程信息的两种方法
进程的概念
课本概念:程序的一个执行实例,正在执行的程序等。
内核观点:担当分配系统资源(CPU,内存)的实体。
?1.描述进程-PCB
我们知道程序是代码编译好后形成的可执行文件,存放在磁盘上。而我们通过学习冯诺依曼体系结构后知道,要想运行程序,需要先把磁盘上的程序加载(将程序拷贝到内存中)到内存上,那么这就是进程了吗?
这里在程序加载到内存之前,就有一个软件运行起来了,这个软件就是操作系统。实际上将程序加载到内存里就是操作系统完成的。往往我们会运行多个程序,将多个程序加载到内存中(这里我们暂且将其叫做"进程"),而操作系统是管理软硬件,进行资源分配的,因此操作系统就需要将它们管理起来,对于操作系统对事物的管理:先描述,再组织!!!??
那么操作系统又是如何描述,组织"进程"的呢?
我们知道操作系统是用C语言写的,因此操作系统会为每一个"进程"定义一个struct结构体,用来描述每一个"进程",而struc结构体里面的内容包含了"进程"的各种属性,同时为了更加方便管理多个进程,这里选择链表进行组织,在struct结构体里加了一个指向下一个描述进程的结构体的指针。
struct XXX
{
//进程的各种属性!!!
struct XXX* next;//结构体指针,指向下一个描述进程的结构体
}
在操作系统中我们常常把用来描述进程的struct结构体叫做PCB(process control block,进程控制块)
虽然现在我们并不知道里面具有什么,但是根据常识,我们可猜测出一些:
struct PCB
{
//id 进程标识符
//代码地址&&数据地址
//状态
//优先级
struct PCB* next;
}
所以我们现在回过头再来看
我们知道程序是一个在磁盘上的一个普通文件,当我们执行程序时,操作系统会把它的代码与数据加载(拷贝)到内存上,而操作系统为了管理这些,所以为每一个"进程"创建了一个PCB,里面记录了各种代码,数据等东西(这里使用指针指向数据所在地址的方式记录)。同时使用链表将各个PCB管理起来,
因此在操作系统层面上就形成了一个struct PCB* process list链表,所以对"进程"的管理就变成了对proc list这个链表的进行增删改查的管理。
我们可能经常会听老师说进程在排队。
现在我们可以知道进程在排队就是对进程的管理,操作系统会把对应进程对应的PCB找到并放到对应的队列里。
所以进程也可以被看成:
进程 = 可执行程序 + 内核数据结构(PCB)
内核数据结构存在的意义:方便操作系统对进程进行管理!
在Linux中进程的PCB具体是struct task_struct{},通过双链表将其连接起来
2.进程标识符pid
每一个进程都有一个对应的pid
查看当前进程的信息:
ps ajx
这个是查看当前所有进程的信息,不利于我们查看我们想看的进程信息,
我们写一个无限循环的程序,并执行
#include<stdio.h>
#include<unistd.h>
int main()
{
while(1)
{
printf("这是一个进程\n");
sleep(1);
}
return 0;
}
然后指令:
ps ajx | head -1 && ps ajx | grep mybin
//ps ajx | head -1 将进程信息的第一行打印出来
//ps ajx | grep mybin 将含有mybin的进程打印出来
我们运行的所有指令,软件,自己写的程序,最终都是进程!!!
3.系统调用函数getpid()
如果每次查看一个进程的pid,都要使用ps指令,会过于麻烦。这里我们可以通过系统调用函获取进程的pid,在程序中打印进程的pid。
函数:
getpid()
使用man手册查看getpid()的使用方法:
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
pid_t id=getpid();
while(1)
{
printf("我是一个进程,我的pid是:%d\n",id);
sleep(1);
}
return 0;
}
pid的作用:
1.标识一个进程
2.用户可以通过pid来对进程做管理。
4.在Linux下使用指令终止进程
在程序运行中我们可以在运行的地方按CTRL+c来结束进程,同时我们还可以使用指令:
kill -9 要杀掉进程的pid
(注:这里-9是信号参数,直接使用即可)
5.父进程与子进程
在Linux中,登录后,命令行多次执行同一程序时,对应的pid时不断变化的,但是其ppid是不变的,那么ppid是什么呢?
ppid是当前进程的父进程的pid
那么这个父进程是谁呢?
这里我们需要知道,在Linux中创造进程的方式:
1.命令行中直接启动进程--手动启动
2.通过代码创建进程
这里不论你是如何创建进程的,启动进程的本质是创建进程,一般是通过父进程创建的。在创建进程时,会创建PCB来管理这个进程,里面的内容一般会用父进程PCB里的东西进行初始化(这个关系我们叫做父子关系)
这里我们通过命令行启动的进程的父进程,是bash
1.通过系统调用接口getppid获取父进程的pid
首先用man手册查看getppid的用法。
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
printf("我是一个进程,我的pid是:%d, 我的ppid:%d\n",getpid(),getpppid());
return 0;
}
查看进程的第二种方式:
查看进信息除了了ps指令外,还有另一种方式。
在Linux下,有一个动态的目录结构,存放所有进程的信息,目录的名称就是以这个进程的pid命名的。这个目录是proc
当我把这个进程杀掉后,617这个目录就会消失
每一个进程都能找到自己的可执行程序
在查看进程的信息是,我们发现其中的exe指向了我们可执行文件的路径。在Linux中进程知道自己在磁盘上的文件在哪里。
当我们把进程在可执行程序磁盘上的可执行文件删掉后,我们正在执行的进程仍可以正常进行
原因:我们已经把进程的可执行文件拷贝到了内存上,因此磁盘上可执行文件删除并不会影响到正在执行的进程,但是却无法再次执行了。
同时当我们删除后,exe执行的路径变红
每一个进程,都要有自己的工作目录
进程的工作目录的作用:
这里我们结合代码说明:
注:当前目录为空目录。
#include<stdio.h>
#include<sys/types.h>
#incldue<unistd.h>
int main()
{
FILE* fp=fopen("1.txt","w");
if(fp==NULL)
return 1;
fclose(fp);
return 0;
}
我们清楚的知道这段代码会在当前目录下创建一个1.txt的文件。
你觉得什么是当前目录呢?
当前目录全程:当前工作目录(缩写为cwd)
在进程创建时会记录当前目录cwd(即当前目录的路径),在使用1.txt相对路径创建文件时,系统会默认创建文件的路径是cwd/1.txt。这也就是为什么在我们使用相对路径创建文件时,这个文件会创建在cwd中。
默认情况下,进程启动所处的路径就是进程的当前路径。
使用系统调用接口chdir()修改cwd(当前工作目录)
在/home/wzy/test1目录中运行程序
注:/home/wzy/test2为空目录。
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
chdir("/home./wzy/test2");//把当前前目录修改为/home./wzy/test2
FILE* fp=fopen("1.txt","w");//在当前目录下创建1.txt文件
if(fp==NULL)
return 0;
fclose(fp);
return 0;
}
?
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!