首页 > 系统相关 >Linux 进程

Linux 进程

时间:2024-08-20 08:58:05浏览次数:8  
标签:状态 调度 PCB exit Linux 进程 CPU

进程

含义:

进程是一个程序执行的过程,会去分配内存资源,具有并发特性(同一时段,运行多个任务)。

进程的基本特性:

(1)动态性:进程是程序的一次执行,它有着创建、活动、暂停、终止等过程,具有一定的生命周期,是动态地产生、变化和消亡的。动态性是进程最基本的特征。

(2)并发性:指多个进程实体同时存于内存中,能在一段时间内同时运行。并发性是进程的重要特征,同时也是操作系统的重要特征。引入进程的目的就是为了使程序能与其他进程的程序并发执行,以提高资源利用率。

(3)独立性:指进程实体是一个能独立运行、独立获得资源和独立接受调度的基本单元。凡未建立PCB的程序都不能作为一个独立的单元参与运行。

(4)异步性:由于进程的相互制约,使得进程具有执行的间断性,即进程按各自独立的、不可预知的速度走走停停、何时开始何时暂停何时结束不可预知的性质,就会导致执行结果的不可再现性,为此在操作系统中必须配置相应的进程同步机制。

(5)结构性:每个进程都配置一个PCB对其进行描述。从结构上看,进程实体是由程序段、数据段和进程控制块三部分组成的。
 

进程的组成

        从结构上看,进程实体是由程序段数据段进程控制块三部分组成的。

        进程控制块 PCB:每个进程有且仅有一个进程控制块(Process Control Block,PCB),或称作进程描述符,它是进程存在的唯一标识,是操作系统用来记录和刻画进程状态及环境信息的数据结构,也是操作系统掌握进程的唯一资料结构和管理进程的主要依据。所以 PCB 是提供给操作系统使用的,操作系统需要对各个进程进行管理,所有管理时所需要的信息,都会被放在 PCB 中。创建进程和撤销进程等都是指对 PCB 的操作,当进程被创建时,操作系统为其创建 PCB,当进程结束时,会回收其 PCB。        

        进程控制块 PCB 一般包含如下四类信息:        

        1)进程描述信息:用来让操作系统区分各个进程,当进程被创建时,操作系统会为该进程分配一个唯一的、不重复的 “身份证号”— PID(ProcessID,进程 ID)。另外,进程描述信息还包含进程所属的用户 ID(UID)        

       2) 进程控制和管理信息:记录进程的运行情况。比如 CPU 的使用时间、磁盘使用情况、网络流量使用情况等。        

        3)资源分配清单:记录给进程分配了哪些资源。比如分配了多少内存、正在使用哪些 I/O 设备、正在使用哪些文件等。      

         4)CPU 相关信息:进程在让出 CPU 时,必须保存该进程在 CPU 中的各种信息,比如各种寄存器的值。用于实现进程切换,确保这个进程再次运行的时候恢复 CPU 现场,从断点处继续执行。这就是所谓的保存现场信息。

数据段:一个进程的数据段,可以是进程对应的程序加工处理的原始数据,也可以是程序执行时产生的中间或最终结果,即进程运行过程中的各种数据(比如程序中定义的变量)。

程序段:程序段就是能被进程调度时程序调度到CPU执行的程序代码段(指令序列)。注意,程序可被多个进程共享,即多个进程可以运行同一个程序。例如:同时挂三个 QQ 号,会对应三个 QQ 进程,它们的 PCB、数据段各不相同,但程序段的内容都是相同的(都是运行着相同的 QQ 程序)

注意:Linux内核使用task_struct数据结构作为PCB的具体实现。task_struct包含了进程的多种属性,如进程标识符(PID)、状态、优先级、程序计数器、内存指针、上下文数据、I/O状态信息等。这些信息帮助操作系统管理和调度进程 

进程和程序的区别


程序:静态
存储在硬盘中代码,数据的集合
进程:动态
程序执行的过程,包括进程的创建、调度、消亡

1)程序是永存,进程是暂时的
2)进程有程序状态的变化,程序没有
3)进程可以并发,程序无并发
4)进程与进程会存在竞争计算机的资源
5)一个程序可以运行多次,变成多个进程
一个进程可以运行一个或多个程序

内存的分布(以32位为例)

0-3G,是进程的空间,3G-4G是内核的空间,虚拟地址(总的内存为4GB)。
虚拟地址 *  物理内存和虚拟内存的地址 映射表 1page=4k   

内存分布图:

进程分类

