【进程篇】03.进程的概念与基本操作

一、进程的概念与理解

1.1 概念

进程是程序的一个执行实例,即正在执行的程序。

1.2 理解

我们编写代码运行后会在磁盘中会形成一个可执行程序,当我们运行这个可执行程序时,这个程序此时就会被操作系统的调度器加载到内存中;操作系统会对进程进行管理(进程的加载、调度、切换、释放……),而我们可能同时启动多个进程(一面听歌一面看PPT),那么操作系统是如何管理进程的呢?

很简单,先描述,后组织,即我们的操作系统对进程的属性进行管理,创建了内核级的数据结构PCB(Linux中的PCB是task_struct)来管理进程。因此实际上进程=内核数据结构(task_struct)+代码和数据。接下来这些task_struct彼此相连构成了struct task_struct* list,而后操作系统就可以对多个进程基于时间片进行轮转调度、切换等等。在这一过程中呈现了动态的特征,因此我们有了如上的结论:进程是运行起来的程序

1.3 源码中对task_struct的描述 

下面是来自Linux0.11版本的源码中对task_struct的描述:

struct task_struct {
/* these are hardcoded - don't touch */long state;	/* -1 unrunnable, 0 runnable, >0 stopped */long counter;long priority;long signal;struct sigaction sigaction[32];long blocked;	/* bitmap of masked signals */
/* various fields */int exit_code;unsigned long start_code,end_code,end_data,brk,start_stack;long pid,father,pgrp,session,leader;unsigned short uid,euid,suid;unsigned short gid,egid,sgid;long alarm;long utime,stime,cutime,cstime,start_time;unsigned short used_math;
/* file system info */int tty;		/* -1 if no tty, so it must be signed */unsigned short umask;struct m_inode * pwd;struct m_inode * root;struct m_inode * executable;unsigned long close_on_exec;struct file * filp[NR_OPEN];
/* ldt for this task 0 - zero 1 - cs 2 - ds&ss */struct desc_struct ldt[3];
/* tss for this task */struct tss_struct tss;
};

二、进程的基本操作

查看进程信息的指令:ps axj

2.1 查看PID

PID是用以区分进程唯一性的编号,我们可以使用系统接口getpid来获取当前进程的pid。

#include<stdio.h>     
#include<sys/types.h> 
#include<unistd.h>      
int main()      
{      while(1)      {      printf("I am a process,My Pid is %d\n",getpid());      sleep(1);      }  return 0;  
}     

终止该进程的方式:1. Crtl+C可以结束进程      2.发送信号 kill -9 5150也可以杀死该进程

仅仅通过ps axj显示的进程信息是有些少的,进程的信息被保存在/proc中,以自己的PID为文件名,因此我们也可以通过查看/proc/PID来查看进程的信息

[caryon@VM-24-10-centos ~]$ ll /proc/9139
total 0
dr-xr-xr-x 2 caryon caryon 0 Oct  9 15:47 attr
-rw-r--r-- 1 caryon caryon 0 Oct  9 15:47 autogroup
-r-------- 1 caryon caryon 0 Oct  9 15:47 auxv
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 cgroup
--w------- 1 caryon caryon 0 Oct  9 15:47 clear_refs
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 cmdline
-rw-r--r-- 1 caryon caryon 0 Oct  9 15:47 comm
-rw-r--r-- 1 caryon caryon 0 Oct  9 15:47 coredump_filter
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 cpuset
lrwxrwxrwx 1 caryon caryon 0 Oct  9 15:47 cwd -> /home/caryon/linux/lesson11
-r-------- 1 caryon caryon 0 Oct  9 15:47 environ
lrwxrwxrwx 1 caryon caryon 0 Oct  9 15:47 exe -> /home/caryon/linux/lesson11/code
dr-x------ 2 caryon caryon 0 Oct  9 15:47 fd
dr-x------ 2 caryon caryon 0 Oct  9 15:47 fdinfo
-rw-r--r-- 1 caryon caryon 0 Oct  9 15:47 gid_map
-r-------- 1 caryon caryon 0 Oct  9 15:47 io
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 limits
-rw-r--r-- 1 caryon caryon 0 Oct  9 15:47 loginuid
dr-x------ 2 caryon caryon 0 Oct  9 15:47 map_files
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 maps
-rw------- 1 caryon caryon 0 Oct  9 15:47 mem
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 mountinfo
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 mounts
-r-------- 1 caryon caryon 0 Oct  9 15:47 mountstats
dr-xr-xr-x 5 caryon caryon 0 Oct  9 15:47 net
dr-x--x--x 2 caryon caryon 0 Oct  9 15:47 ns
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 numa_maps
-rw-r--r-- 1 caryon caryon 0 Oct  9 15:47 oom_adj
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 oom_score
-rw-r--r-- 1 caryon caryon 0 Oct  9 15:47 oom_score_adj
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 pagemap
-r-------- 1 caryon caryon 0 Oct  9 15:47 patch_state
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 personality
-rw-r--r-- 1 caryon caryon 0 Oct  9 15:47 projid_map
lrwxrwxrwx 1 caryon caryon 0 Oct  9 15:47 root -> /
-rw-r--r-- 1 caryon caryon 0 Oct  9 15:47 sched
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 schedstat
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 sessionid
-rw-r--r-- 1 caryon caryon 0 Oct  9 15:47 setgroups
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 smaps
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 stack
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 stat
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 statm
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 status
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 syscall
dr-xr-xr-x 3 caryon caryon 0 Oct  9 15:47 task
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 timers
-rw-r--r-- 1 caryon caryon 0 Oct  9 15:47 uid_map
-r--r--r-- 1 caryon caryon 0 Oct  9 15:47 wchan

