多任务——进程(创建、退出、等待)

多任务

多任务主要包括:进程、进程间通信、线程这三大内容

一、什么是单任务?
一个任务执行结束之后,另一个任务才开始执行。

二、什么是多任务?
1)正确理解:系统可以响应多个任务。一个任务执行过程中,可以暂停执行,然后cpu执行其他任务。
2)错误理解:同时执行多个程序。
接下来,解释一下为什么这个说法是错误的。对于单个cpu平台来说,也就是单核平台来说,一个核同一时刻只能执行一条语句,但是单核也可以进行多任务。这就说明多任务不可能同时执行多个程序。
2、单核和多核cpu进行多任务时,单核是并发执行,多核是并行执行
1)并发执行(单核)——就是cpu轮换的执行,当前进程执行了一个短暂的时间片之后,切换执行另一个程序,如此反复,在宏观上感觉到所有的进程是在同时运行的,但是在微观上cpu每次只执行某一个进程的命令。
并行执行(多核)——不同的cpu同时独立执行不同的程序(与单核多任务区分开),这种叫并行执行。所以在多核中,并发核并行是同时存在的。
3、多任务:在进行任务切换时(任务切换是由操作系统来捕获的),分为抢占式和非抢占式
1)时间片轮转:非抢占式,非实时性,给每个任务使用cpu固定的时间,单核cpu进行多任务的方式。
2)中断:抢占式,实时性高。

进程

1、多任务编程也就是多进程、多线程编程
2、什么是进程?(进程和程序)
所有的程序都在硬盘上,只有./a.out执行这个程序时,它才会被加载到内存中,这叫做进程,程序执行结束后,进程也就随之而消失。程序是静态的,进程是动态的。

进程:一个程序执行的一次过程,进程是操作系统执行的最小执行单元,一个程序会有多个进程。
3、linux进程特点?
每个进程都有自己独立的虚拟地址空间,大小为4G(互不干扰,相互独立),所有的数据保存在自己独立的空间内。
4、进程虚拟地址空间的划分?
在这里插入图片描述
在这里插入图片描述
从上往下,高地址——低地址
栈空间:先进后出,系统管理,生命周期由所在函数决定
堆空间:先进先出,用户管理(malloc,free),用户决定
数据段:系统管理,生命周期:全局

5、进程id:动态分配,获取id
6、所有进程创建都是由父进程创建的,父进程创建的进程称为子进程
7、Linux下所有进程的父进程:init 0

创建进程

进程的创建1——fork函数
1、fork函数作用是:创建进程
2、工作原理
1)给子进程分配空间
2)拷贝父进程的代码段,数据段到子进程的地址空间
3)给父子进程的pid赋值

fork函数创建的进程,父子进程的执行顺序是随机的,父子进程的调度是由系统决定的,父子进程有自己的各自空间

3、getpid函数返回当前进程标识
getppid函数返回父进程标识
4、返回值作用:父进程返回的id号其实就是子进程的pid号
在这里插入图片描述

进程的创建2——vfork函数

执行顺序:创建子进程,子进程先执行,然后再执行父进程
空间:父子进程享用同一块空间
注意点:释放空间只能释放一次,所以在子进程结束后,要使用_exit()函数异常退出,否则会发生内存错误。
在这里插入图片描述
进程的创建3——system和exec函数族
1、system创建进程:也就是在进程中运行另一个程序
2、system(“./程序”),所以需要先将.c文件链接成可执行文件,gcc 文件名.c -o 文件名
3、exec函数族:覆盖原有进程的代码段,创建新的进程,pid会发生改变
4、system和exec区别:system执行的进程不会覆盖原有的进程代码,也就是说不会改变新的进程,pid不会发生改变
在这里插入图片描述

进程退出

exit或者_exit函数

区别:
1、exit是库函数,里面封装了_exit函数,_exit函数是系统调用函数,只能在Linux下使用
2、_exit函数退出进程不会使进程刷新缓冲区,而exit函数在_exit函数后会刷新缓冲区。

进程等待

1 、僵尸进程:父进程先于子进程退出来,该子进程就成了一个僵尸进程,因为子进程的资源需要靠父进程进行回收。
2、怎么解决僵尸进程?
1)进程等待,等待子进程结束后回收资源
2)wait(pid)函数堵塞等待子进程退出
3)waitpid函数

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
//waitpid的返回值比wait稍微复杂一些,一共有3种情况:
// 1、当正常返回的时候,waitpid返回收集到的子进程的进程ID;
// 2、如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
// 3、如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;

//WNOHANG参数调用waitpid,即使没有子进程退出,它也会立即返回
// pid>0时,只等待进程ID等于pid的子进程
// pid=-1时,等待任何一个子进程退出,没有任何限制
// pid=0时,等待同一个进程组中的任何子进程,
//如果子进程已经加入了别的进程组,waitpid不会对它做任何理睬。
// pid<-1时,等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值。

int main()
{
    //pid_t waitpid(pid_t pid,int *status,int options);
    pid_t pc,pr;
    pc=fork();
    if(pc<0)
    {
    	 printf("error occured on forking\n");
    }
    else if(pc==0)
    {
    	printf("fork jincheng success\n");
        sleep(5);
        exit(0);
     }
       /* 如果是父进程 */
     do{
     	  pr=waitpid(pc,NULL,WNOHANG);// 使用了WNOHANG参数,waitpid不会在这里等待
          if(pr==0)
           {
                printf("no child exited\n");
                sleep(1);
            }
        }whlie(pr==0);/* 没有收集到子进程,就回去继续尝试 */
         if(pr==pc)
    {
        printf("successfully get child %d\n",pr);
    }
    else
    {
        printf("some errors occured\n");
    }
    
    return 0;
}
//把pr=waitpid(pc, NULL, WNOHANG)
//改为pr=waitpid(pc, NULL, 0)或者pr=wait(NULL)
//修改后的结果使得父进程将自己阻塞,直到有子进程退出为止
    
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值