文章目录

  • 1.创建进程
    • 1.1 fork()函数初识
    • 1.2 fork()创建进程代码示例
  • 2.等待进程
    • 2.1 进程等待概念
    • 2.2进程等待必要性
    • 2.3 进程等待方法
      • 2.3.1 wait
      • 2.3.2waitpid
    • 2.4 获取子进程status
  • 3.进程终止
    • 3.1 进程退出的情况
    • 3.2 main函数用return退出进程
    • 3.3 exit函数退出
    • 3.4 _exit函数
    • 3.5 _exit()和exit()的区别

1.创建进程

1.1 fork()函数初识

在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。

pid_t fork(void);
//fork函数的头文件
#include <unistd.h>
  • 返回值:创建成功给子进程返回0,父进程返回子进程id,出错返回-1
  • 使用 fork() 函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间:包括进程上下文(进程执行活动全过程的静态描述)、进程堆栈、打开的文件描述符、信号控制设定、进程优先级、进程组号等。子进程所独有的只有它的进程号,计时器等(只有小量信息)

进程调用fork,当控制转移到内核中的fork代码后,内核(OS)做:

  • 分配新的内存块和内核数据结构给子进程
  • 将父进程部分数据结构内容拷贝至子进程(fork创建子进程是以父进程为“模板”的)
  • 添加子进程到系统进程列表当中
  • fork返回,开始调度器调度

1.2 fork()创建进程代码示例

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main(int argc, char *argv[])
{pid_t pid;pid = fork();if( pid < 0 ){  // 没有创建成功perror("fork");}if(0 == pid){ // 子进程while(1){printf("I am son\n");sleep(1);}}else if(pid > 0){ // 父进程while(1){printf("I am father\n");sleep(1);}}return 0;
}

运行结果:

2.等待进程

2.1 进程等待概念

之前说,子进程退出,父进程如果不管不顾,就可能造成“僵尸进程”的问题,进而造成内存泄露,进而,进程一旦变成僵尸状态,杀人不眨眼的”kill-9”也无能为力,因为谁也没有办法杀死一个已经死去的进程,最后,父进程派给子进程的任务完成的如何,我们需要知道,如子进程运行完成,结果是还是不对,或者是否正常退出,我们需要知道。

  • 父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息

2.2进程等待必要性

  • 子进程退出,父进程如果不处理,就可能造成僵尸进程的问题,从而导致内存泄漏。
  • 另外,进程一旦变成僵尸状态,那就刀枪不入,kill -9 也没办法杀死,因为谁也没有办法杀死一个已经死去的进程。
  • 最后,父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,或者是否正常退出。
  • 父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息。

2.3 进程等待方法

2.3.1 wait

pid_t wait(int *status)
//头文件
#include<sys/wait.h>
#include<sys/type.h>

返回值:

  • 成功:返回被等待进程(子进程)pid
  • 失败:返回-1
  • 输出型参数,获取子进程退出状态,不关心则可以设置为NULL

wait进程等待代码示例:

2.3.2waitpid

pid_t waitpid(pid_t pid,int *status,int options)
//头文件:
#include<sys/type.h>
#include<sys/wait.h>

返回值:

  • 当正常返回的时候waitpid返回收集到的子进程的进程ID
  • 如果设置了选项WNOHANG,而调用中waitpid发现已经没有已经可以退出的子进程可收集,则返回0
  • 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在

参数说明:

  • 1.pid
    pid=-1,等待任一个子进程,与wait等效
    pid>0,等待其进程ID与pid相等的子进程

  • 2.status
    WIFEXITED(status): 若为正常终止子进程返回的状态,则为真(此参数是查看进程是否是正常退出)
    WEXITSTATUS(status): 若WEXITSTATUS非零,提取子进程退
    出码(查看进程的退出码)

  • 3.options
    WNOHANG:若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待,若正常结束,则返回该子进程的ID

  • 如果子进程已经退出,调用wait/waitpid会立即返回,并且释放资源,获得子进程退出信息
  • 如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞
  • 如果不存在该子进程,则立即出错返回
  • 子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止)

