linux中进程相关概念(一)

什么是程序,什么是进程,有什么区别?

程序是静态的概念,当我们使用gcc xxx.c -o pro进行编译时,产生的pro文件,就是一个程序。
进程是程序的一次运行活动,通俗点就是说程序跑起来了就是进程。

如何查看系统中有哪些进程?

1.使用ps指令查看
实际工作中,配合grep来查找程序中是否存在某一个进程

ps -aux	//来查看整个系统中的进程
//但是在实际工作过程中,往往我们只需要查看某个进程的运行情况,此时可以用grep关键字
//比如我们需要查找init进程,通过grep过滤即可
ps -aux|grep init

2.使用top指令查看,类似windows任务管理器
在这里插入图片描述

什么是进程标识符?

每个进程都有一个非负整数表示唯一的id,叫做pid,类似身份证
pid=0;称为交换进程,作用是进程调度
pid=1;称为init进程,作用是系统初始化

getpid

可以通过getpid获取进程的pid号
#include <sys/types.h>
#include <unistd.h>

pid_t getpid(void);

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main(){//pid_t getpid(void);pid_t pid;pid = getpid();printf("my pid is: %d\n",pid);while(1);return 0;
}

在这里插入图片描述
在这里插入图片描述

什么叫父进程,什么叫子进程?

进程A创建了进程B
那么A叫做父进程,B叫做子进程,父子进程是相对的概念,理解为人类中的父子关系

C程序的存储空间是如何分配的?

代码段(正文):if else 、swtich case等算法代码段。
初始化数据段:初始化过的数据。
非初始化数据段(bss段):未被初始化的数据。
堆:存放malloc的数据。
栈:函数递归调用返回地址,局部变量等数据。
命令行参数和环境变量:argc,argv等

编程创建进程

fork

#include <unistd.h>

pid_t fork(void);


#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main(){//pid_t getpid(void);pid_t pid;pid = getpid();fork();printf("my pid is: %d\n",pid);return 0;
}

运行这段代码,会发现返回两个pid
my pid is: 12296
my pid is: 12296
在fork之前有一个进程,通过fork创建了一个进程,我们可以理解为第一个进程printf了一次,第二个进程也printf了一次,因此会出现两个pid号。我们可以通过getpid的方法来找出新进程的pid:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main(){//pid_t getpid(void);pid_t pid;pid = getpid();fork();printf("my pid is: %d,current pid is:%d\n",pid,getpid());return 0;
}

运行结果:
my pid is: 12376,current pid is:12376
my pid is: 12376,current pid is:12377
第一行的两个pid都相等,代表了这是原先的进程,第二行打印出一个新的pid,说明这是我们新创建的进程。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main(){//pid_t getpid(void);pid_t pid;pid = getpid();fork();if(pid == getpid()){printf("this is father process,father pid is:%d\n",pid);}else{printf("this is son process,sun pid is:%d\n",getpid());}return 0;
}

运行结果:
this is father process,father pid is:12437
this is son process,sun pid is:12438
说明子进程和父进程都会执行这段代码,只不过两个进程会进入不同的分支。

研究fork的返回值

返回值为0说明为子进程
返回值大于0说明为父进程,并且值为子进程的pid号


#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main(){//pid_t getpid(void);pid_t pid;printf("current pid is:%d\n",getpid());pid = fork();if(pid > 0){printf("this is father process,father pid is:%d\n",getpid());}else if(pid == 0){printf("this is son process,sun pid is:%d\n",getpid());}return 0;
}

运行结果:
current pid is:12567
this is father process,father pid is:12567
this is son process,sun pid is:12568

fork时发生了什么事情

以前的版本,我们在fork之后会将原先的地址空间全部拷贝一份,而现在的版本我们采用写时拷贝,只有在我们在子进程中修改每一个参数的值的时候,才从父进程中拷贝一份这个数据到子进程地址空间去。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main(){//pid_t getpid(void);pid_t pid;int data = 10;printf("current pid is:%d\n",getpid());pid = fork();if(pid > 0){data+=10;printf("this is father process,father pid is:%d,data=%d\n",getpid(),data);}else if(pid == 0){printf("this is son process,sun pid is:%d,data=%d\n",getpid(),data);}return 0;
}

