口碑好的品牌网站建设,自己搭建app托管平台,wordpress call to un,怎样做影视网站环境#xff1a;centos7.6#xff0c;腾讯云服务器Linux文章都放在了专栏#xff1a;【Linux】欢迎支持订阅#x1f339;相关文章推荐#xff1a;【Linux】冯.诺依曼体系结构与操作系统进程概念什么是进程#xff1f;进程是什么#xff1f;我们打开任务管理器可以看到有…环境centos7.6腾讯云服务器Linux文章都放在了专栏【Linux】欢迎支持订阅相关文章推荐【Linux】冯.诺依曼体系结构与操作系统进程概念什么是进程进程是什么我们打开任务管理器可以看到有很多的程序正在运行状态并且上面写着进程二字。难道进程就是指这些被运行起来的程序吗课本上对于进程是这么说的程序的一个执行实例正在执行的程序等。windows下的进程但是实际上这种说法并不完全准确举个例子一个仅仅进入学校的人并不能算是这个学校的学生只有这个人的信息被加载到学校的教务系统并且被这个学校所管理的人才称得上学生。这里的学校就是指内存数据只有加载到内存并被OS所管理这才算是一个完整的进程。os管理进程在前文我们知道了cpu一般不会与外设进行直接沟通而是与内存打交道。所以我们在磁盘上的程序被运行时要将数据与代码加载到内存中。由操作系统来进行管理。具体怎么来管理呢先描述再组织。所谓的先描述实际上是指OS会用一个特定的结构体PCB/task_struct来提取该进程的各种属性这里的属性与加载到内存中的数据与代码无关或者说仅仅只有一点点的关系即可以通过对应的 task_struct找到该进程的代码和数据。组织是指OS会以链表或者其它的数据结构将各个task_struct组织起来方便管理。对进程的修改---对链表或者其它数据结构的增删查改比如我们结束一个进程实际上就是删掉数据结构中对应的pcb★上面啰嗦一大堆无非就是说两个事结论一进程os内核关于该进程的相关数据结构PCB/task_struct当前程序加载到内存的代码与数据。结论二OS如何管理进程先描述pcb/task_struct再组织(链表等数据结构)。PCB — 进程控制块进程需要被OS管理管理的本质就是先描述再组织。而PCB就是用来描述进程的一种特定结构体。在Linux系统下的PCB就是task_struct。task_struct内容分类task_struct结构体中主要包含了以下信息了解一下即可标示符: 描述本进程的唯一标示符用来区别其他进程。状态: 任务状态退出代码退出信号等。优先级: 相对于其他进程的优先级。程序计数器: 程序中即将被执行的下一条指令的地址。内存指针: 包括程序代码和进程相关数据的指针还有和其他进程共享的内存块的指针上下文数据: 进程执行时处理器的寄存器中的数据[休学例子要加图CPU寄存器]。IO状态信息: 包括显示的I/O请求,分配给进程的IO设备和被进程使用的文件列表。记账信息: 可能包括处理器时间总和使用的时钟数总和时间限制记账号等。其他信息如何查看进程第一种方法通过ps指令我们输入ps axj就可以查看当前所有进程信息同时由于进程信息较多我们可以利用之前学过的管道以及grep用来筛选过滤从而拿到我们想要的进程信息。如下第二种方法通过函数getpid在上面task_struct内容中有一个是标识符用来区分其他进程。这里的标识符实际就是指PID。每一个进程都有自己的pid并且每一次运行pid的值都会发生变化一般都是逐渐递增当下一次重新登陆时又是随机值。而我们可以通过系统调用函数getpid()来获取当前进程的pid。我们可以用man手册来查询getpid的使用。我们可以通过如下的简单代码来验证。#includestdio.h
//头文件包含
#includeunistd.h
#includesys/types.h
int main()
{while(1){//获取当前进程pidprintf(hello world,我的pid:%d\n,getpid()); sleep(1); } return 0; } 第三种方法在路径/proc下查看事实上我们在执行一个程序时会在/proc目录下生成一个以当前程序的pid命名的目录文件该目录文件内包含了当前进程的所有信息。并且还有一个特点当该程序停止运行时以pid命名的文件会自动销毁。如何中止进程★三种方法我们可以通过指令kill -9进程pid来中止进程通过热键ctrl c来中止当前进程通过指令killall 进程名称 来中止进程三种方式终止进程父子进程PPID进程之间存在父子关系我们知道bash是命令行解释器当我们在命令行输入指令执行一个进程时我们执行的进程就是bash的子进程。究竟是否如我们所说我们可以验证一下当然在此之前我们要先谈一下PPIDPPID就是当前进程的父进程的pid。fork创建子进程我们也可以通过系统调用函数fork用来给当前进程创建子进程。我们用man手册查询fork的用法。我们可以通过如下代码来进行简单测试#includestdio.h
#includeassert.h
#includeunistd.h
int main()
{//我们用ret来接受fork的返回值pid_t retfork();assert(ret!-1);//断言一下//我们通常使用if语句用来进行执行流分流if(ret 0) { while(1){ //此时是子进程,fork给子进程返回0printf(我是子进程pid:%d,ppid:%d,ret:%d,ret:%p\n,getpid(),getppid(),ret,ret); sleep(1); } } else if(ret 0){ while(1){ //此时是父进程fork给父进程返回子进程的pidprintf(我是父进程pid:%d,ppid:%d,ret:%d,ret:%p\n,getpid(),getppid(),ret,ret);sleep(1); } }return 0;}
运行结果我们发现确实如此不过这里有一个疑问为什么ret的地址相同但是ret的值却不相同呢我们从未见过这种现象同一个变量竟然有两个返回值。这是为什么呢?实际上我们在函数的最后有一个return 0而fork之后的代码是父子进程共享的也就是说return这个语句被执行了两次并且当return执行时函数体内部是已经执行完了的。所以会有两个返回值。为了验证fork之后的代码被父子进程共享我们可以写一个简简单单的代码用来测试一下#includestdio.h
#includeunistd.hint main(){int ret fork();//这里只有一个printfprintf(hello proc,pid:%d,ppid:%d,ret:%d\n, getpid(),getppid(),ret); sleep(1);return 0;}
运行结果我们发现确实如此。不仅如此进程还具有独立性我们可以定义一个全局变量父进程对全局变量进行修改我们发现不会影响到子进程中的那个全局变量。我们也可以进行验证#includestdio.h
#includeunistd.h
//定义全局变量
int a100;
int main(){pid_t retfork();if(ret 0){while(1){//子进程不对a做修改printf(我是子进程a%d,a:%p\n,a,a);sleep(1);}}else {while(1){//父进程,对全局变量a进行修改 a100;//假如进程不具有独立性那么父进程的修改也会影响子进程究竟会不会呢printf(我是父进程a%d,a:%p\n,a,a);sleep(1);}}return 0;}结果我们发现确实如此不过为什么同一个地址对内容进行修改却不会互相影响呢实际上这里的地址并不是真正的物理地址并且当进程尝试对数据进行修改时还会触发写时拷贝。具体放在后面进程地址空间章节详细讲解。总结★上面写了这么多总结如下命令行启动的程序都会变成bash的子进程我们可以通过fork为当前进程创建子进程fork的返回值给子进程返回0给父进程返回子进程的pid创建进程失败时返回-1fork之后的代码被父子进程共享但是谁先运行不确定进程具有独立性父子进程也是如此对其中一个进程的修改不会影响另一个进程独立性体现在两方面1、代码方面是可读的 2、数据方面当一个执行流尝试修改数据时OS会给我们的进程触发写时拷贝后面章节详细讲解。end.生活原本沉闷但跑起来就会有风