【Linux】进程控制1-进程创建、进程终止

2023-11-15

进程创建

fork函数

调用fork函数让正在运行的进程创建出来一个子进程。得到的新进程为子进程,而原进程为父进程。

pid_t fork(void)

fork函数有两个返回值,如果创建成功,那么返回给父进程一个大于0的值,即子进程的进程号,返回给子进程数字0,如果创建失败,那就给父进程返回-1,父子进程是独立的进程,fork分别在父子进程当中进行返回,由于父子进程返回不同的值,且相互独立,我们可以通过返回值来让父子进程执行不同的代码。
我们来简单看一下正在运行的父进程创建子进程的代码,试验一下:
在这里插入图片描述
运行结果:
在这里插入图片描述

观察数字,我们可以给出一个经验,一般来说,子进程的pid比父进程小1。

fork内部完成的事情:

  • 创建子进程,子进程拷贝父进程的PCB
  • 分配新的内存块和内核数据结构(task_struct)给子进程
  • 将父进程部分数据结构内容拷贝给子进程
  • 添加子进程到系统进程列表当中,添加到双向链表里当中
  • fork返回,操作系统开始进行调度,调度的时候遵循以下原则:先来先服务、短作业优先、优先级优先、时间片轮转等

用户空间、内核空间

内核空间:Linux操作系统和驱动程序运行在内核空间。系统调用的函数都是运行在内核空间的,因为是操作系统提供的函数。
用户空间:应用程序都是运行在用户空间的,应用程序属于程序员自己写的代码,程序员自己写的代码都是运行在用户空间的。
当程序员写的代码中调用了系统调用函数,就会从用户空间切换到内核空间去执行系统调用函数,执行完之后再次回到用户空间继续执行程序员写的代码。

写实拷贝

fork创建子进程的时候,子进程会拷贝父进程的PCB,页表也会拷贝父进程的。所以同一个变量的的虚拟地址和物理地址的映射关系在父进程和子进程中是一样的,也就是说,操作系统并没有给子进程当中的变量在物理内存当中分配内存空间进行存储,子进程的变量还是父进程的物理地址当中的内容。

当子进程中的变量发生改变时,才会以写实拷贝的方式进行拷贝,也就是分配物理内存,此时父子进程通过各自的页表,指向不同的物理地址。
当子进程中的变量不发生改变时,父子进程共享一个数据,这样子有一个明显的好处就是节省内存空间。

在这里插入图片描述

执行结果:

在这里插入图片描述

fork创建子进程时的一些特性

  • (进程独立性)父子进程相互独立,互不干扰。各自有各自的进程虚拟地址空间和映射页表,不能访问对方的数据
  • 父子进程独立被操作系统调度,父子进程是抢占式执行,父子进程先后执行顺序本质是由操作系统调度决定的,不过进程自身情况也会影响执行先后顺序
  • 子进程是从fork之后开始运行
  • 代码共享,数据独有

守护进程

父进程创建子进程,通过进程程序替换,让子进程执行真正的业务,父进程负责守护子进程,子进程和父进程之间进行进程间通信,当父进程检测到子进程异常的时候,父进程就会重新启动子进程(再创建一个子进程),让子进程继续提供服务。
守护进程是提高“高可用”的一种手段。

进程终止

进程终止有两种场景,正常终止和异常终止。
正常终止又有两种情况:代码运行完毕,完成了既定的代码功能;代码运行完毕,但是没有完成既定的功能。

正常终止

可以通过命令“echo $?”查看进程退出码

正常终止有下面三种情况:

  • 1、从main函数的return返回

在这里插入图片描述

我们查看一下进程退出码:

在这里插入图片描述

这种情况下,进程退出码就是return返回的值,我们修改一下return后面的值,就会发现进程退出码也会改变。

在这里插入图片描述

查看一下进程退出码:

在这里插入图片描述

  • 2、调用exit函数(库函数)

在这里插入图片描述

调用exit函数之后,就会直接退出进程了,所以上面的代码查看进程退出码就是2不是1了,因为后面的打印和return 0 都不会执行。

在这里插入图片描述

  • 3、调用_exit函数(系统调用函数)

在这里插入图片描述

在这里插入图片描述

异常终止

  • 1、解引用空指针,解引用野指针(垂悬指针)
    在这里插入图片描述
    执行结果:
    在这里插入图片描述
    产生了段错误,进程异常终止,此时会产生一个核心转储文件,我们来看一看:
    在这里插入图片描述
    看不到核心转储文件,这是为什么呢?因为core file size的-c的位置是0,有限制,我们修改一下:
    在这里插入图片描述
    现在就能产生核心转储文件了,再执行一次,就能看到产生的核心转储文件了。
    在这里插入图片描述
    我们看一下这个coredump文件的这个段错误的信息:
    在这里插入图片描述
  • 2、double free