运行结果:
current pid is:12889
this is father process,father pid is:12889,data=20
this is son process,sun pid is:12890,data=10

创建子进程的目的

应用场景1. 创建子进程响应客户端请求

父进程自身作为一个服务器,当收到一个客户端发来的请求时,就fork一个子进程来响应这个请求。
我们可以用while循环来模拟一下这个过程:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main(){//pid_t getpid(void);pid_t pid;int data;while(1){printf("please input a data\n");scanf("%d",&data);if(data == 1){pid = fork();if(pid > 0){}else if(pid == 0){while(1){printf("do net request,pid=%d\n",getpid());sleep(3);}}}else{printf("wait,no request\n");}}return 0;
}

在这里插入图片描述
ps -aux|grep myPro
Warning: bad ps syntax, perhaps a bogus ‘-’? See http://procps.sf.net/faq.html
CLC 13052 0.0 0.0 4164 352 pts/2 S+ 22:09 0:00 ./myPro
CLC 13053 0.0 0.0 4164 96 pts/2 S+ 22:09 0:00 ./myPro
CLC 13054 0.0 0.0 4164 96 pts/2 S+ 22:09 0:00 ./myPro
CLC 13055 0.0 0.0 4164 96 pts/2 S+ 22:09 0:00 ./myPro
CLC 13058 0.0 0.0 13588 940 pts/3 S+ 22:10 0:00 grep --color=auto myPro
可以看到父进程为13052,而53,54,55都是我们创建的子进程来响应客户端的请求。

应用场景2. 一个进程要执行一个不同的程序

这对shell时常见的情况。在这种情况下,子进程从fork返回后立即调用exec,在后续会学习该方面知识。

fork总结

由fork创建的新进程被称为子进程。fork函数被调用一次,但返回两次。两个返回的唯一区别是子进程的返回值是0,而父进程的返回值则是新子进程的进程pid。将子进程id返回给父进程的理由是:因为一个进程的子进程可以有多个,并且没有一个函数使一个进程可以获得其所有子进程的pid。fork使子进程得到返回值0的理由是:一个进程只会有一个父进程,所以子进程总是可以调用getpid以获得其父进程的进程id。(进程id 0总是由内核交换进程使用,所以一个子进程的进程id不可能为0)。
子进程和父进程继续执行fork之后的指令。子进程获得父进程的数据空间、堆栈副本。注意,这是子进程所拥有的副本。父子进程并不共享这些存储空间部分,父子进程共享正文段(代码段)。
后来采用写时拷贝,只有修改一块的变量才会复制那一块到自己的内存空间中。

vfork

vfork与fork的区别:
①vfork直接使用父进程存储空间,不拷贝。
②vfork保证子进程先运行,当子进程调用exit推出后,父进程才执行。

例如:
普通的fork创建进程:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main(){//pid_t getpid(void);pid_t pid;pid = fork();if(pid > 0){while(1){printf("this is father process,father pid is:%d\n",getpid());sleep(1);}}else if(pid == 0){while(1){printf("this is son process,son pid is:%d\n",getpid());sleep(1);}}return 0;
}

运行结果:
this is father process,father pid is:13256
this is son process,son pid is:13257
this is son process,son pid is:13257
this is father process,father pid is:13256
this is father process,father pid is:13256
this is son process,son pid is:13257
this is father process,father pid is:13256
this is son process,son pid is:13257
父子进程都会运行。
当我们将fork改为vfork时:
运行结果:
this is son process,son pid is:13370
this is son process,son pid is:13370
this is son process,son pid is:13370
this is father process,father pid is:13369
this is father process,father pid is:13369
this is father process,father pid is:13369
this is father process,father pid is:13369
this is father process,father pid is:13369
this is father process,father pid is:13369
先运行子进程,当子进程exit后,才运行父进程。并且子进程直接使用父进程的存储空间,不拷贝,比如我们创建一个cnt,在子进程中对cnt进行累加,当cnt为3时,我们退出进程,此时在父进程中输出cnt的值为3。

