Linux__进程概念详解

进程

进程指正在执行的程序。从内核来说,它是担当分配系统资源(CPU时间,内存)的实体。

那进程跟程序有什么区别呢?从数据和代码层面看,它们是一样的,但是进程比程序多了一个东西,那就是描述进程的PCB结构体。
那这个PCB到底有什么作用呢?

PCB

相信学过操作系统的同学都知道,操作系统作为软件和硬件的管理者,那操作系统要管理那么多的进程,而每个进程都有很多的信息,为了方便管理这些进程信息,它们被放在一个叫做进程控制块的数据结构中,我们称之为PCB。

在Linux中描述进程的结构体叫做task_struct。它是Linux内核的一种数据结构,会被装载到内存里。

task_ struct内容分类

标识符(PID) :跟这个进程相关的唯一标识符,用来区别其他进程
状态 :如果进程正在执行,那么进程处于执行状态。
优先级 :相对于其他进程的优先级。
程序计数器 :程序中即将被执行的下一条指令的地址。
内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
上下文数据:进程执行时处理器的寄存器中的数据。
I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备(如磁带驱动器)和被进程使用的文件列表。
审计信息:可包括处理器时间总和,使用的时钟数总和,时间限制,审计号等。

标识符(PID)

在Linux下可以使用top命令(相当于windows系统下的任务管理器)可以查看
在这里插入图片描述
也可以使用ps aux命令,可以查看所有进程,也可以使用ps aux | grep +特定要查找的进程 。(可以使用ps aux | head -1 && ps aux | grep XXX可在第一行显示对应的属性)

当然也有可以查看PID的函数getpid(),查看父进程的函数getppid()

 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 int main()
 {
     printf("pid: %d\n",getpid());
     printf("ppid: %d\n",getppid());
 	 return 0;
 }   
getpid返回当前进程标识,getppid返回父进程标识。可以通过ps aux | grep + PID,可以看到所显示的父进程PID为bash

可以通过echo $$ 查看脚本运行的当前进程的PID

使用ls /proc 命令可以查看动态目录,存放的是一些进程的信息。

通过系统调用创建进程(fork)

如何创建一个进程呢?我们可以使用fork()函数来创建

 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 int main()
 {
     fork();
     printf("process : %d , parent: %d\n", getpid(), getppid());
     sleep(1);
     return 0;
 }


可以看到fork之后有两个进程,为父子关系。
而fork的有两个返回值,给父进程返回子进程的PID,给子进程返回0值。 父进程后面需要通过子进程的PID管理子进程的状态。

进程状态

可以通过ps aux | ps axj 命令查看

R(running) 运行状态:表示进程要么在运行中,要么在运行队列里。
S(sleeping) 睡眠状态:可中断睡眠状态,表示进程正在等待事件完成。
D(disk sleep) 磁盘休眠状态:不可中断睡眠状态,在这个状态的进程通常会等待IO的结束。
T(stopped) 停止状态:可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可 以通过发送 SIGCONT 信号让进程继续运行。
X(dead) 死亡状态:这个状态为返回状态。
Z(zombie) 僵尸状态:当进程退出并且父进程使用wait()系统调用没有读取到子进程退出的返回代码时就会产生僵死(尸)进程,僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。 所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态。(类似于警察检查死者,要知道死者的原因和状态)

注:若系统中有大量僵尸状态的进程,长时间不回收,会造成内存资源的浪费,造成==内存泄漏问题==

在下面简单的实现一个僵死进程

#include <iostream>                                       
#include <stdlib.h>
#include <sys/types.h>
include <unistd.h>
using namespace std;

int main()
{
    pid_t id = fork();
    int count = 0;
    if(id == -1){
        cerr << "fork error " << endl;
    }
    if(id == 0){//chlid
    while(1){
        cout << "I am chlid ..." << endl;
        sleep(1);
        if(count++ >= 3)
             exit(1);   //退出进程
    }
    else
	{
		 while(1){//father
		 cout << "I am father " << endl;
		 sleep(1);
		 }
	}
	return 0;
}

另起一个终端,跑一个脚本 while :; do ps aux | grep ‘myprocess’| grep -v grep ;sleep 1;echo ‘###################’;done

在这里插入图片描述
可以从图片上看出三秒之后,子进程变成僵死状态。

那父进程如果提前退出,子进程后退出会怎样呢?这时候子进程就称为孤儿进程了,应该由1号(操作系统)init进程领养,之后也由init进程回收。

int main()
{
    pid_t id = fork();
    int count = 0;
    if(id == -1){
        cerr << "fork error " << endl;
    }
    if(id == 0){//chlid
    while(1){
        cout << "I am chlid ..." << endl;
        sleep(1);
    }
    else
	{
		 while(1){//father
		 cout << "I am father " << endl;
		 sleep(1);
		 if(count++ >= 3)
             exit(1);   //退出进程
		 }
	}
	return 0;
}

跑脚本:while :; do ps axj | grep ‘myprocess’| grep -v grep ;sleep 1;echo ‘###################’;done

注:要看到父进程,需要将aux变成axj

在这里插入图片描述
可以看到当父进程退出之后,子进程被1号进程领养。

进程优先级

进程的优先权:CPU资源分配的先后顺序。一般来说,数字越小优先级越高。
可以使用ps -l 命令查看优先级
在这里插入图片描述
nice值为Linux下优先级的修正数据,nice其取值范围是-20至19。
PRI = (旧的)PRI + nice

可使用top命令进行修改(一般不建议修改)
进入top之后按“r” —> 输入进程ID —>输入nice值


总结来说,如何管理进程就是先描述再组织,先把进程描述起来(就是这些表征信息,都放在task_struct里面),然后进行组织。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值