您现在的位置:首页 >> 前端 >> 内容

学习进程的创建:进程的实际应用

时间:2018/5/31 15:17:16 点击:

  核心提示:之前了解了进程的相关基础知识,现在来了解一下进程的实际应用1进程创建的一般过程:1)给新进程分配一个标识符。内核中分配一个PCB2)复制父进程的环境3)分配程序.数据.栈等内存资源4)复制父进程的地址...

之前了解了进程的相关基础知识,现在来了解一下进程的实际应用

1进程创建的一般过程:

1)给新进程分配一个标识符。内核中分配一个PCB

2)复制父进程的环境

3)分配程序.数据.栈等内存资源

4)复制父进程的地址空间的内容

5)将进程置成就绪状态,放入就绪队列

2.fork

1)首先调用fork之前,要加头文件#include

2)函数原型 pid_t fork(void)

3)返回值:子进程返回0,父进程返回子进程id,出错返回-1,创建子进程失败。

4)fork调用失败原因:系统内有太多进程或者实际用户的进程数超过了限制。

下面验证一下fork()的返回值

学习进程的创建:进程的实际应用

图中箭头和数字代表程序执行步骤

运行结果:

学习进程的创建:进程的实际应用

解释一下:程序开始执行,首先进入父进程,在调用fork之前,先输出父进程的id,执行fork后,父子进程会从fork之后的代码来继续执行,继续执行父进程,pid接受fork返回值,父进程返回子进程id,然后进入子进程,pid接收fork返回值,子进程返回0。

注意:

1)父子进程执行先后顺序不确定

2)调用fork以后,父子进程交替运行。

3)如果父进程先死,子进程就变成孤儿进程,孤儿进程会被1号进程收养。

4)如果子进程先死,子进程就会变成僵尸进程(清理僵尸进程,用wait函数)

另一种执行步骤:(fork后先执行子进程)

学习进程的创建:进程的实际应用

3.子进程与父进程

子进程继承父进程:

地址空间,进程上下文,进程堆栈,内存信息,文件描述符(父进程打开的文件),信号设置,进程调度优先级,当前路径,根路径,控制终端,进程组,资源限制情况...

子进程不继承父进程:

1>父进程的锁子进程不继承

2>父进程id子进程不继承

3>父进程未决的信号子进程不继承

4>父进程的闹钟子进程不继承

子进程与父进程的关系:

子进程以父进程为模板,首先复制父进程的PCB,并进行简单修改;复制父进程的虚拟地址空间(页表)对应的物理内存会进行写时拷贝。

4.vfork

1)首先调用vfork之前,要加头文件#include 和 #include

2)函数原型 pid_t vfork(void)

vfork 与fork的区别

1)vfork用于创建一个子进程,创建出来的子进程和父进程共用同一块虚拟空间。但fork出来的子进程具有独立的地址空间。

2)vfork出来的子进程一定会先执行,父进程会挂起,一直挂起到子进程调用了_exit或exec父进程才会继续执行。

实例:

 #include 
 #include 
 #include 
 #include 

 int glob=100;

 int main(void){
        pid_t pid;

        pid = vfork();
        if(pid==-1) perror("fork"),exit(1);
        else if(pid ==0) {//子进程
                sleep(3);
                glob=200;
                printf("child glob %d \n",glob);
                exit(0);
                }
        else { //父进程
                printf("parent glob %d \n",glob);
        }
        return 0;
}

运行结果:

学习进程的创建:进程的实际应用

解释一下:子进程先运行,修改了glob变量的值,调用了exit,父进程调度执行,父子进程共用一块虚拟内存,所以glob的值也被更改。

作者:网络 来源:Warrior_Ha