进程退出

正常退出

1.main函数调用return
2.进程调用exit(),标准C库
3.进程调用_exit()或者_Exit(),属于系统调用
4.进程最后一个线程返回
5.最后一个线程调用pthread_exit

异常退出

1.调用abort
2.当进程收到某些信号时,如ctrl+C
3.最后一个线程取消(cancellation)请求做出响应

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/9252.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

利用智能私信软件,快速拓展潜在客户群体

在数字化营销的浪潮中&#xff0c;企业如何快速而有效地触及并吸引潜在客户&#xff0c;已成为一个不可忽视的挑战。随着人工智能技术的不断进步&#xff0c;智能私信软件作为一种新型工具&#xff0c;正逐渐改变着企业的市场拓展方式。本文将探讨如何通过这类软件&#xff0c;…

RBAC 权限设计(五)

序言 本文介绍 RBAC2 模型以及具体的实现方案。本文仅提供实现思路供大家参考&#xff0c;在生产实践中请根据业务场景进行具体设计。 一、RBAC2 模型 RBAC2 是 RBAC&#xff08;基于角色的访问控制&#xff09;模型中的一种&#xff0c;它在 RBAC0 的基础上&#xff0c;对用…

GitHub中Asterank源码python修改成C++(本人python不太会)

GitHub - typpo/asterank: asteroid database, interactive visualizations, and discovery tools 主要目的是在进行多元线性回归的时候将枚举型转换为数值型 python: # # The constants used in calculations for the values of asteroids. ## General constants GENERAL_I…

学习torchmd分子动力学模拟

TorchMD打算提供一种简单易用的API&#xff0c;用于使用PyTorch进行分子动力学。这使研究人员能够更快地进行力场开发研究&#xff0c;并以PyTorch的简单性和强大性将神经网络潜力无缝集成到动力学中。 TorchMD使用与经典MD代码&#xff08;如ACEMD&#xff09;一致的化学单位&…

引入OSS

前置条件 AccessKey 引入依赖 都是官网上的&#xff1a;https://help.aliyun.com/zh/oss/developer-reference/java-installation?spma2c4g.11186623.0.i16 <!--若是创建项目的时候这个依赖勾选了就不用了--><!--不加启动会报错No active profile set, falling back…

JavaScript之数据类型(2)——复杂类型(object)

object的介绍&#xff1a; 我对于object的理解是和C/C中的结构体一样&#xff0c;是一个自定义的数据类型&#xff0c;我们可以通过多个简单的数据类型来定义一个便于我们使用的新的数据类型。 在网上某佬对于其解释如下&#xff1a; Object类型&#xff0c;我们也称为一个对象…

Windows命令行一键安装、配置WSL的方法

本文介绍在Windows电脑中&#xff0c;通过命令行的方式&#xff0c;快速、方便安装适用于Linux的Windows子系统&#xff08;Windows Subsystem for Linux&#xff0c;WSL&#xff09;的方法。 WSL是由微软开发的一项功能&#xff0c;允许在Windows操作系统上运行Linux发行版系统…

【Linux的文件篇章 - 磁盘文件】

Linux学习笔记---012 Linux之进程程序替换理解1、磁盘文件1.1、文件如何存取的问题1.2、了解磁盘的存储结构1.3、如何找到指定位置的扇区&#xff1f;1.4、对磁盘的存储进行逻辑抽象(了解OS对磁盘这样的硬件设备的抽象与管理) 2、磁盘级文件系统2.1、Linux文件系统特定2.2、文件…

Ansible--Templates 模块 Tags模块 Roles模块

一 Templates 模块 ①Jinja是基于Python的模板引擎。Template类是Jinja的一个重要组件&#xff0c;可看作一个编译过的模 板文件&#xff0c;用来产生目标文本&#xff0c;传递Python的变量给模板去替换模板中的标记。 ②在配置文件中&#xff0c;会有一些数据&#xff08;如…

