开发者

linux应用软件编程之多任务(进程)详解

目录
  • 一、多任务概述
  • 二、进程概述
    • 1.定义
    • 2.程序和进程的区别
    • 3.进程的产生
    • 4.进程的调度
    • 5.进程的状态
    • 6.进程的消亡
  • 三、进程相关的命令
    • 1. ps  -aux
    • 2. top
    • 3. ps -ef查看该进程的ID和父进程ID
    • 4. pstree查看进程的产生关系
    • 5.kill
    • 6. jobs查看当前终端的后台进程
    • 7.fg
  • 四、进程相关的编程
    • 1.实现进程的步骤
    • 2.进程创建函数
    • 3.示例程序
    • 3.进程退出函数
    • 4.回收资源空间:
  • 总结

    一、多任务概述

    1.定义:

    让系统具备同时处理多个任务的能力

    2.实现过程

    • 多进程
    • 多线程
    • 进程间通信

    二、进程概述

    1.定义

    一个正在运行的程序称为一个进程,其运行过程中需要消耗内存和CPU。

    linux应用软件编程之多任务(进程)详解

    2.程序和进程的区别

                           程序                        &nbswww.devze.comp;                                                               进程

    静态的数据集合,存储在硬盘空间               &编程客栈nbsp;    是一个程序动态执行的过程,需要消耗内存和CPU

    程序运行起来可以产生进程                               进程具备动态生命周期,从产生到调度再到消亡

    一个程序可以产生多个进程                               一个进程中也可执行多个程序

    3.进程的产生

    进程产生时,操作系统都会为其分配0-4G的虚拟内存空间。操作系统内存区如下图所示:

    linux应用软件编程之多任务(进程)详解

    (1)内核: 1 文件管理;2. 进程管;3. 内存管理。

    (2)栈区:1.保存局部变量;2.函数的形参和返回值;3.保存函数的调用关系(保护现场和恢复现场)。

    (3)堆区:1. 由开发人员手动分配;2. 使用完要手动释放。

    (4)数据区:

    • data段:1. 已初始化的全局变量 ;2. 已初始化的静态变量。
    • bss段:1.未初始化的全局变量 ; 2. 未初始化的静态变量(static)-->bss段初始时按位清0。
    • 字符串常量区:保存字符串常量   "hello world"

    (5)文本区:1. 存放指令代码 hpp;  ;2. 存放常量。

    4.进程的调度

    • CPU:

    由于CPU数据处理速度快,因此是“宏观并行,微观串行”。

    • cpu调度算法

    1、时间片轮询算法

    2、先来先服务,后来后服务(任务队列)

    3、短作业优先调度

    4、高优先级先执行,低优先级后执行

    5.进程的状态

    • 操作系统的三态图:

    linux应用软件编程之多任务(进程)详解

    • linux操作系统的进程状态:

    linux应用软件编程之多任务(进程)详解

    • 各进程状态:

    1.运行态(用户运行态、内核运行态)     R

    正在执行,且被CPU任务调度所执行的进程    

    2.就绪态    R

    正在执行,没有CPU任务调度执行的进程(只缺少cpu)

    3.可唤醒等待态    S

    也称为睡眠态,阻塞等待资源的进程

    4.不可唤醒等待态 D

    不想被CPU任务调度所打断的进程任务可以设置为不可唤醒等待态       

    5.暂停态    T

    被暂停执行的进程        

    6.僵尸态    Z

    进程执行结束,空间没有被回收        

    7.结束态    X

    进程执行结束,空间被回收

    6.进程的消亡

    • 进程执行结束(进程退出)
    •  回收进程资源空间

    三、进程相关的命令

    • 父进程:产生子进程的进程称为父进程
    • 子进程:父进程产生出来的新进程即为该父进程的子进程

    1. ps  -aux

    查看进程相关参数:PID、状态、CPU占有率、内存占有率

    linux应用软件编程之多任务(进程)详解

    • USER:创建者
    • PID:进程的ID号
    • %CPU:CPU占有率
    • %MEM:内存占有率
    • TTY:当前进程所关联的终端
    • STAT:当前进程的状态值(带“+”号表示前台进程,不带“+”号表示后台进程)
    • START TIME:进程创建的时间
    • COMMAND:进程的名称(init进程是操作系统启动的第一个进程)
    ps -aux | grep ./a.out
    • |:管道 :前面命令的输出作为后面命令的输入
    • grep:字符串查找:在输入中查找和后面字符串相关的数据        

     

    linux应用软件编程之多任务(进程)详解

    2. top

    动态查看进程的相关参数:CPU占有率、内存占有率

    ——按照CPU、内存占有率的高低进行排列的

    linux应用软件编程之多任务(进程)详解

    • PR、NI:表示进程的优先级,值越小,优先级越高
    • TIME+:进程运行的时间

    3. ps -ef查看该进程的ID和父进程ID

    linux应用软件编程之多任务(进程)详解

    4. pstree查看进程的产生关系

    pstree -p

    查看进程的产生关系(有PID号)

    linux应用软件编程之多任务(进程)详解

    pstree -sp  进程PID号

    查看某个指定的进程的产生关系

    linux应用软件编程之多任务(进程)详解

    5.kill

    kill -信号的编号/信号的名称  PID

    向进程发送信号,让进程的状态发生变化

    linux应用软件编程之多任务(进程)详解

    linux应用软件编程之多任务(进程)详解

    由第一张图片中可以看出20429进程一开始是在R+运行状态python,执行kill相关命令,其进程被杀死。

    结束一个进程的三种表示形式:

    kill -9 PID
    kill -SIGKILL PID
    killall -9  进程名称
    kill -l

    查看系统支持的信号

    linux应用软件编程之多任务(进程)详解

    • 9——SIGKILL——杀死信号
    • 19——SIGSTOP——暂停态信号
    • 18——SIGCONT——唤醒信号

    +前台进程后台进程

    6. jobs查看当前终端的后台进程

    linux应用软件编程之多任务(进程)详解

    7.fg

    [ fg 后台进程编号]

    让后台进程切换成前台进程

    linux应用软件编程之多任务(进程)详解

    linux应用软件编程之多任务(进程)详解

    四、进程相关的编程

    1.实现进程的步骤

    进程创建 :   fork()

    • getpid():获取当前进程自己的PID号
    • getppid():获取当前进程父进程的PID号

    进程调度:操作系统完成

    进程消亡:

    • 1.进程退出:return、exit()相关函数
    • 2.回收资源空间:wait()、waitpid()

    2.进程创建函数

    pid_t fork(void);

    功能:通过拷贝父进程产生一个新的子进程

    • 子进程完全拷贝父进程0-3G的虚拟内存空间
    • 子进程拷贝父进程PCB(进程控制块)块中的部分内容:PID不拷贝

    返回值:

    • >0:父进程 ,是子进程的PID号
    • ==0:子进程
    • -1 :出错

    linux应用软件编程之多任务(进程)详解

    3.示例程序

    使用fork函数创建新进程,

    • 父进程打印自己的PID和自己子进程的pid
    • 子进程中打印自己的PID和父进程的PID
    #include <sys/types.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    int main(int argc , const char *argv[])
    {
        
        pid_t pid = fork();
    
        if(pid > 0)
        {   
           
            while(1)
            {   
                printf("I am father pid = %d sonpid = %d \n",getpid(),pid);
                sleep(1);
            }
        }
        else if(0 == pid)
        {   
            
            while(1)
            {
    
                printf("I am son pid = %d ppid = %d \n",getpid(),getppid());
                sleep(1);
            }
        }
        else
        {
            perror("fork error");
        }
    
        return 0;
    }

    注意:

    1. 子进程完完整整拷贝父进程0-3G虚拟内存空间。

    2. 父子进程栈区、数据区、文本区、堆区完全独立,数据不共享

    3. 要想共享数据,需要使用进程间通信方式实现

    linux应用软件编程之多任务(进程)详解

    例如以下程序:

    #include <sys/types.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    int main(int argc , const char *argv[])
    {
        
        pid_t pid = fork();
        int num = 0;
        if(pid > 0)
        {   
           num = 100;
            while(1)
            {   
                printf("I am father pid = %d sonpid = %d  num = %d\n",getpid(),pid,num);
                sleep(1);
            }
        }
        else if(0 == pid)
        {   
            num = 1000;
            while(1)
            {
    
                printf("I am son pid = %d ppid = %d num = %d\n",getpid(),getppid(),num);
                sleep(1);
            }
        }
        else
        {
            perror("fork error");
        }
    
        return 0;
    }

    运行结果如下:

    linux应用软件编程之多任务(进程)详解

    3.进程退出函数

    (1)main中return

    #include <stdio.h>
    #include <stdlib.h>
    int fun()
    {
    	return 0;
    }
    int main(int argc, const char *argv[])
    {
    
    	int i = 15;
    	while (i--)
    	{
    		printf("PID =http://www.devze.com %d\n", getpid());
    		sleep(1);
    	}
    
    	return 0;
    }

     (2) exit ()、_exit() :结束一个进程

    • exit (0) : 正常退出
    • exit (非0) :由于进程产生了某种问题,需要主动退出进程
    #include <stdio.h>
    #include <stdlib.h>
    int fun()
    {
    	exit(0);
    	return 0;
    }
    int main(int argc, const char *argv[])
    {
    
    	fun();
    	
    	printf("hello world\n");
    	return 0;
    }

    4.回收资源空间:

    wait()、waitpid()

    僵尸进程:进程退出后,但其资源空间未被父进程回收

    如何避免僵尸进程产生:

    1.  子进程退出后,父进程及时为其回收资源空间

    2.  让该进程成为一个孤儿进程,结束时被操作系统中的系统进程回收

    孤儿进程:父进程先消亡,其对应的子进程成为一个孤儿进程,会被系统进程所收养

    (守护类的进程)

    #include <sys/types.h>
    #include <unistd.h>
    #include <stdio.h>
    int main(int argc, const char *argv[])
    {
    	pid_t pid = fork();
    	if (pid > 0)
    	{
    	
    		while (1)
    		{
    		
    			printf("I am father : pid = %d, sonpid = %d\n", getpid(), pid);
    			sleep(1);
    		}
    	}
    	else if (0 == pid)
    	{
    		int i = 15;
    		while (i--)
    		{
    			printf("I am son : pid = %d, ppid = %d\n", getpid(), getppid());
    			sleep(1);
    		}
    	}
    	else
    	{
    		perror("fork error");
    	}
    	return 0;
    }
    #include <sys/types.h>
    #include <unistd.h>
    #include <stdio.h>
    int main(int argc, const char *argv[])
    {
    	pid_t pid = fork();
    	if (pid > 0)
    	{
    		int i = 10;	
    		while (i--)
    		{
    		
    			printf("I am father : pid = %d, sonpid = %d\n", getpid(), pid);
    			sleep(1);
    		}
    	}
    	else if (0 == pid)
    	{
    		int i = 20;
    		while (i--)
    		{
    			printf("I am son : pid = %d, ppid = %d\n", getpid(), getppid());
    			sleep(1);
    		}
    	}
    	else
    	{
    		perror("fork error");
    	}
    	return 0;
    }

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新运维

    运维排行榜