Linux——进程控制1|再谈fork()|fork常规用法和调用失败原因|进程终止|main函数返回值|exit和_exit|相同点|不同点 |总结 |进程等待(上)

简介: 笔记

再谈fork()


1.png

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


分配新的内存块和内核数据结构给子进程



将父进程部分数据结构内容拷贝至子进程



添加子进程到系统进程列表当中



fork返回(当return的时候),开始调度器调度


创建子进程,给子进程分配对应的内核结构,这个结构必须子进程自己独有,因为具有独立性,理论上子进程也要有自己的代码和数据,可是一般而言,我们没有加载的过程,也就是说子进程没有自己的代码和数据。所以,子进程只能使用父进程的代码和数据


代码:都是不可被写的,只能读取,父子共享没问题


数据:可能被修改,所以,必须分离。


对于数据而言创建进程的时候,就直接拷贝分,这种情况可能会拷贝一些不会用到的空间,即使用到了,也只能读取

2.png3.png

编译器编译程序的时候,尚且知道节省空间。创建子进程,不需要将不会被访问的,或者只会读取的数据,拷贝一份。将来被父或子进程写入得数据会被拷贝。一般而言即便是OS,也无法提前知道哪些空间可能会被写入。所以操作系统选择了,写时拷贝技术,将父子进程的数据分离。

4.png

fork之后代码共享,共享的是所有的代码


我们的代码汇编之后,会有很多行代码,而且每行代码加载到内存之后,都有对应的地址


当进程没执行完时候,可能被切换,下次回来,还会从之前切换的位置继续运行,所以CPU要记住这个位置,CPU中有对应的寄存器数据来记录这个当前位置

5.png

pc指针存的是当前正在执行代码的下一行代码的地址,寄存器在CPU内只有一份,但寄存器内的数据(进程的上下文数据)可以有多份


父子进程可以各自调度上下文数据,各自会修改EIP,但是已经不重要了,子进程认为自己的EIP起始值,就是fork之后的代码,子进程从after开始跑,不代表fork之前的代码它看不到


fork常规用法和调用失败原因

一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。



一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数


系统中有太多的进程



实际用户的进程数超过了限制


进程终止


1. 进程终止,操作系统都做了什么?


释放进程申请的相关内核数据结构和对应的数据和代码,本质就是释放系统资源


2.进程终止常见的方式有哪些?


a.代码跑完,结果正确           b.代码跑完,结果不正确          c.代码没有跑完,程序崩溃了(下面例子)

6.png

程序崩溃

7.png



main函数返回值

main函数的返回值并不总是0,return 后面跟的数字是进程退出码,进程退出码表示进程是否正确返回,如果返回0则运行结果正确,如果非0,则结果不正确


查看退出码:echo $?

8.png

我们把进程退出码修改为10,第一次查看退出码结果是10,之后查看结果就会是0,这是因为echo $?获取的是最近一个进程执行完毕后的退出码


main函数返回值的意义,返回给上一级进程(如父进程),用来评判该进程执行结果用的,可以忽略。


我们可以通过退出码判断出运行错误的原因,不同的退出码代表着不同的出错信息


strerror可把一个整数转换成字符串

9.png

查看退出码

10.png

我们可以看到0代表成功


11.png12.png



我们可以自己使用这些退出码和含义,我们也可以自己定义退出码和推出含义,如return 10,我们可认为10是File exists


程序崩溃的时候,退出码无意义,一般而言程序还没执行到return就会崩溃,只有main函数里的return是进程退出,其它函数return起返回作用


exit和_exit

相同点

exit

13.png

_exit

14.png



测试exit

15.png

退出码 111,说明exit在代码的任何地方调用都是直接终止进程

16.png

测试_eixt

17.png

说明exit和_exit共同之处,一执行就退出

18.png



不同点

19.png

正常运行

20.png

去掉\n,由于没了\n,就无法刷新缓冲区,也就是说要打印的内容此时存在了输出缓冲区当中,但exit此时也正常运行

21.png

我们换成_exit


22.png