对一块空间释放两次,会引起进程的异常终止,也会产生coredump文件。

在这里插入图片描述

执行产生了错误:

在这里插入图片描述

  • 3、内存访问越界

进程内存访问越界的时候,会被操作系统强杀。

exit和_exit的区别

exit函数_exit函数两者最大的区别就是exit函数会比_exit函数多了两个步骤:执行用户定义的清理函数、冲刷缓冲,关闭流等。

  • 1、执行用户自定义的清理函数
    在这里插入图片描述

void (*function)(void) 这是一个函数指针

指针函数:本质是一个函数,返回值是指针,也就是说,指针函数就是返回值为指针的函数。
函数指针:本质是一个指针,指向代码段中函数入口地址,(*function) 是一个整体,代表的是指向该函数的指针,(function) 是函数指针变量,函数名就是函数的入口地址,所以函数指针变量就是函数名。

atexit是注册函数指针保存的函数地址到内核当中去,注册这个函数并不是调用这个函数。所以下面这段代码中,atexit注册了atexit_callback函数,但是并没有调用执行,而是在整个进程结束之后,进行回调,所以才有了这样子的执行结果。

4 void atexit_callback(){                                                                        
  5   printf("I am atexit_callback,hhhh.\n");
  6 }
  7 int main(){
  8   atexit(atexit_callback);
  9   printf("hello world.\n");
 10   return 0;
 11 }

执行结果:

在这里插入图片描述

当程序达到了某种固定的场景的时候,会进行回调,调用的函数被称为回调函数。

  • 2、刷新缓冲区
printf("hello world.\n");

“hello world”并不是直接被打印到屏幕上面的,而是先被放入缓冲区,再刷新缓冲区到屏幕上。

换行符可以刷新缓冲区、从main函数的return返回可以刷新缓冲区、exit函数、fflush函数(强制刷新缓冲区)这几种方式都可以刷新缓冲区。
在这里插入图片描述

#include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 int main(){
  5   printf("hello world");
  6   fflush(stdout);                                                                              
  7   _exit(2);
  8   int count = 5;
  9   while(count){
 10     sleep(1);
 11     count--;
 12   }
 13   return 0;
 14 }

