Linux---进程的基本概念

在了解进程之前先要知道操作系统的基本原理。

操作系统

操作系统是管理计算机硬件与软件资源的计算机程序,是计算机系统的内核与基石。简单理解就是,操作系统包括内核与其他程序两部分。

  • 内核包括:进程管理、内存管理、文件管理等。
  • 其他程序:库函数、shell程序等。

设计操作系统就是方便用户与硬件进行交互,帮助用户管理软硬件资源。那么怎么管理呢?
例如:学生、班长、班主任,学生被班长管理,班长又受班主任管理,层层递进。
总的来说,操作系统管理软硬件资源,就是先对其进行描述,再对其进行组织管理。

  • 描述起来是用struct结构体。
  • 组织是通过一些数据结构。
    由于操作系统内核中包括进程管理,所以操作系统对进程的管理方式也是,先描述,再组织(将多个进程组织起来)。

进程

概念

进程是一个运行中的程序,但是操作系统将运行中的程序描述起来,通过描述来实现对程序的运行调度,这个描述信息就是操作系统调度一个程序运行的实体。

  • 用户角度:一个运行中的程序。
  • 操作系统角度:运行中程序的描述信息,通过一个task_struct结构体来描述,统称为pcb(也称为进程控制块)。

task_struct中包含的内容(pcb中的内容)

  • 进程标识符
  • 内存指针
  • 上下文数据
  • 程序计数器
  • 优先级
  • 记账信息
  • I/O状态信息
  • 其他信息

操作系统组织进程的方式:通过链表的形式将task_struct结构体存在内核中。

cpu的分时机制(时间片轮转)
cpu对每一个进程的处理时间都非常的短,处理完后,切换下一个进程,不停的进行轮询处理。

进程的查看

  • ps -ef / -aux
    在这里插入图片描述
    在这里插入图片描述
    ps -aux查看的信息,比ps -ef多。

进程创建
fork函数,它从存在中的进程创建一个新进程,该新进程称为子进程,原进程称为父进程。

#include <stdio.h>
#include <unistd.h>
int res = fork();

fork返回值:

  • 子进程: == 0
  • 父进程:> 0返回子进程的pid ,< 0 创建子进程失败。

fork创建子进程之后,通常要用if分流

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
    
    
        //创建一个子进程
        int ret = fork();
        if(ret<0)
        {
    
    
                perror("创建失败“);
                return -1;
        }
        else if(ret == 0)
        {
    
    
                printf("子进程 进程ID = %d ret = %d",getpid(),ret);
        }
        else
        {
    
    
                printf("父进程 进程ID = %d ret = %d",getpid(),ret);
        }
        return  0;
}

使用fork创建子进程,新的进程(子进程)会复制父进程(代码共享,数据独有),用fork创建出来的子进程,只是拷贝fork函数后面的数据,之前的不会拷贝。

进程状态
进程的状态有:就绪态,运行态、阻塞态。
Linux下进程的状态:

  • R运行态,并不意味着进程一定在运行,有可能进程处于运行队列中。
  • S休眠态,意味着进程在等待某一事件的完成,可以被打断。
  • D磁盘休眠态:不可中断,在该状态下进程一般等待IO操作结束。
  • T停止状态
  • X死亡状态

进程状态查看的方法:ps -aux/-axj
在这里插入图片描述

孤儿进程

产生原因:父进程提前退出,子进程就被称为“孤儿进程”,子进程成为后台进程,并且子进程被1号进程所收养,其父进程变为1号进程。

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
    
    
        //创建一个子进程
        int ret = fork();
        if(ret<0)
        {
    
    
                perror("创建失败“);
                return -1;
        }
        else if(ret == 0)
        {
    
    
                printf("子进程 进程ID = %d",getpid());
                sleep(10);
        }
        else
        {
    
    
                printf("父进程 进程ID = %d",getpid());
                sleep(5);
                exit(0); //父进程退出
        }
        return  0;
}

僵尸进程

子进程退出后,资源没有释放,处于僵死状态。
产生原因:子进程优先于父进程退出,父进程正在执行其他操作,没有关注子进程退出,这时候操作系统为了保护子进程退出的原因,不会释放子进程中的资源,子进程既没有运行,也没有退出,处于僵死状态,成为僵尸进程。

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
    
    
        //创建一个子进程
        int ret = fork();
        if(ret<0)
        {
    
    
                perror("创建失败“);
                return -1;
        }
        else if(ret == 0)
        {
    
    
                printf("子进程 进程ID = %d",getpid());
                exit(0); //子进程退出
        }
        else
        {
    
    
                printf("父进程 进程ID = %d",getpid());
                sleep(10);
        }
        return  0;
}

在这里插入图片描述
僵尸进程的危害

  • 如果父进程一直不关注子进程退出,子进程将一直处于僵尸进程。
  • 因为子进程没有退出,所以pcb一直没有被释放。
  • 存在内存泄漏。

怎么避免产生僵尸进程

  • 关闭父进程,当父进程关闭以后,子进程将没有必要保存自己的退出信息。
  • 设置进程等待,等待子进程退出后,通知父进程。

环境变量

在操作系统中,用来指定操作系统的运行环境的参数。

常见的环境变量

  • HOME:家目录。
  • PATH:指定命令的搜索路径。
  • SHELL

查看环境变量

  • echo $name, 通过变量名称,查看指定变量。
  • env:查看所有环境变量
  • export:声明一个环境
  • unset:删除一个临时变量

在这里插入图片描述
每个程序都有一个环境表,环境表类似于一个指向数组的指针,在数组中存放一个个环境参数。

查看环境变量的方法:

#include<stdio.h>

int main(int agv,char *argv[])
{
    
    
        extern char **environ;
        int i = 0;
        for(;environ[i];i++)
        {
    
    
                printf("%d -- %s\n",i,environ[i]);
        }
        return 0;
}

在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
int main()
{
    
    
	char * env = getenv("MYENV"); //getenv访问特定环境变量的接口
	if(env){
    
    
		printf("%s\n", env);
	}
	return 0;
}

由于子进程会复制父进程的pcb,所以父进程的环境变量,子进程可以被继承。

猜你喜欢

转载自blog.csdn.net/qq_42708024/article/details/104349058