Linux 进程概念

进程

概念

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
每个进程都有自己的状态,和自己独立运行的空间。
进程需要由相关的结构体来进行管理,而在 linux 中进程是由内核中的 PCB(进程控制块) 来进行管理。OS 通过 PCB 来感知一个进程的存在。

进程与程序的区别

  1. 程序由 代码块+数据块 组成
    进程由 代码块+数据块 + PCB + 堆栈 组成,其中 由PCB 将数据粘合起来。
  2. 进程是动态的,程序是静态的。
  3. 进程的生命周期是短暂的,程序是永久的。
  4. 进程中有数据结构 PCB 。
  5. 一个进程只能对应一个程序,而一个程序可以对应多个程序。

进程状态

进程的状态:
运行态 :进程正在运行
时间片到 运行态 —> 就绪态
等待事件 运行态 —> 阻塞态
就绪态 :进程在就绪队列中
进程调度 就绪态 —> 运行态
阻塞态 :由于等待事件
等待事件到 阻塞态 —> 就绪态
死亡态 :进程结束
这里写图片描述
linux下进程状态:
在传统 linux 下有 7 种状态。
这其中状态又可以分为用户态和内核态两类。
用户态 :运行态
内核态 :运行态,就绪态,阻塞态,僵尸态,可中断睡眠状态,不可中断睡眠状态。
这里写图片描述

进程创建

因为一个正在运行的程序就是一个进程。我们在这里先运行一个程序。
这里写图片描述
我们编译运行之,然后查看之。
这里写图片描述

我们已经知道了一个正在运行的程序就是一个进程,而我们在这里需要做的是在一个进程中创建一个新的子进程。
fork 函数

pid_t fork( void );

一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。
子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程间不共享这些存储空间。

为什么 父进程和子进程返回值不同:
一个现有进程调用 fork 函数创建一个新进程,fork 函数调用一次但是返回两次。我们为了区分当前进程是父进程还是子进程,所以将 fork 的返回值设定为 父进程返回子进程的进程号,子进程返回 0。就像父亲生了儿子需要知道儿子的名字,生出来的儿子没有名字所以返回 0。
在这里我们使用代码来进行测试
这里写图片描述
运行结果
这里写图片描述
我们可以发现,其中 hehe 只输出了一次,前面我们提到,子进程是父进程的一个副本。所以我们可以发现,子进程的运行位置是 fork 的下一行。
这里写图片描述

进程等待

wait 函数

pid_t wait(int *status);
成功返回被等待进程 pid ,失败返回 -1.
status 用来获取子进程退出状态,如果不关心可以设为 NULL。

wait 函数用于使父进程阻塞,直到一个子进程结束或者该进程接收到一个指定信号。如果该父进程没有子进程或子进程已经结束,则 wait 函数会立即返回。

waitpid 函数

pid_t waitpid(pid_t pid, int *status, int options);
参数 pid > 0 等待子进程的 pid 为参数 pid 的进程死亡。
        = 0 调用者进程所在组的任何一个子进程死亡。
        = -1 等待任意一个子进程死亡。
        < -1 等待子进程为 pid 绝对值的子进程死亡。
    options WNOHANG   若指定 pid 的子进程未死亡,则不阻塞立即返回。
            WUNTRACED 为了实现某种操作,现在暂时不讨论。
            0 阻塞父进程,等待子进程退出。

实际上,wait()函数只是 waitpid()函数的一个特例,在Linux 内部实现 wait()函数时直接调用的就是waitpid()函数。

进程终止

进程的终止方式:

  • 正常退出

    • main 函数返回 (return)
    • exit 函数
    • _exit 函数
  • 异常退出

    • abort 函数
    • ctrl + c 信号终止
      在这里我们重点介绍 exit 函数和 _exit 函数。

exit 函数

void exit(int status);
// 正常终止函数
status :进程退出码,相当于 main 函数返回值。
被终止的父进程可以通过 wait 函数获取 status 低八位,来获取子进程退出信息。
exit(0) 表示正常退出,非 0 都表示非正常退出。
exit 和 return 的区别
  1. eixt 用于在程序运行中随时结束程序,并将应用程序的状态信息返回给 OS。将控制权交给 OS。
    return 是用来退出当前函数,返回函数值,并将控制权交给调用函数。
  2. exit 是系统调用级别,用来表示一个进程的结束。
    return 是语言级别,用来表示调用堆栈的返回。
  3. 在 main 函数结束时,会隐式地调用 exit 函数。exit 将删除进程所使用的内存空间,同时将信息返回给 父进程。

exit 函数在结束前会做三件收尾工作
1. 调用实现通过 atexit 或 on_exit 函数注册的退出处理函数。
2. 冲刷并关闭所有仍处于打开的标准 I/O 流。
3. 删除所有通过 tmpfile 函数创建的临时文件。

最后 exit 函数并不处理文件描述符,多进程以及进程控制。

_exit 函数

void _exit(int status);
status 进程退出码,同 exit

_exit 函数在结束前也会做三件工作,但与exit函数所做的不同。事实上,exit函数在做完它那三件收尾工作之后紧接着就会调用_exit函数。
1. 关闭所有仍处于打开的文件描述符
2. 将调用进程的子进程托付给 init 进程收养。
3. 向调用的父进程发送 SIGCHLD(17) 信号。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值