linux中进程相关概念(一)

news2024/12/25 12:41:58

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

程序是静态的概念,当我们使用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.coloradmin.cn/o/1657409.html

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

相关文章

docker学习笔记(四)制作镜像

目录 第1步&#xff1a;编辑Dockerfile 第2步&#xff1a;编辑requirements.txt文件 第3步&#xff1a;编辑app.py文件&#xff0c;我们的程序文件 第4步&#xff1a;生成镜像文件 第5步&#xff1a;使用镜像&#xff0c;启动容器 第6步&#xff1a; 启动redis容器、将容器…

PLC数据采集网关的功能和特点-天拓四方

一、引言 随着工业自动化程度的不断提高&#xff0c;数据在生产线上的作用愈发重要。PLC作为工业自动化的核心设备&#xff0c;其数据采集和处理能力直接影响到整个生产线的效率和稳定性。而PLC数据采集网关&#xff0c;作为连接PLC与外部系统的桥梁&#xff0c;正日益受到人们…

我的Transformer专栏来啦

五一节前吹的牛&#xff0c;五一期间没完成&#xff0c;今天忙里偷闲&#xff0c;给完成了。 那就是初步拟定了一个《Transformer最后一公里》的写作大纲。 之前一直想写一系列Transformer架构的算法解析文章&#xff0c;但因为一直在忙&#xff08;虽然不知道在忙啥&#xf…

YOLOv8 Tensorrt Python/C++部署详解

按照大佬的方法进行部署&#xff0c;但是中间出现了很多问题&#xff0c;这里进行一下总结。 YOLOv8 Tensorrt Python/C部署教程_yolo 安装tensorrt-CSDN博客https://blog.csdn.net/weixin_45747759/article/details/130341118 Monday-Leo/Yolov5_Tensorrt_Win10: A simple i…

即插即用 | YOLOv8热力图可视化方法详解,揭秘AI如何「看」世界!【附完整源码】

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

TypeScript学习日志-第十七天(泛型约束)

泛型约束 当我们使用泛型时非常方便&#xff0c;但是在使用的过程中也会遇到很多问题&#xff0c;如图&#xff1a; 这时候就会提示错误&#xff0c;因为返回的是相加的值&#xff0c;但是不是所有的类型都能相加的&#xff0c;例如来个undefined类型的 就不能进行相加了&…

锂电池恒流恒压CCCV充电模型MATLAB仿真

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; CCCV简介 CCCV充电过程是恒流充电&#xff08;CC&#xff09;和恒压充电&#xff08;CV&#xff09;的结合。在CC阶段对电池施加恒定电流&#xff0c;以获得更快的充电速度&#xff0c;此时电池电压持续升高…

docker安装Debian:11 freeswitch1.10.5

文章目录 一、生成一个镜像二、切换一个镜像源为阿里源三、安装一些相关依赖和freeswitch3.1第一步&#xff1a;安装freeswitch-mod和下载所需的依赖项3.2 设置密钥3.3 安装freeswitch所需的依赖项3.4 报错3.4.1 报错13.4.2 报错23.4.3 报错3 四、运行4.1 通话三十秒自动挂断 一…

Hotcoin Research | 模块化将是大势所趋:拆解模块化区块链的现状和未来

关于模块化区块链叙事的讨论源于Celestia和其代币TIA的亮眼表现。实际上&#xff0c;模块化是未来区块链设计的主要发展方向和大势所趋。模块化区块链就像乐高积木一样&#xff0c;将区块链系统拆分为可重用的模块&#xff0c;通过定制组合可实现不同功能的区块链网络。这种灵活…

【半个月我拿下了软考证】软件设计师高频考点--系统化教学-网络安全

&#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;软件设计师考点暴击 ⭐&#x1f170;️进入狂砍分⭐ ⭐软件设计师高频考点文档&#xff0c; ⭐软件设计师高频考点专栏 ⭐软件设计师高频考点⭐ &#x1f3b6;&#xff08;A) 考点1&#xff0c;网络攻击 理解记忆 &#…