缓冲方式

  • 全缓冲:缓冲区写满再进行IO
  • 行缓冲:输入和输出遇到换行符的时候,标准I/O库执行I/O操作,也就是说,一行写满就进行刷新。
  • 不缓冲:不带缓冲,标准I/O库不对字符进行缓冲存储,也就是说放入缓冲区后立即就刷新出来。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Linux】进程控制1-进程创建、进程终止 的相关文章

  • 应用程序中两个不同版本的库

    考虑一个场景 其中有两个不同版本的共享库 考虑 A 1 so 链接到 B so A 2 so 链接到 C so 现在 B so 和 C so 都链接到 d exe 当 B so 想要调用 A 1 so 中的函数时 它最终会调用 A 2 so
  • 如何在Linux上用C/C++编写Web服务器[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在考虑在 Linux 平台上开发一个小型 阅读 初级 Web 服务器 但我不知道从哪里开始 我希望它能够做的是 监听特定端口 接受
  • 任何退出 bash 脚本但不退出终端的方法

    当我使用exitshell 脚本中的命令 该脚本将终止终端 提示符 有什么方法可以终止脚本然后停留在终端中吗 我的剧本run sh预计通过直接获取或从另一个脚本获取来执行 编辑 更具体地说 有两个脚本run2 sh as run sh ec
  • 在ubuntu中打开spyder

    我想在ubuntu中打开spyder Python IDE 通常我会在 shell 中编写 spyder 它会打开spyder IDE 现在 当我在shell中编写spyder时 它只是换行 什么也没有发生 类似于按 enter 我如何找回
  • MySQL 与 PHP 的连接无法正常工作

    这是我的情况 我正在尝试使用 Apache 服务器上的 PHP 文件连接到 MySQL 数据库 现在 当我从终端运行 PHP 时 我的 PHP 可以连接到 MySQL 数据库 使用 php f file php 但是当我从网页执行它时 它只
  • Crontab 每 5 分钟一次 [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我如何告诉 crontab 每 5 分钟运行一次 但从每小时的第二分钟开始 换句话说 我想在以下时间执行我的脚本minute 5 2 例如 我的脚本应
  • 正则表达式删除块注释也删除 * 选择器

    我正在尝试使用 bash 从 css 文件中删除所有块注释 我有以下 sed 命令的正则表达式 sed r s w s w d 这可以很好地去除块注释 例如 This is a comment this is another comment
  • 如何从 C++ 程序中重新启动 Linux?

    我有一个 Qt 4 GUI 我需要在下拉菜单中提供一个选项 允许用户选择重新启动计算机 我意识到这对于以其他方式重新启动计算机的能力来说似乎是多余的 但选择需要保留在那里 我尝试使用 system 来调用以下内容 suid root she
  • Python 3.4.3 subprocess.Popen 在没有管道的情况下获取命令的输出?

    我试图将命令的输出分配给变量 而不让命令认为它正在通过管道传输 原因是 如果正在通过管道传输 则相关命令会给出未格式化的文本作为输出 但如果从终端运行 则会给出颜色格式化的文本 我需要获取这种颜色格式的文本 到目前为止我已经尝试了一些事情
  • 在汇编中使用 printf 会导致管道传输时输出为空,但可以在终端上使用

    无输出 https stackoverflow com questions 54507957 printf call from assembly do not print to stdout即使在终端上 当输出不包含换行符时也有相同的原因
  • 如何在线程创建和退出时调用函数?

    include
  • 为什么 fork 炸弹没有使 android 崩溃?

    这是最简单的叉子炸弹 我在许多 Linux 发行版上执行了它 但它们都崩溃了 但是当我在 android 终端中执行此操作时 即使授予后也没有效果超级用户权限 有什么解释为什么它没有使 Android 系统崩溃吗 一句话 ulimit Li
  • 如何在不使用 IDE 的情况下在 Linux 上运行 Java 项目

    我是 Java 新手 基本上 我开发了一个java项目 其中包含Eclipse中的多个Java包 该项目在我安装了 redhat Linux 的桌面上运行正常 然而 我需要在一个更强大的没有安装X11的Linux服务器 redhat ent
  • SSH,运行进程然后忽略输出

    我有一个命令可以使用 SSH 并在 SSH 后运行脚本 该脚本运行一个二进制文件 脚本完成后 我可以输入任意键 本地终端将恢复到正常状态 但是 由于该进程仍在我通过 SSH 连接的计算机中运行 因此任何时候它都会登录到stdout我在本地终
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • 在 C 中使用单个消息队列是否可以实现双向通信

    我希望服务器向客户端发送一些消息 并让客户端确认它 我被分配了这个任务 我可以在 C linux 中使用单个消息队列来完成它还是我需要创建两个 谢谢 是的 可以使用 sysV 消息队列来做到这一点 从您之前的问题来看 您正在使用该队列 您可
  • linux下无法创建僵尸进程

    嗯 我有一个奇怪的问题 我无法在我的项目中创建僵尸进程 但我可以在其他文件中创建僵尸进程 有简单的说明 int main if fork 0 printf Some instructions n else sleep 10 wait 0 r
  • 调用 printf 系统子例程在汇编代码中输出整数错误[重复]

    这个问题在这里已经有答案了 来回 在windows7控制台窗口中运行gcc s2 asm 然后生成一个exe文件 运行a exe 然后崩溃 为什么 s2 asm 代码由以下源代码生成 int m m 1 iprint m s2 asm请参考
  • docker 非 root 绑定安装权限,WITH --userns-remap

    all 尝试让绑定安装权限正常工作 我的目标是在容器中绑定安装卷 以便 a 容器不以 root 用户身份运行入口点 二 docker daemon 配置了 userns remap 这样容器 主机上没有 root c 我可以绑定挂载和读 写
  • 如何为 Linux 桌面条目文件指定带有相对路径的图标?

    对于我的一个 Linux 应用程序 我有应用程序二进制文件 一个 launcher sh 脚本 针对 LD LIBRARY PATH 和一个 desktop 文件 所有这些都位于同一文件夹中 我想使用图标的相对路径而不是绝对路径 我试过了

随机推荐

  • foreach用法_R语言--并行计算包(parallel、foreach)

    R语言是单核计算语言 在数据建模或计算过程中 常常出现相同或相似任务的重复计算 一般操作是for循环处理或采用apply族函数处理 为了更快完成计算 采用并行计算是更优的选择 本文采用R语言中的parallel包与foreach包实现并行计
  • ueditor-后台配置项返回格式出错,上传功能将不能正常使用!

    一 服务器环境 php centos apache 二 症状 ueditor编辑界面可以显示 但单图片上传按钮点击没反应 多图片上传显示 后台配置项返回格式出错 上传功能将不能正常使用 三 分析 1 打开浏览器调试模式 显示 后台配置项返回
  • Zookeeper——zookeeper基础

    在深入了解ZooKeeper的运作之前 让我们来看看ZooKeeper的基本概念 我们将在本章中讨论以下主题 Architecture 架构 Hierarchical namespace 层次命名空间 Session 会话 Watches
  • 剑指 Offer 06. 从尾到头打印链表

    从尾到头打印链表 蠢想法 解题思路 的节点顺序已经反转过来了 栈 package swordPointingToTheOffer import java util Stack 引用栈 public class six 初始化 Stack
  • MessageBoxA的用法

    一 函数原型 int fastcall MessageBox const char Text const char Caption int Flags 0x0 Flags表示对话框的按钮组合 取值有 MessageBox Flags def
  • 虚拟地址内存空间

    bss段详解 详细讲解
  • 一个简单的HttpClient使用案例

    HttpClient 是什么 HttpClient 是Apache Jakarta Common 下的子项目 可以用来提供高效的 最新的 功能丰富的支持 HTTP 协议的客户端编程工具包 并且它支持 HTTP 协议最新的版本和建议 该如何使
  • Web3-js的学习(5)-实现合约事件监听

    合约事件监听 latest 监听最新出块事件 pending 监听发布未进块事件 代码很简单 var Web3 require web3 var web3 new Web3 new Web3 providers HttpProvider h
  • 解决在Intellij IDEA中无法创建Servlet类的问题/New中没有Servlet类/创建不了Servlet类

    新手在学习Servlet相关知识的时候 一些课程往往会告知新手去使用IDEA自带的模板来创建Servlet 这样减少了注解等麻烦 降低了工作量 然而 如下图所示 很多人发现在自己的new一栏不存在Servlet类 如下图 网上的解决办法很多
  • 服务 -web服务器及ssh

    web服务器 文件共享 nfs samba 一般用于局域网中 ftp http 一般用于公网 tcp 80 httpd apache 1 完全开源 2 跨平台 3 支持多种编程语言 4 采用模块化的设计 5 安全稳定 IE www taob
  • 笔记/samba搭建

    1 安装 yum y install samba 2 配置 vim etc samba smb conf global 安全模式 user shared domain security user 认证模式 passdb backend td
  • autosar宏定义搜集

    1 AUTOSAR 长函数声明 2 教你如何阅读Autosar代码 1 概述 3 把AUTOSAR函数以及变量等定义的宏用脚本展开以提高可读性 4 Specification of Compiler Abstraction autosar
  • C语言满天星加月亮

    import java awt Color import java awt Graphics import javax swing JFrame import javax swing JPanel public class Stars pu
  • C++关键字 noexcept

    1 关键字noexcept 从C 11开始 我们能看到很多代码当中都有关键字noexcept 比如下面就是std initializer list的默认构造函数 其中使用了noexcept constexpr initializer lis
  • 使用JAVA反射的利与弊

    b color olive size large 在Java的20周年的纪念日的日子里 让我们来重新温习下Java里面的高级知识 Java肯定希望大家了解她 要不然你跟她天天相濡以沫了这么长时间 让她知道你竟然不了解她 不在乎她 那么她该有
  • wsus服务器搭建自动更新

    WSUS服务器搭建 第一次写博客还有点小激动 没有啥过硬的技术手段 简单记录一下日常操作 整一个Windows 2012 Server镜像文件 简单说一下为啥我找的是win 2012 Server吧 微软好像发布了个停止对Windows S
  • SearchView详细使用

    Android SearchView详细使用 布局
  • 在Fedora16中安装Qt

    首先 在http www trolltech com download上下载linux下的qt源文件 我下载时最新版是 qt everywhere opensource src 4 7 4 tar gz 将该文件放到某个目录下 进行解压缩
  • conda常用命令汇总

    conda常用命令汇总 1 创建一个虚拟环境 conda create name pytorch gpu python 3 8 创建一个名为pytorch gpu 可自定义 的虚拟环境 3 8指的是所安装python版本 2 进入一个已经存
  • 【Linux】进程控制1-进程创建、进程终止

    文章目录 进程创建 fork函数 用户空间 内核空间 写实拷贝 fork创建子进程时的一些特性 守护进程 进程终止 正常终止 异常终止 exit和 exit的区别 缓冲方式 进程创建 fork函数 调用fork函数让正在运行的进程创建出来一