1、交互式进程   
2、批处理进程   (批处理进程是指那些不需要用户干预即可自动执行的进程。它们通常用于执行一系列预先定义好的任务或脚本。)
3、 守护进程    (大部分时间处于休眠状态,满足某些特定条件才运行)

进程的状态:

3个状态,就绪→执行态→阻塞(等待,睡眠)基本操作系统
linux中的状态,运行态,睡眠态,僵尸态,暂停态。

进程的调度:

进程调度是操作系统内核的一个重要功能,它负责决定哪个进程获得处理器时间以及何时进行切换。(宏观并行,微观串行)

1.调度队列(Ready Queue):
就绪队列包含所有可运行的进程,它们已经准备好被CPU执行。

2.调度策略(Scheduling Policy):
操作系统采用不同的调度策略来决定哪个进程应该获得CPU时间。常见的调度策略包括先来先服务(FCFS)、最短作业优先(SJF)、轮转(Round-Robin)、优先级调度等。

3.上下文切换(Context Switch):
当前运行的进程被挂起,CPU的状态(如寄存器内容)被保存到该进程的PCB中。然后,调度程序加载下一个要运行的进程的上下文到CPU。

4.调度算法(Scheduling Algorithm):
调度算法是一组规则,用于决定进程调度的顺序。不同的算法有不同的性能指标,如吞吐量、响应时间、等待时间和周转时间。

5.抢占式调度(Preemptive Scheduling):
在抢占式调度中,高优先级的进程可以中断当前正在运行的进程,抢占CPU时间。

6.非抢占式调度(Non-Preemptive Scheduling):
在非抢占式调度中,一旦一个进程开始执行,它将运行直到完成或主动放弃CPU。

7.优先级(Priority):
进程被赋予不同的优先级,调度器根据优先级来选择下一个要执行的进程。

8.时间片(Time Quantum):
在时间片轮转调度中,每个进程被分配一个时间片,即它在CPU上允许运行的时间。

9.多级队列(Multilevel Queue):
操作系统可能使用多个队列来管理不同类别的进程,每个队列都有自己的调度算法。

10.多级反馈队列(Multilevel Feedback Queue):
一种复杂的调度机制,允许进程在多个优先级队列之间移动,根据其行为动态调整优先级。

11.调度决策(Scheduling Decisions):
调度器需要做出的决策包括哪个进程将获得CPU,何时进行上下文切换,以及如何调整进程的优先级。

12.调度器(Scheduler):
调度器是操作系统内核的一部分,负责执行进程调度的算法和策略。

进程相关命令
1.ps  aux

查看进程相关信息

进程的当前状态

D: Uninterruptible sleep(不可中断睡眠状态) - 进程正在等待某些事件的完成,通常是 I/O 操作。在这种状态下,进程不能被中断。

R: Running or runnable(运行或可运行状态) - 进程正在使用 CPU 或者在运行队列中等待 CPU 时间。

S: Interruptible sleep(可中断睡眠状态) - 进程正在等待某个事件的发生,并且可以被信号中断。

T: Stopped(停止状态) - 进程已经停止执行,通常是因为接收到了一个暂停信号(如 SIGSTOP)。

t: Traced or stopped by debugger(被跟踪或由调试器停止) - 进程被调试器控制或因为某些调试操作而停止。

W: Paging(分页状态) - 这个状态在 Linux 2.6 版本之后的内核中不再有效。

X: Dead(死亡状态) - 进程已经结束,但不应该会在 ps 命令的输出中看到。

Z: Defunct(“僵尸”状态) - 进程已经终止,但父进程尚未调用 wait() 或 waitpid() 系统调用来读取其退出状态。
2.top

根据CPU占用率查看进程相关信息

3.kill,killall

kill

kill 命令用于向特定进程发送信号。它的使用格式通常是 kill PID,其中 PID 是要接收信号的进程的进程标识符

kill    -2    (PID)15  //发送信号+PID对应的进程,默认接收者关闭
      (1-64)   (Id号) 
      (-2代表中止)

killall

killall 命令用于向所有匹配指定名称的进程发送信号。与 kill 不同,killall 通过进程名称而不是 PID 来识别进程。

killall -9 进程名
发送信号 进程名对应的所有进程

eg:
killall a.out
进程相关的函数
1.fork();

在Linux操作系统中,fork() 系统调用是一种创建新进程的方式。这个调用非常特殊,因为它会复制调用它的进程,生成一个新的子进程。

返回值:int 类型的数字。
       在父进程中:成功 返回值是子进程的 pid号 >0
                             失败 返回-1;
        在子进程中:成功 返回值 0
        失败 无

