【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-进程创建、进程终止 的相关文章

  • 如何修复“iptables:没有该名称的链/目标/匹配”?

    我在我的 Linux 嵌入式系统上构建并安装了 iptables 如果我列出所有规则 则一切正常 iptables list Chain INPUT policy ACCEPT target prot opt source destinat
  • 何时使用 pthread 条件变量?

    线程问题 看来 只有在其他线程调用 pthread cond notify 之前调用 pthread cond wait 时 条件变量才起作用 如果在等待之前发生通知 那么等待将被卡住 我的问题是 什么时候应该使用条件变量 调度程序可以抢占
  • Elasticsearch 无法写入日志文件

    我想激活 elasticsearch 的日志 当我运行 elasticsearch 二进制文件时 我意识到我在日志记录方面遇到问题 无法加载配置 这是输出 sudo usr share elasticsearch bin elasticse
  • 在 Linux 上更快地分叉大型进程?

    在现代 Linux 上达到与 Linux 相同效果的最快 最好的方法是什么 fork execve combo 从一个大的过程 我的问题是进程分叉大约 500MByte 大 并且一个简单的基准测试只能从进程中实现约 50 个分叉 秒 比较最
  • 强制卸载 NFS 安装目录 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案
  • Linux 中的无缓冲 I/O

    我正在写入大量的数据 这些数据数周内都不会再次读取 由于我的程序运行 机器上的可用内存量 显示为 空闲 或 顶部 很快下降 我的内存量应用程序使用量不会增加 其他进程使用的内存量也不会增加 这让我相信内存正在被文件系统缓存消耗 因为我不打算
  • 如何检测并找出程序是否陷入死锁?

    这是一道面试题 如何检测并确定程序是否陷入死锁 是否有一些工具可用于在 Linux Unix 系统上执行此操作 我的想法 如果程序没有任何进展并且其状态为运行 则为死锁 但是 其他原因也可能导致此问题 开源工具有valgrind halgr
  • 仅打印“docker-container ls -la”输出中的“Names”列

    发出时docker container ls la命令 输出如下所示 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a67f0c2b1769 busybox tail f dev
  • 如何禁用 GNOME 桌面屏幕锁定? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何阻止 GNOME 桌面在几分钟空闲时间后锁定屏幕 我已经尝试过官方手册了在红帽 https access redhat com doc
  • Jenkins中找不到环境变量

    我想在詹金斯中设置很多变量 我试过把它们放进去 bashrc bash profile and profile of the jenkins用户 但 Jenkins 在构建发生时找不到它们 唯一有效的方法是将所有环境变量放入Jenkinsf
  • 如何在 shell 脚本中并行运行多个实例以提高时间效率[重复]

    这个问题在这里已经有答案了 我正在使用 shell 脚本 它读取 16000 行的输入文件 运行该脚本需要8个多小时 我需要减少它 所以我将其划分为 8 个实例并读取数据 其中我使用 for 循环迭代 8 个文件 并在其中使用 while
  • 在哪里可以找到并安装 pygame 的依赖项?

    我对 Linux 比较陌生 正在尝试安装 python 的 pygame 开发环境 当我运行 setup py 时 它说我需要安装以下依赖项 我找到并安装了其中之一 SDL 然而 其他人则更加难以捉摸 Hunting dependencie
  • 使用 sed 更新 xml 属性(Windows + cygwin 和 Linux)?

    我需要使用 sed 命令对 xml 文件进行更新 但我在这方面遇到了麻烦 它需要在 Windows 使用 cygwin 和 Linux 上运行 XML 具有以下元素
  • 域套接字“sendto”遇到“errno 111,连接被拒绝”

    我正在使用域套接字从另一个进程获取值 就像 A 从 B 获取值一样 它可以运行几个月 但最近 A 向 B 发送消息时偶尔会失败 出现 errno 111 连接被拒绝 我检查了B域套接字绑定文件 它是存在的 我也在另一台机器上做了一些测试 效
  • nslookup 报告“无法解析 '(null)': 名称无法解析”,尽管它成功解析了 DNS 名称

    我在 ubuntu 上 并且正在运行 docker 默认桥接网络 我有 Zookeeper kafka 的容器化版本 以及我编写的与 kafka 对话的应用程序 I do a docker exec it
  • 两种情况或 if 哪个更快? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我必须制作一个 非常 轻的脚本 它将接受用户的选项并调用脚本中的函数来执行一些任务 现在我可以使用 IF 和 CASE 选项 但我想知道两
  • Pyaudio 安装错误 - “命令‘gcc’失败,退出状态 1”

    我正在运行 Ubuntu 11 04 Python 2 7 1 并想安装 Pyaudio 于是我跑了 sudo easy install pyaudio 在终端中 进程退出并显示以下错误消息 Searching for pyaudio Re
  • Linux 内核标识符中前导和尾随下划线的含义是什么?

    我不断遇到一些小约定 比如 KERNEL Are the 在这种情况下 是内核开发人员使用的命名约定 还是以这种方式命名宏的语法特定原因 整个代码中有很多这样的例子 例如 某些函数和变量以 甚至 这有什么具体原因吗 它似乎被广泛使用 我只需
  • Linux:在文件保存时触发 Shell 命令

    我想在修改文件时自动触发 shell 命令 我认为这可以通过注册 inotify 挂钩并调用来在代码中完成system 但是是否有更高级别的 bash 命令可以完成此任务 尝试 inotify 工具 我在复制链接时遇到问题 抱歉 但 Git
  • Linux 可执行文件与 OS X“兼容”吗?

    如果您在基于 Linux 的平台上用 C 语言编译一个程序 然后将其移植以使用 MacOS 库 它会工作吗 来自编译器的核心机器代码在 Mac 和 Linux 上兼容吗 我问这个问题的原因是因为两者都是 基于 UNIX 的 所以我认为这是真

随机推荐

  • 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函数让正在运行的进程创建出来一