认识cwd和exe

• exe
我们可以尝试一下将进程启动然后删掉可执行程序,我们发现进程依然是可以运行的,但是一旦退出了进程就不能再运行了,但是进程结束后我们发现exe报红了,这就是由于exe存储了我们的形成该进程的原文件。

 cwd
我们之前总是听到这么一句话“当我们打开一个不存在的文件时会在当前目录下创建这个文件”,为什么会在当前目录下新建这个文件?又是怎么新建的呢?
当一个进程在实际启动的时候,该进程会用cwd记录当前工作目录,新建文件就是把cwd拿过来在后面加上/文件名,这也就意味着我们如果能改变进程启动的cwd即可对新建文件的创建位置进行控制,而系统给我们提供了这样的接口chdir()

#include<stdio.h>
#include<unistd.h>
int main()
{chdir("/home/caryon");FILE* fp=fopen("log.txt","w");if(fp==NULL){}return 0;
}

/proc是系统为我们提供的一个访问进程信息的接口,因此实际上的ps就是对/proc进行相关的文本分析,而/proc也并不是磁盘级文件,因此频繁的创建于删除并不影响效率。

2.2 查看PPID

在Linux中,OS启动之后,新建的任何进程都是由自己的父进程创建的,我们可以使用系统调用接口getppid()获取当前进程的ppid。

#include<stdio.h>    
#include<unistd.h>    
int main()    
{    while(1)    {    printf("PID:%d,PPID:%d\n",getpid(),getppid());                                sleep(1);    }    return 0;    
}    

 

 我们反复执行了几次代码,发现该进程的PPID居然没有变,它的父进程究竟是谁啊?

[caryon@VM-24-10-centos ~]$ ps ajx|head -1;ps ajx|grep 31222PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
31222 28570 28570 31222 pts/0    28570 S+    1001   0:00 ./code
31220 31222 31222 31222 pts/0    28570 Ss    1001   0:00 -bash7482 31749 31748  7482 pts/1    31748 S+    1001   0:00 grep --color=auto 31222

原来是bash(Linux下的命令行解释器)。命令行中,执行命令/程序本质上就是bash创建子进程,由子进程执行我们的代码。

创建子进程
系统接口提供了fork()来创建子进程,如果创建成功则给父进程返回子进程的PID,给子进程返回0,失败则给父进程返回-1,子进程创建失败。

#include<stdio.h>
#include<unistd.h>int gal=0;int main()
{printf("我的PID是%d,我的PPID是%d\n",getpid(),getppid());pid_t id=fork();if(id==0){while(1){printf("我是子进程,我的PID是%d,我的PPID是%d,gal=%d\n",getpid(),getppid(),gal);sleep(1);gal++;}}else{while(1){printf("我是父进程,我的PID是%d,我的PPID是%d,gal=%d\n",getpid(),getppid(),gal);sleep(1);}}return 0;
}
[caryon@VM-24-10-centos lesson11]$ ./code
我的PID是13111,我的PPID是31222
我是父进程,我的PID是13111,我的PPID是31222,gal=0
我是子进程,我的PID是13112,我的PPID是13111,gal=0
我是父进程,我的PID是13111,我的PPID是31222,gal=0
我是子进程,我的PID是13112,我的PPID是13111,gal=1
我是父进程,我的PID是13111,我的PPID是31222,gal=0
我是子进程,我的PID是13112,我的PPID是13111,gal=2
我是父进程,我的PID是13111,我的PPID是31222,gal=0
我是子进程,我的PID是13112,我的PPID是13111,gal=3
我是父进程,我的PID是13111,我的PPID是31222,gal=0
我是子进程,我的PID是13112,我的PPID是13111,gal=4

对于同一个父进程可以创建多个子进程,对于每一个子进程只能有一个父进程,故进程也是树形结构。

理解fork函数

fork()函数一旦调用之后,后面就会有两个进程了,这两个进程各自执行各自的代码,只不过fork()给父进程返回的是子进程的PID,给子进程则返回0。对于父子进程,它们的关系是代码共享,数据私有一份

