Linux——进程介绍

一、进程

1.基本概念

    课本概念:程序的一个执行实例,正在执行的程序等

     内核观点:担当分配系统资源的实体

描述进程——PCB

    进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合

    课本上之所以称之为PCB(process control block),Linux操作系统下的PCB是task_struct

task_struct——PCB的一种(是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息)

task_struct内容分类

    标识符:描述本进程的唯一标识符,用来区别其他进程

    状态:任务状态,退出代码,退出信息等

    优先级:相对于其他进程的优先级

    程序计数器:程序中即将被执行的下一条指令的地址

    内存指针:包含程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针

    上下文数据:进程执行时处理器的寄存器中的数据

    I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表

    记账信息:可能包含处理器时间总和,使用的时钟数总和,时间限制,记账号等

    其他信息

2.组织进程

     可以在内核源代码里找到它,所有运行在系统里的进程都以task_struct链表的形式存在内核里

3.查看进程

    进程的信息可以通过/proc系统文件夹查看

    如要获取PID为1的进程信息,需要查看/proc/1这个文件夹:



通过系统调用来获取进程标识符

    系统为每一个进程分配一个唯一的标识号,这个标识号就称为进程的ID(process identifer)

    进程id(PID)

    父进程id(PPID)

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

4.通过系统调用创建进程——fork()初识

进程创建的一般过程:

    1.分配PID

    2.分配PCB

    3.将父进程环境复制过来

    4.将父进程地址空间的内容拷贝到自己的地址空间

    5.放入就绪队列

    使用man手册认识fork():


    返回值:


    父子进程代码共享,数据各自开辟空间

    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>
    
    int main()
    {
        int ret=fork();
        printf("hello proc:%d,ret:%d\n",getpid(),ret);
        return 0;
    }

    fork()之后通常要用if分流:

    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>
    
    int main()
    {
        int ret=fork();
        if(ret<0){
            perror("fork");
            return 1;
        }
        else if(ret==0){  //child
            printf("I am child:%d,ret:%d\n",getpid(),ret);
        }
        else{   //father
            printf("I am father:%d,ret:%d\n",getppid(),ret);
        }
        sleep(2);
        return 0;
    }

二、程序和进程

    程序:完成特定任务的一系列指令集合

    进程:从用户角度看,进程是程序的一次动态执行过程;从操作系统角度看,进程是操作系统分配资源的基本单位,也是最小单位

   每个进程都有自己的状态和独立的地址空间

    进程需要有相关的数据结构来管理,操作系统通过PCB感知一个进程的存在

    程序:数据+代码

    进程:数据+代码+堆栈+PCB

进程和程序的区别:

    进程是动态,程序是静态

    进程的生命周期短暂,程序永久

    进程有重要的数据结构PCB

    一个进程只能对应一个程序,一个程序可以对应多个进程

三、进程状态


1.进程的几种状态

    R 运行状态(running):并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里

    S 睡眠状态(sleeping):意味着进程在等待事件完成(也可叫做可中断睡眠 interruptible sleep)

   D 磁盘休眠状态(Disk sleep):有时也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待 I/O的结束

    T 停止状态(stopped):可以通过发送SIGSTOP信号给进程来停止(T)进程,这个被暂停的进程可以通过发送SIGCONT信号让进程继续运行

    X 死亡状态(dead):这个状态只是一种返回状态,你不会在任务列表里看到这个状态


2.进程状态的修改

    通过kill演示一下T、R状态:

    · kill -l:查看系统支持的信号列表

    · ps -l:查看进程信息

    · kill -SIGSTOP pid:将该进程状态改为T状态

    · kill -SIGCONT pid:将该进程状态改为R状态


Z(zombie)僵尸进程

    · 僵尸状态(zombie)是一个比较特殊的状态,当进程退出并且父进程(使用wait()系统调用)没有读到子进程退出的返回代码时就会产生僵尸进程

    · 僵尸进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态码

    · 所以,只要子进程退出父进程还在运行,但父进程中没有读取子进程状态,子进程进入Z状态

举例:维持30秒僵尸进程

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        pid_t id=fork();
        if(id<0){
            perror("fork");
            return 1;
        }
        else if(id>0){
            printf("parent [%d] is sleeping...\n",getpid());
            sleep(30);
        }
        else{
            printf("child [%d] is begin z...\n",getpid());
            sleep(5);
            exit(EXIT_SUCCESS);
        }
        return 0;
    }
    


编译运行并在另一个终端下启动监控:



测试结果:


可以看到子进程5秒后由S状态进入僵尸状态

僵尸进程危害

    · 进程的退出状态必须被维持下去,父进程若一直不读取,子进程将一直处于Z状态

    · 维护退出状态本身就是要用数据维护,也属于进程的基本信息,所以保存在PCB中,即Z状态一直不退出,PCB一直都要维护

    · 若一个父进程创建了很多子进程,就是不回收,就会造成资源的浪费,因为数据结构本身就要占用内存,就像C语言中定义一个结构体变量,是要在内存的某个位置开辟空间

    · 造成内存泄露

孤儿进程

    父进程如果提前退出,那么子进程后退出,进入Z状态之后,该如何处理?

    父进程先退出,子进程就被称为孤儿进程

    孤儿进程被1号init进程“领养”(当然要有init进程回收)

举例:

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    int main()
    {
        pid_t id=fork();
        if(id<0){
            perror("fork");
            return 1;
        }
        else if(id==0){
            printf("I am child,pid:%d\n",getpid());
            sleep(10);
        }
        else{
            printf("I am father,pid:%d\n",getpid());
            sleep(3);
            exit(0);
        }
        return 0;
    }

测试结果:







猜你喜欢

转载自blog.csdn.net/tangduobutian/article/details/79966388