Java毕设之基于SpringBoot的在线拍卖系统

运行环境 开发语言:java 框架:springboot&#xff0c;vue JDK版本:JDK1.8 数据库:mysql5.7(推荐5.7&#xff0c;8.0也可以) 数据库工具:Navicat11 开发软件:idea/eclipse(推荐idea) 系统详细设计 管理员功能模块 管理员登录&#xff0c;管理员通过输入用户名、密码、角色等信…

UE4_Water插件_Buoyancy组件使用

water插件提供了一个浮力Actor蓝图类。 需要注意的几个问题&#xff1a; 1、StaticMesh需要替换根组件。 2、需要模拟物理设置质量。 3、需要添加浮力组件&#xff0c;设置浮力点&#xff0c;应用水中牵引力。 4、最重要的是需要激活——自动启用。 5、调水波长的地方 双击图片…

FreeRTOS学习 -- 任务相关API函数

一、任务创建和删除API函数 FreeRTOS 最基本的功能就是任务管理&#xff0c;而任务管理最基本的操作就是创建和删除任务。 FreeRTOS的任务创建和删除API函数如下&#xff1a; 1、函数 xTaskCreate() 此函数用来创建一个任务&#xff0c;任务需要 RAM 来保存于任务有关的状…

前端js面试题--从字符串中删除删除注释代码

问题&#xff1a;从字符串中删除删除注释代码 描述&#xff1a; solution(weex,rex # and react\nflutter\nnative ssss !hybrid app, [#, !]) 写一个solution函数清除后面参数数组里面的字符串 打印效果 代码1 思路&#xff1a; 将字符全凡是有去掉标志符号的全部添加\n…

Java_File

介绍&#xff1a; File对象表示路径&#xff0c;可以是文件&#xff0c;也可以是文件夹。这个路径可以是存在的&#xff0c;也可以是不存在的&#xff0c;带盘符的路径是绝对路径&#xff0c;不带盘符的路径是相对路径&#xff0c;相对路径默认到当前项目下去找 构造方法&…

基于SSM的校园短期闲置资源置换平台(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的校园短期闲置资源置换平台&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过…

燃气电力瓶装气行业入户安检小程序开发

我们开发的小区业主入户安检小程序&#xff0c;旨在满足燃气、电力以及其他需要入户安检的行业需求。该程序支持自定义安检项目&#xff0c;实现线下实地安检与线上数据保存的完美结合。在安检过程中&#xff0c;我们可以拍照或录像&#xff0c;以确保安检的透明性和可追溯性&a…

渲染管线中光照的计算

文章目录 渲染管线中光照的计算前言法向量朗伯余弦定律漫反射环境光照镜面光照菲涅尔效应 表面粗糙度光照模型平行光源点光源衰减 聚光灯 渲染管线中光照的计算 前言 首先我们来看一下同一个模型在有光与无光下的区别&#xff1a; 无光&#xff1a; 有光 很明显的感知就是…

加速科技突破2.7G高速数据接口测试技术

随着显示面板分辨率的不断提升&#xff0c;显示驱动芯片&#xff08;DDIC&#xff09;的数据接口传输速率越来越高&#xff0c;MIPI、LVDS/mLVDS、HDMI等高速数据接口在DDIC上广泛应用。为满足高速数据接口的ATE测试需求&#xff0c;作为国内少数拥有完全自研的LCD Driver测试解…

WebSocket 来单提醒和客户催单功能

一&#xff1a;WebSocket &#xff1a; WebSocket 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手&#xff0c;两者之间就可以创建持久性的连接&#xff0c; 并进行双向数据传输。 HTTP协议和WebSocket协议对比&#…

vue 代码样式问题

部分电脑存在样式错乱问题&#xff0c;部分电脑样式正常。最后发现是样式写在 el-col 里面导致的。 注意&#xff1a;写样式不要放在 el-row 或者 el-row &#xff0c;导致部分电脑会出现莫名其妙的样式问题 <el-row class"detail"><el-col class"it…