注意:

1.一次调用,会返回两次。
2.子进程先运行和是父进程先进程,顺序不确定。
3.变量不共享。
4.子进程复制父进程的0到3g空间和父进程内核中的PCB,但id号不同。
          功能:通过该函数可以从当前进程中克隆一个同名新进程。
                     克隆的进程称为子进程,原有的进程称为 父进程。
                     子进程是父进程的完全拷贝。
                     子进程的执行过程是从fork函数之后执行。
5.子进程与父进程具有相同的代码逻辑。

举例:边看电视边吃饭,(处理一起运行的进程)

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main(int argc, const char *argv[])
{
	pid_t ret=fork();
	if(ret>0)
	{
		//father
		while(1)
		{
			printf("吃饭\n");
			sleep(1);
				
		}
	}
	else if(0==ret)
	{
		//child
		while(1)
		{
			printf("看电视呢\n");
			sleep(1);
		}
	}
	else
	{
		perror("fork error\n");
		return 1;
	}

	
	return 0;
}

父子进程的关系:
子进程是父进程的副本。子进程获得父进程数据段,堆,栈,正文段共享。

在fork之后,一般情况那个会先运行,是不确定的。如果非要确定那个要先运行,需要IPC机制。

区别:
1)fork的返回值
2)pid不同

2.getpid
pid_t getpid(void);

功能:
        获得调用该函数进程的pid
参数:
        缺省
返回值:
        进程的pid

3.getppid
pid_t getppid(void);


功能:
        获得调用该函数进程的父进程pid号
参数:
        缺省
返回值:
        返回父进程id号

进程的终止:8中情况
1)main 中return
2)exit(), c库函数,会执行io库的清理工作,关闭所有 的流,以及所有打开的文件。已经清理函数(atexit)。
3)_exit,_Exit 会关闭所有的已经打开的文件,不执行清理函数。
4) 主线程退出
5)主线程调用pthread_exit
异常终止
6)abort()
7)signal   kill pid
8)最后一个线程被pthread_cancle

进程的退出


  僵尸进程和孤儿进程

僵尸进程:进程执行结束但空间未被回收变成僵尸进程

僵尸:
    当一个子进程完成执行后,如果父进程没有通过wait()或waitpid()系统调用来获取子进程的退出状态,子进程的进程描述符(PCB)仍然保留在系统中,这种状态的进程被称为僵尸进程 

僵尸进程的产生原因主要有两点:
    子进程已经终止,但父进程没有调用wait()或waitpid()来回收子进程的资源。
父进程在子进程终止前退出,导致子进程成为孤儿进程,被init进程接管,但僵尸状态的子进程仍然存在 
。

孤儿进程:

是指父进程已经终止,但子进程仍在运行的进程




1.exit     库函数


        退出状态,终止的进程会通知父进程,自己使如何终止的。如果是正常结束(终止),则由exit传入的参数。如果是异常终止,则有内核通知异常终止原因的状态。任何情况下,负进程都能使用wait,waitpid获得这个状态,以及资源的回收。

void exit(int status) 
exit(1);


功能:
        让进程退出,并刷新缓存区
参数:
        status:进程退出的状态
返回值:
        缺省

举例:


#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
    
    FILE* fp = fopen("1.txt","w");
    char buf[512]="hello,123";
    fputs(buf,fp);
    exit(0);
    printf("aaaaaaaaaaa\n");
    return 0;
}



return  当该关键字出现在main函数中时候可以结束进程
如果在其他函数中则表示结束该函数。
exit -> 刷新缓存区 -> atexit注册的退出函数 -> _exit


2._exit    系统调用


函数原型

void _exit(int status);


功能:
        让进程退出,不刷新缓存区
参数:
        status:进程退出状态
返回值:
        缺省



3.atexit  (回调函数)

        通常用于执行清理工作,比如释放资源或保存状态。

原型:

int atexit(void (*function)(void));


功能:
        注册进程退出前执行的函数
参数:
        function:函数指针
        指向void返回值void参数的函数指针
返回值:
        成功返回0
        失败返回非0

注意事项:

    atexit 调用的函数不应该执行太长时间,因为它们会阻塞程序的退出。

               程序员应该小心避免在退出函数中调用可能已经关闭的函数或资源。

                过多的 atexit 调用可能会影响程序的性能,因为每个调用都需要系统来跟踪这些函数。

                当程序调用exit或者由main函数执行return时,所有用atexit注册的退出函数,将会由注册时顺序倒序被调用