为什么代码是共享的呢?

我们知道进程=内核数据结构(task_struct)+代码和数据。fork之后产生子进程,子进程的内核数据结构拷贝自父进程,但是没有代码和数据怎么办呢?系统就会让子进程的内核数据结构指向父进程的代码和数据。

为什么数据是私有一份的呢?

上面我们不是说子进程的内核数据结构指向父进程的代码和数据吗?这是因为进程具有很强的独立性,多个进程运行时互不干扰(即使是父子)。代码是只读的,可以共享;但是数据不一定时只读的,当数据被修改时两个进程必须要进行分割,也就是各自要私有一份。

#include<stdio.h>
#include<unistd.h>int gal=0;
int main()
{pid_t id=fork();if(id==0){while(1){printf("I am a subprocess,my pid is %d,my ppid is %d,gal = %d\n",getpid(),getppid(),gal++);sleep(1);}}else{while(1){printf("I am a parentprocess,my pid is %d,my ppid is %d,gal = %d\n",getpid(),getppid(),gal);sleep(1);}}return 0;
}

上面的这段代码我们可以看到全局变量gal在两个进程中的数值是不相同的,也就是进程间实现了数据私有一份的。

这时我们也能理解了fork的返回值了。因为id也是变量,返回的本质就是向指定变量进行写入,因此两个进程的id是不相同的。

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

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

相关文章

基于MATLAB 的数字图像处理技术总结

大家好&#xff01;欢迎来到本次的总结性的一篇文章&#xff0c;因为咸鱼哥这几个月是真的有点小忙&#xff08;参加了点小比赛&#xff0c;准备考试等等&#xff09;所以&#xff0c;在数字图像学习后&#xff0c;我来写一个总结性的文章&#xff0c;同时帮助大家学习&#xf…

llama2——微调lora,第一次参考教程实践完成包括训练和模型

前言&#xff1a;磕磕绊绊&#xff0c;不过收获很多&#xff0c;最大的收获就是解决报错error的分析方法和解决思路 1、首先&#xff0c;我参考的是这篇博客&#xff1a;怎样训练一个自己的大语言模型&#xff1f;全网最简单易懂的教程&#xff01;_开源模型训练出一个语言模型…

类OCSP靶场-Kioptrix系列-Kioptrix Level 3

一、前情提要 二、实战打靶 1. 信息收集 1.1. 主机发现 1.2. 端口扫描 1.3.目录遍历 1.4. 敏感信息 2.漏洞发现 2.1.登录功能账号密码爆破 2.2.CMS历史漏洞 2.2.1.exp利用 2.2.2.提权 2.3. sql注入getshell 2.3.1.发现注入点 2.3.2. 测试字段和类型 2.3.3.查询字…

WPF实现曲线数据展示【案例:震动数据分析】

wpf实现曲线数据展示&#xff0c;函数曲线展示&#xff0c;实例&#xff1a;震动数据分析为例。 如上图所示&#xff0c;如果你想实现上图中的效果&#xff0c;请详细参考我的内容&#xff0c;创作不易&#xff0c;给个赞吧。 一共有两种方式来实现&#xff0c;一种是使用第三…

PHP代码审计学习(一)--命令注入

1、漏洞原理 参数用户可控&#xff0c;程序将用户可控的恶意参数通过php可执行命令的函数中运行导致。 2、示例代码 <?php echorec-test; $command ping -c 1 .$_GET[ip]; system($command); //system函数特性 执行结果会自动打印 ?> 通过示例代码可知通过system函…

Vivado安装System Generator不支持新版Matlab解决方法

目录 前言&#xff1a; Vivado安装System Generator不支持新版Matlab解决方法 前言&#xff1a; 本文介绍一下Vivado不支持新版Matlab的解决办法&#xff0c;Vivado只支持最近两年3个版本的Matlab&#xff0c;当前最新版vivado 2018.3只支持2017a,2017b,2018a。 Vivado安装Sy…

半导体数据分析(二):徒手玩转STDF格式文件 -- 码农切入半导体系列

一、概述 在上一篇文章中&#xff0c;我们一起学习了STDF格式的文件&#xff0c;知道了这是半导体测试数据的标准格式文件。也解释了为什么码农掌握了STDF文件之后&#xff0c;好比掌握了切入半导体行业的金钥匙。 从今天开始&#xff0c;我们一起来一步步地学习如何解构、熟…

#渗透测试#漏洞挖掘#红蓝攻防#SRC漏洞挖掘02之权限漏洞挖掘技巧

免责声明 本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停止本文章读。 权限相关漏洞 越权、未授权访问、oss、后台暴露、…

IS-IS协议

