【操作系统】进程的创建与销毁

9

进程

程序和进程

程序就是一堆指令和数据的集合,这个集合反映在了一个静态可执行文件和相关的配置文件等。

操作系统可以运行多个程序。实际上,CPU的执行是很快的,而待运行的程序很多,那么为了让操作系统运行多个程序,CPU会把它的执行时间划分成很多段,比如每一段是0.1秒,那么就可以这样A程序运行0.1秒,然后B程序运行0.1,然后C程序运行0.2秒,因为这个切换很快,所以我们感觉程序是同时运行的。

从操作系统上来看,运行程序就指的是一个进程,因为存在切换,所以进程管理了很多资源,比如:打开的文件、挂起的信号、进程状态、内存地址空间等等,也就是说进程参与了CPU的调度,管理了所有资源。

更详细的来说,现代计算机的CPU执行速度非常快,使用一个进程参与调度时,频繁地从CPU的寄存器和进程堆栈的保存运行状态和对应的信息都很耗时,所以现代CPU将进程仅仅作为一个资源管理的东西,而引入线程作为CPU调用的基本单位,多个线程可以共享同一进程的所有资源。

要注意的是,程序并不是进程,实际上两个或多个进程不仅有可能执行同一程序,而且还有可能共享地址空间等资源。

Linux内核通过一个被称为进程描述符的task_struct结构体来管理进程,这个结构体包含了一个进程所需的所有信息。它定义在/include/linux/sched.h中。


创建进程

fork()

#include <unistd.h>
#include <stdio.h>
int main()
{
    pid_t fpid;//fpid接收fork函数返回的值
    int count=0;
    fpid=fork();
    if (fpid < 0)
        printf("error in fork!");
    else if (fpid == 0) {
        printf("i am the child process, my process id is %d\n",getpid());
        printf("I’m children\n");
        count +=2;
    }
    else {
        printf("i am the parent process, my process id is %d/n",getpid());
        printf("I’m parent.\n");
        count++;
    }
    printf("统计结果是: %d\n",count);
    return 0;
}

image-20220806164102224

说明:

调用fork后,会创建一个子进程,父子进程都从fork处开始执行,fork函数有两个返回值,父进程会返回子进程的pid>0,子进程pid=0。

传统的linux操作系统以统一的方式对待所有的进程,子进程复制父进程所拥有的所有资源,这种方法使得创建进程非常慢,因为子进程需要拷贝父进程的所有的地址空间。

现代的操作系统,主要以下如下三种方式进行处理:

  • 写时复制(需要不同的值)。
  • 轻量级进程允许父子进程共享每进程在内核的很多数据结构,比如地址空间、打开文件表和信号处理。
  • vfork系统调用创建的进程能共享其父进程的内存地址空间,为了防止父进程重写子进程需要的数据,阻塞父进程的执行,一直到子进程退出为止。

销毁进程

exit()

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

int main()
{
    pid_t fpid;//fpid接收fork函数返回的值
    int count=0;
    int status = 0;

    fpid=fork();
    if (fpid < 0)
        printf("error in fork!\n");
    else if (fpid == 0) {
        printf("i am the child process, my process id is %d\n",getpid());
        printf("I’m children\n");
        count +=2;
        exit(-10);
    }
    else {
        printf("i am the parent process, my process id is %d\n",getpid());
        printf("I’m parent.\n");
        count++;
    }
    printf("统计结果是: %d\n",count);
    //父进程捕捉子进程的状态
    wait(&status);
    printf("parent: status: %d\n", WEXITSTATUS(status));
    return 0;
}

image-20220806165256761