fork()函数:创建一个新进程,需要包含下面的头文件

#include <sys/types.h>
#include <unistd.h>
pid_t  fork(void);

功能:fork()函数用于从一个已存在的进程中创建一个新进程;

           新进程称为子进程原进程称为父进程

返回值:

       >> 成功:子进程中返回0父进程中返回子进程PID

       >> 失败:返回-1.

说明:使用fork函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间。

地址空间:包括进程上下文,进程堆栈、打开的文件描述符、信号控制设定、进程优先级、进程组号等。

子进程中所独有的只有它的进程号,计时器等。因此,使用fork函数的代价是很大的。

子进程从fork函数调用之后执行,父进程有的全局变量,子进程也会有,但是存在不同的(独立的)地址空间

所以子进程内部对该变量的改变不会影响父进程中的同名变量。同样,父进程中的改变也不会影响子进程。

fork底层是调用了内核的函数来实现的,即先create()先创建进程,此时进程内容为空,然后clone()复制父进程的内容到子进程中,此时子进程就诞生了,接着父进程就return返回了。而子进程诞生后,是直接运行return返回的,然后接着执行后面的程序.

这里注意:子进程是不会执行前面父进程已经执行过的程序了得,因为PCB中记录了当前进程运行到哪里,而子进程又是完全拷贝过来的,所以PCB的程序计数器也是和父进程相同的,所以是从fork()后面的程序继续执行

1)分支结构如下:(多任务执行)

python fork进程执行 fork()进程创建_#include

2)fork1.c展示,子进程中变量的改变不会影响父进程中的变量 --- 独立的地址空间

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

static int num = 2;
int main(){
    int a = 10;
    pid_t pid;
    pid = fork();
    switch(pid){
    case -1:
        printf("fork error.\n");
        break;
    default:
        sleep(1);
        printf("father process: num = %d,a = %d\n",num,a);
        break;
    case 0:
        num++;
        a++;
        ++a;
        ++num;
        printf("child process: num = %d,a = %d\n",num,a);
        sleep(1);
        break;
    }
    return 0;
}

编译和运行结果如下:

python fork进程执行 fork()进程创建_#include_02

从上面的执行结果可以看出:子进程对变量所做的改变并不影响父进程中该变量的值,说明父子进程各自拥有自己的地址空间。

>>一般来说,在fork之后是父进程先执行还是子进程先执行是不确定的。这取决于内核所使用的调度算法

如果要求父子进程之间相互同步,则要求某种形式的进程间通信IPC

3)复制缓冲区,1代表标准输出的文件描述符。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(int argc,char * argv[])
{
    pid_t pid;
    int length = 0;
    char buf[] = "a write to stdout.\n";
    length = write(1,buf,strlen(buf)); //write buf to stdout
    if(length != strlen(buf)){
        printf("write error.\n");
    }
    printf("before fork.\n");
    pid = fork();
    if(pid < 0){
        printf("fork error.\n");
        perror("fork");
    }else if(pid == 0){
        printf("in son process.\n");
    }else{
        sleep(1);
        printf("in father process.\n");
    }
    return 0;
}

编译和执行结果:

python fork进程执行 fork()进程创建_子进程_03

设计模式-状态模式

1、解决

当控制一个对象状态转换的条件表达式过于复杂时的情况。

2、角色

-- 上下文环境(Context):定义客户程序需要的接口并维护一个具体状态角色的实例。

-- 抽象状态(State):定义一个接口以封装使用上下文环境的一个特定状态相关的行为。

-- 具体状态(Concrete State):实现抽象状态定义的接口。

抽象类(抽象状态),当前状态(static variable)

The State Pattern allows an object to alter its behavior when its internal state changes. The object will appear to change its class.

The pattern encapsulates state into separate classes and delegates to the object representing the current state, we know that behavior changes along with the internal state.