waitpid进程等待代码示例:

2.4 获取子进程status

wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充
如果传递NULL,表示不关心子进程的退出状态信息,否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程

status不能简单的当作整形来看待,可以当作位图来看待,具体细节如下图(只研究status低16比特位):

正常终止:

status & 0x7f, 如果是0的话,那就表示正常退出
0xff是0111111,status按位与0x7f,表示取出status的低7位

当正常终止的时候,status高8位就是子进程的退出码
status & 0xff,就是取出status的高8位

异常终止:

status & 0x7f, 不为0的话,那就表示异常退出

代码示例:

3.进程终止

3.1 进程退出的情况

  1. 代码跑完了,结果正确
  2. 代码跑完了,结果不正确
  3. 代码没跑完,程序异常终止

正常终止(可以通过 echo $? 查看最近一次进程退出码):

  1. 从main返回
  2. 调用exit / _exit

异常退出:

  1. ctrl + c,信号终止

3.2 main函数用return退出进程

main函数退出时, return的数字就是程序的退出码。 问题: 为什么main的return一般会写成0?
因为0在函数设计中,一般代表正确。非0代表错误。

#include <iostream>
#include <unistd.h>
#include <sys/types.h>using namespace std;int main()
{cout << "hello" << endl;return 0;//退出码为0
}

3.3 exit函数退出

void exit(int status);
//头文件
#include <unistd.h>
  • exit:终止整个进程,任何地方都会调用,都会终止
  • return:终止函数。main函数return 代表进程退出

3.4 _exit函数

void _exit(int status);
//头文件
#include <unistd.h>
  • 参数:status 定义了进程的终止状态,父进程通过wait来获取该值
  • 说明:虽然status是int,但是仅有低8位可以被父进程所用。所以_exit(-1)时,在终端执行$?发现返回值是255。