IS-IS协议介绍 IS-IS&#xff08;Intermediate System to Intermediate System&#xff09;协议是一种链路状态的内部网关协议&#xff08;IGP&#xff09;&#xff0c;用于在同一个自治系统&#xff08;Autonomous System, AS&#xff09;内部的路由器之间交换路由信息。IS-I…

4.7 TCP 的流量控制

欢迎大家订阅【计算机网络】学习专栏&#xff0c;开启你的计算机网络学习之旅&#xff01; 文章目录 前言1 滑动窗口与流量控制2 持续计时器与零窗口探测3 控制TCP发送报文段的时机3.1 控制发送时机的三种机制3.2 糊涂窗口综合症 前言 在网络通信中&#xff0c;流量控制是确保…

不良人系列-复兴数据结构(栈和队列)

个人主页&#xff1a;爱编程的小新☆ 不良人经典语录&#xff1a;“相呴相济 玉汝于成 勿念 心安” 目录 一. 栈(stack) 1. 栈的概念 2. 栈的常见方法 3.栈的模拟实现 ​编辑 二. 队列 1. 队列的概念 2. 队列的使用 2.1 队列的常见方法 2.2 队列的模拟实现 2.3 队列…

在clion中使用MySQL的教程

首先就是配置好东西&#xff0c;也是非常简单的&#xff1a; 1.把mysql安装目录&#xff08;其中的lib好像&#xff09;中的2个文件复制到下面就行 2.然后配置&#xff0c;这个文件 cmake_minimum_required(VERSION 3.24) project(2024_12project)include_directories(D:\\mys…

某名校考研自命题C++程序设计——近10年真题汇总(下)

第二期&#xff0c;相比上一贴本帖的题目难度更高一些&#xff0c;我当然不会告诉你我先挑简单的写~ 某名校考研自命题C程序设计——近10年真题汇总&#xff08;上&#xff09;-CSDN博客文章浏览阅读651次&#xff0c;点赞9次&#xff0c;收藏13次。本帖更新一些某校的编程真题…

探讨不同类型的自动化测试框架

以下为作者观点&#xff1a; 在自动化测试中&#xff0c;框架提供了一种组织和执行测试案例的结构化方式。它们提供了一套准则和最佳实践&#xff0c;使测试人员能够编写可重复使用、可维护和可扩展的测试脚本。在这篇文章中&#xff0c;我们将讨论自动化测试中不同类型的框架…

C# 网络编程--关于Socket编程TCP协议中封包、拆包问题

在使用 Socket 编程&#xff0c;进行TCP协议网络通信时&#xff0c;经常会遇到“粘包”&#xff08;也称为“封包、拆包”&#xff09;的问题。粘包是指发送方发送的多个数据包被接收方合并成一个数据包&#xff0c;或者一个数据包被拆分成多个数据包接收。这通常是由于 TCP协议…

HarmonyOS:@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化

装饰器仅能观察到第一层的变化&#xff0c;但是在实际应用开发中&#xff0c;应用会根据开发需要&#xff0c;封装自己的数据模型。对于多层嵌套的情况&#xff0c;比如二维数组&#xff0c;或者数组项class&#xff0c;或者class的属性是class&#xff0c;他们的第二层的属性变…

Excel拆分脚本

Excel拆分 工作表按行拆分为工作薄 工作表按行拆分为工作薄 打开要拆分的Excel文件&#xff0c;使用快捷键&#xff08;AltF11&#xff09;打开脚本界面&#xff0c;选择要拆分的sheet&#xff0c;打开Module&#xff0c;在Module中输入脚本代码&#xff0c;然后运行脚本 Su…

【机器人】Graspness 端到端 抓取点估计 | 论文解读

在复杂场景中实现抓取检测&#xff0c;Graspness是一种端到端的方法&#xff1b; 输入点云数据&#xff0c;输出抓取角度、抓取深度、夹具宽度等信息。 开源地址&#xff1a;GitHub - rhett-chen/graspness_implementation: My implementation of Graspnet Graspness. 论文地…

盛元广通畜牧与水产品检验技术研究所LIMS系统

一、系统概述 盛元广通畜牧与水产品检验技术研究所LIMS系统集成了检测流程管理、样品管理、仪器设备管理、质量控制、数据记录与分析、合规性管理等功能于一体&#xff0c;能够帮助实验室实现全流程的数字化管理。在水产、畜牧产品的质检实验室中&#xff0c;LIMS系统通过引入…

kubeadm安装K8s高可用集群之集群初始化及master/node节点加入calico网络插件安装

系列文章目录 1.kubeadm安装K8s高可用集群之基础环境配置 2.kubeadm安装K8s集群之高可用组件keepalivednginx及kubeadm部署 3.kubeadm安装K8s高可用集群之集群初始化及master/node节点加入集群calico网络插件安装 kubeadm安装K8s高可用集群之集群初始化及master/node节点加入ca…