融知财经:期货在哪里可以交易?期货交易有哪些交易规则?

作为当前金融市场的一种投资方式&#xff0c;期货只适合一些投资者&#xff0c;比如想获得高收益的投资者&#xff0c;因为期货的风险系数很高。但是很多投资者还不知道期货的意思&#xff0c;在一个固定的交易场所&#xff0c;期货是买卖标准化商品或金融资产的远期合约的交易…

软件1班20240509

文章目录 1.JDBC本质2.增3.改4.删5.查6.JDBC标准写法 1.JDBC本质 重写 接口的 方法 idea 报错 – 不动脑 alt enter 知道没有重写方法 CTRL o 重写 方法 快捷键 package com.yanyu;/*** Author yanyu666_508200729qq.com* Date 2024/5/9 14:42* description:*/ public interf…

使用QLoRA在自定义数据集上finetuning 大模型 LLAMA3 的数据比对分析

概述: 大型语言模型(LLM)展示了先进的功能和复杂的解决方案,使自然语言处理领域发生了革命性的变化。这些模型经过广泛的文本数据集训练,在文本生成、翻译、摘要和问答等任务中表现出色。尽管LLM具有强大的功能,但它可能并不总是与特定的任务或领域保持一致。 什么是LL…

oracle 数据库找到UDUMP的文件名称

oracle 数据库找到UDUMP的文件名称 select p.value||\||i.instance_name||_ora_||spid||.trc as "trace_file_name" from v$parameter p ,v$process pro, v$session s, (select sid from v$mystat where rownum1) m, v$instance i where lower(p.name)user_dump_…

红米Turbo3小米平板6SPro澎湃OS系统强解BL锁-跳小米社区绑定-刷ROOT权限

红米Turbo3小米平板6SPro这2款设备都出厂为澎湃OS系统&#xff0c;官方提供都是小米社区申请解锁权限&#xff0c;然后自己答题解锁&#xff0c;门槛非常高&#xff0c;想要玩机root的用户&#xff0c;都在堵在门外。还在这目前这两款机型官方并没有加入强制验证&#xff0c;在…

Python turtle绘制图形详解

Python 的 Turtle 模块是一个简单而直观的绘图工具&#xff0c;可以帮助初学者理解基本的图形绘制概念。 1.导入 Turtle 模块&#xff1a; import turtle 2.创建 Turtle 对象&#xff1a; t turtle.Turtle() 3.绘制图形&#xff1a; 4.移动Turtle对象&#xff1a;t.forward(di…

基于Spring Boot的酒店管理系统设计与实现

基于Spring Boot的酒店管理系统设计与实现 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 系统首页界面图&#xff0c;在系统首页可以查看首页…

pgsql查看指定模式的存储过程

pgsql查看指定模式的存储过程 在 PostgreSQL 中&#xff0c;如果你想要查看指定模式的存储过程&#xff08;也称为函数&#xff09;&#xff0c;你可以使用 \df 或 \df 命令在 psql 命令行工具中&#xff0c;或者使用 SQL 查询来从 pg_catalog 系统模式中查询。 \df命令行查询…

容器集群管理系统Kubernetes(K8S)

目录 一、前言 1.1什么是云原生&#xff1f; 1.2云要素的四要素&#xff1f; 1.2.1微服务 1.2.2容器化 1.2.3DevOps 1.2.4持续交付 1.3云平台有哪些&#xff1f; 1.4SRE 二、Kubernetes 概述 2.1K8S 是什么 2.2K8S作用 2.3K8S版本 2.4为什么要用 K8S 2.5K8S 的特…

从零开始打造个性化生鲜微信商城小程序

随着移动互联网的普及&#xff0c;小程序商城已经成为越来越多商家的选择。本文将通过实战案例分享&#xff0c;教您如何在五分钟内快速搭建个性化生鲜小程序商城。 步骤一&#xff1a;登录乔拓云网后台&#xff0c;进入商城管理页面 打开乔拓云官网&#xff0c;点击右上角的“…