代码示例:

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>using namespace std;int exe()
{_exit(12);return 12;}int main(){cout << "you should running here!";                                                    sleep(5);//sleep5秒exit(13);                            return 0;//退出码为0                 }

3.5 _exit()和exit()的区别

  1. 最大的区别是 exit()函数在调用 _exit() 系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件 (即刷新缓冲区), 然后将控制权交给内核 . _exit() 则是执行后立即返回给内核,而exit()要先执行一些清除操作
  2. 调用_exit函数时,会关闭进程所有的文件描述符,清理内存以及其他一些内核清理函数,但不会刷新缓冲区, exit函数是在_exit函数之上的一个封装,其会调用_exit,并在调用之前先刷新缓冲区。
  • 补充: exit()函数在调用exit系统之前要检查文件的打开情况,把文件缓冲区的内容写回文件。由于Linux的标准函数库中,由于内存中都有一片缓冲区. 每次读文件时,会连续的读出若干条记录,这样在下次读文件时就可以直接从内存的缓冲区读取. 同样,每次写文件的时候也仅仅是写入内存的缓冲区,等满足了一定的条件(如达到了一定数量或遇到特定字符等),再将缓冲区中的内容一次性写入文件。这种技术大大增加了文件读写的速度,但也给编程代来了一点儿麻烦。比如有一些数据,认为已经写入了文件,实际上因为没有满足特定的条件,它们还只是保存在缓冲区内,这时用_exit()函数直接将进程关闭,缓冲区的数据就会丢失。因此,要想保证数据的完整性,就一定要使用exit()函数

Linux_进程控制(创建进程,等待进程,进程终止)相关推荐

  1. Linux 进程控制(创建/退出/等待/替换)

    目录 进程创建 fork()函数 fork返回值 fork写时拷贝 fork失败原因 fork用法 进程退出 退出场景 常见的退出方法 正常退出 异常退出 _exit()系统调用 exit()函数 _ ...

  2. 进程控制(2):进程操作

    前言: 关于进程控制这块的好文很多,下面转载的这篇内容很丰富,也会举适当的栗子,与其写的一知半解不如参读学习别人的优秀博文,感谢原作,本系列摘录自:https://www.cnblogs.com/xi ...

  3. 进程控制-创建、退出、等待、替换

    目录 进程创建 1.子进程继承 2.写时拷贝 进程退出 echo $? 退出码 进程异常退出的情况模拟: 退出进程的方式 退出码的意义: 进程退出,在系统中发生了什么? 进程等待 为什么要有进程等待呢 ...

  4. 【Linux】进程控制(创建、终止、等待)

    环境:centos7.6,腾讯云服务器 Linux文章都放在了专栏:[Linux]欢迎支持订阅 相关文章推荐: [Linux]冯.诺依曼体系结构与操作系统 [Linux]进程理解与学习Ⅰ-进程概念 [ ...

  5. 进程控制——创建,终止

    目录 1.进程的创建 fork函数初识 fork函数返回值 写时拷贝 fork常规用法 2.进程终止 进程退出场景 进程常见退出方法 进程退出返回值的意义: 1.进程的创建 fork函数初识 在lin ...

  6. 【Linux】进程控制2-进程等待

    文章目录 进程等待 进程等待的必要性 wait函数 waitpid函数 进程等待 进程等待的必要性 我们之前提到过僵尸进程,僵尸进程就是子进程先于父进程退出,子进程的退出状态信息发送给父进程但是父进程 ...

  7. 实验2linux进程控制与通信,实验2 进程控制与通信管理word文档良心出品

    <实验2 进程控制与通信管理word文档良心出品>由会员分享,可在线阅读,更多相关<实验2 进程控制与通信管理word文档良心出品(13页珍藏版)>请在人人文库网上搜索. 1. ...

  8. linux下进程的创建代码,Linux下进程创建分析

    如何创建一个进程? 子进程拷贝父进程的代码和数据,进程拥有自己的独占资源(写时拷贝),父,子进程共享代码区,不共享数据区(私有化) 当使用pid_t fork(void)创建进程时,若创建成功,给父进 ...

  9. 【Linux】linux进程--进程控制:进程创建、进程终止、进程等待、进程程序替换

    目录 1.进程创建 1)重温fork():让正在运行的进程创建出来一个子进程:从已存在的进程中创建一个新的进程,新进程为子进程而远进程为父进程. 2)fork内部完成的事情 3)用户空间 & ...

最新文章

  1. 一些实用的注册表封装类
  2. Python Dict用法
  3. ThreadLocal源码剖析
  4. iOS开发篇——赋值语句介绍(C++)
  5. php 伪静态 500错误,Apache开启伪静态后报500错误.
  6. [react-router] React-Router怎么设置重定向?
  7. 软件测试要求太高,软件“故障门”频现 对软件测试提出更高要求
  8. 关于struts线程问题 转
  9. ANSI C和Glib C区别(二)
  10. 【转】对 Rust 语言的分析
  11. 使用rem单位布局的时候有什么好处_好程序员web前端技术分享移动端页面布局
  12. ubuntu固定ip地址
  13. Ubuntu 更改鼠标滚轮速度
  14. 机器周期、指令周期、时钟周期、总线周期
  15. python学员管理系统
  16. Substance Designer中Histogram相关节点理解
  17. _search.php_wholesale_search.php
  18. 清华、商汤提出SIM方法,让自监督学习兼顾语义对齐与空间分辨能力
  19. fnl数据下载之requests,urllib等安装
  20. 可视化,市场分析表Excel模板,财务统计EXCEL模版,人员变动EXCEL模版,销量完成度Excel模板

热门文章

  1. 413 request entity too large php,413 Request Entity Too Large
  2. 通过云服务器对内网穿透实现外网访问群晖NAS
  3. Lawnmower E题
  4. 计算机执行管理任务时,管理Active Directory用户和计算机
  5. bzip2格式文件解压
  6. windows MNN 的使用流程(Python版)
  7. Linux下查看CPU核数
  8. CSS层叠样式表(Cascading Style Sheets)
  9. 国产自研开源大数据管理平台DataSophon Manager安装教程
  10. 使用XUnit的测试驱动开发过程