此时没有打印出来,也就是_exit不会刷新缓冲区

23.png

加上\n之后,正常运行


24.png



总结

25.png

exit最后也会调用_exit, 但在调用_exit之前,还做了其他工作

1. 执行用户通过 atexit或on_exit定义的清理函数。

2. 关闭所有打开的流,所有的缓存数据均被写入


3. 调用_exit


26.png

printf不加\n数据保存在“缓冲区”当中,这个缓冲区一定不在操作系统内部,如果是操作系统维护的,缓冲区_eixt也能刷新,该缓冲区只能在库函数,如C标准库


相关文章
|
16天前
|
存储 Linux API
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
在计算机系统的底层架构中,操作系统肩负着资源管理与任务调度的重任。当我们启动各类应用程序时,其背后复杂的运作机制便悄然展开。程序,作为静态的指令集合,如何在系统中实现动态执行?本文带你一探究竟!
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
|
12天前
|
Linux
Linux:守护进程(进程组、会话和守护进程)
守护进程在 Linux 系统中扮演着重要角色,通过后台执行关键任务和服务,确保系统的稳定运行。理解进程组和会话的概念,是正确创建和管理守护进程的基础。使用现代的 `systemd` 或传统的 `init.d` 方法,可以有效地管理守护进程,提升系统的可靠性和可维护性。希望本文能帮助读者深入理解并掌握 Linux 守护进程的相关知识。
27 7
|
11天前
|
Linux Shell
Linux 进程前台后台切换与作业控制
进程前台/后台切换及作业控制简介: 在 Shell 中,启动的程序默认为前台进程,会占用终端直到执行完毕。例如,执行 `./shella.sh` 时,终端会被占用。为避免不便,可将命令放到后台运行,如 `./shella.sh &`,此时终端命令行立即返回,可继续输入其他命令。 常用作业控制命令: - `fg %1`:将后台作业切换到前台。 - `Ctrl + Z`:暂停前台作业并放到后台。 - `bg %1`:让暂停的后台作业继续执行。 - `kill %1`:终止后台作业。 优先级调整:
32 5
|
11天前
|
Linux 应用服务中间件 nginx
Linux 进程管理基础
Linux 进程是操作系统中运行程序的实例,彼此隔离以确保安全性和稳定性。常用命令查看和管理进程:`ps` 显示当前终端会话相关进程;`ps aux` 和 `ps -ef` 显示所有进程信息;`ps -u username` 查看特定用户进程;`ps -e | grep <进程名>` 查找特定进程;`ps -p <PID>` 查看指定 PID 的进程详情。终止进程可用 `kill <PID>` 或 `pkill <进程名>`,强制终止加 `-9` 选项。
20 3
|
9月前
|
监控 Linux 应用服务中间件
探索Linux中的`ps`命令:进程监控与分析的利器
探索Linux中的`ps`命令:进程监控与分析的利器
175 13
|
8月前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能
|
8月前
|
弹性计算 Linux 区块链
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
243 4
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
|
7月前
|
算法 Linux 调度
探索进程调度:Linux内核中的完全公平调度器
【8月更文挑战第2天】在操作系统的心脏——内核中,进程调度算法扮演着至关重要的角色。本文将深入探讨Linux内核中的完全公平调度器(Completely Fair Scheduler, CFS),一个旨在提供公平时间分配给所有进程的调度器。我们将通过代码示例,理解CFS如何管理运行队列、选择下一个运行进程以及如何对实时负载进行响应。文章将揭示CFS的设计哲学,并展示其如何在现代多任务计算环境中实现高效的资源分配。
|
8月前
|
存储 缓存 安全
【Linux】冯诺依曼体系结构与操作系统及其进程
【Linux】冯诺依曼体系结构与操作系统及其进程
212 1
|
8月前
|
小程序 Linux
【编程小实验】利用Linux fork()与文件I/O:父进程与子进程协同实现高效cp命令(前半文件与后半文件并行复制)
这个小程序是在文件IO的基础上去结合父子进程的一个使用,利用父子进程相互独立的特点实现对数据不同的操作
160 2