举例:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
char * p ; 
void clean(void)
{
    printf("clean func,p %s\n",p);
    free(p);
}

int main(int argc, char *argv[])
{
    atexit(clean);
    p = (char*)malloc(50);

    strcpy(p,"hello");

    printf("main p %s\n",p);
    exit(0);
    
    return 0;
}

标签:状态,调度,PCB,exit,Linux,进程,CPU
From: https://blog.csdn.net/qq_63145217/article/details/141317287

相关文章

  • Linux scp 文件传输
    scp将本服务器的文件传输到远程服务器基本语法scp`[源路径]``[目标服务器]`:`[目标路径]`样例将本服务器123.txt文件传输到远程服务器并重命名为456.txtscp123.txtuser@remote_server:/home/tabu/456.txt使用-r选项复制整个目录scp-rtabu/*user@remote_server:/ho......
  • Linux搭建环境:从零开始掌握基础操作(二)
    ​​您好,我是程序员小羊!前言软件测试第一步就是搭建测试环境,如何搭建好测试环境,需要具备两项的基础知识:1、Linux命令:软件测试第一个任务,一般都需要进行环境搭建,一部分,环境搭建内容是在服务器上实现的,跟服务器交互(没有图形化页面),需要使用Linux命令。2......
  • Redis在Linux(Centos7)单机部署和集群部署
    目录一、单机部署1、软件准备 2、安装配置3、启动Redis二、Redis集群2.1、主从模式2.1.1、作用 2.1.2、规划图2.1.3、具体配置准备工作 主从配置启动测试 2.1.4、主从复制原理主从全量复制主从增量同步(slave重启或后期数据变化)2.1.5、缺点 2.2、哨兵......
  • 简单的linux系统学习笔记——08
    一、文件属性-权限属性33555523-rw-r--r--.1rootroot1586月72013/etc/hosts-rw-r--r-- 【rw-】:权限是属主的权限 【r--】:权限是属组的权限 【r--】:权限是其他人的权限r//读取权限 针对文件:含义是,可以打开文件,查看文件的内容 针对目录:含义是,可以查......
  • 简单的linux系统学习笔记——09
    一、用户分类1.root//皇帝用户,定制规则用户,系统高级管理员【uid,gid0】2.普通用户//有特定的权限,权限是root授予的【uid,gid大于1000】3.傀儡用户//没有家目录,不能登录系统;【0-999】二、用户相关的配置文件1.用户列表文件[root@c7-100~]#cat/etc/passwdroot:x......
  • C++ 获取Linux 服务器CPU占用率+内存空闲率(亲测绝对可以运行)
    转自:C++获取Linux服务器CPU占用率+内存空闲率(亲测绝对可以运行)-远征i-博客园(cnblogs.com)代码来自网络,部分修改,亲测绝对可用C++:#include<stdio.h>#include<stdlib.h>#include<string.h>#include<iostream>#include<unistd.h>usingnamespacestd;type......
  • TCPIP路由技术第一卷第七章第六部分案例研究二多eigrp进程Passive接口自动汇总和手工
    tcp/ip_eigrp-2案例研究r1:routereigrp90nonetwork15.1.1.10.0.0.0r5:noroutereigrp90routereigrp1network0.0.0.00.0.0.0r1:routereigrp1network15.1.1.10.0.0.0routereigrp90redistributeeigrp1(在eigrp和eigrp之间重分布不需要加metric)rout......
  • Linux学习/TCP Socket通信
    案例案例一server.c#include<stdio.h>//标准输入输出#include<stdlib.h>//提供通用的工具函数,例如内存分配和程序退出。#include<string.h>//提供字符串处理函数。#include<unistd.h>//提供对POSIX操作系统API的访问,包括对文件描述符的操作。#include<arpa/i......
  • 【Linux_install】详细的Ubuntu和win双系统安装指南
    @目录1.前期准备1.1制作启动盘1.2关闭快速启动、安全启动、bitlocker1.2.1原因1.2.2进入BIOSshell命令行进入BIOSwindows设置中高级启动在开机时狂按某个键进入BIOS1.2.3关闭Fastboot和Secureboot1.3划分磁盘空间1.3.1查看目前的虚拟内存大小2.开始安装2.1使用启动盘启动......
  • Linux---systemctl常用命令以及service文件配置
    简介1.1什么是systemctl命令        systemctl是一个在Linux系统中用于管理系统服务的命令。它是systemd这个初始化系统的一部分,通过控制和监视系统的服务和单位文件,提供了对系统进程的强大管理功能。1.2systemctl的作用和用途        systemctl可以用于......