Linux Day07

一、僵死进程

1.1僵死进程产生的原因

       子进程先于父进程结束, 而父进程没有获取子进程退出码,释放子进程占用的资源,此时子进程将成为一个僵死进程。

在第一个框这里时父进程子进程都没有结束,显示其pid 父进程是2349,子进程是2350

在第二个框这里时父进程没有结束,子进程结束,因此显示父进程的pid,但是因为父进程没有获取子进程的退出码,子进程就处于僵死状态<defunct>

第三个框这里父进程结束,父进程成功获取子进程的退出码,子进程结束。

1.2 PCB消失的条件

       获取到退出码,子进程要父进程获取子进程的退出码才能完全结束。


1.3危害

        占用资源空间。如果进程不调用wait/waitpid,那么保留的那段信息就不会被释放,其进程号就会一 直被占用,但是系统能使用的进程号是有限的,如果产生大量的僵死进程,将因为没有可用的进程号而 导致系统不能产生新的进程。

1.4 如何处理

1.父进程调用wait()方法获取子进程的退出码

wait(&val):执行该指令,会将子进程的退出码填到val中。

结果:

这个时候我们不难发现:先打印的都是子进程,父进程一点都没有打印,当子进程结束才开始父进程,等val退出码打印后才开始。

原因:wait,即先阻塞父进程,直至子进程运行结束,父进程获取到子进程的退出码后,父进程才继续运行。


wait(&val):返回值pid_t,调用函数后会将退出码通过指针赋值到val上。
WIFEXITED(val):由于退出码为1字节,val为4字节,通过该函数可以将其转化为1字节,返回值为bool类型,判断进程是否正常结束。
WEXITSTATUS(val):获取进程退出状态。

2.父进程先结束----孤儿进程

结果

 在父进程结束后出现了提示符,但是此时子进程还没有结束,所以还在执行

第一个框,父进程的id为2621,他的父进程是2135,子进程的id为2622,他的父进程为2621

父进程结束后,会随机为子进程分配一个父进程,该父进程的id为1536,收养了这个孤儿进程

注意:老版本是 init进程,其进程号为1,新版本是随机分配一个系统进程

init进程一定会对子进程执行wait()指令,获取子进程的退出码,子进程的pcb被操作系统删除,至此子进程彻底结束。

1.5 练习

1.5.1  练习一

结果

原因

板块一:此时i=0,执行fork语句生成板块2,打印第一个A,此时i++变成1,然后继续循环,执行fork语句,生成板块3(板块三的i是从1开始的),打印第二个A,i++变成2,结束板块一

板块三:因为是子进程,从fork语句后执行,打印第一个A,i++变成2,结束板块三

板块二:也是子进程,从fork语句后执行,打印第一个A,i++变成1,继续循环,执行fork语句生成板块四(板块四的i是从1开始的),打印第二个A,i++变成2,结束板块二。

板块四:也是子进程,打印第一个A,i++变成 2,结束板块2.

总计:6个A

 1.5.2 练习二

 

结果

原因

注意一点:fork()执行完后,子进程从fork语句后执行

第一个板块:执行fork语句生成板2,此时将打印的A放在缓冲区,为什么呢?可以看下linux day06讲printf这块,此时i++变成1,继续循环,执行fork语句生成板块3,(注意板块三内容有原先父进程的缓冲区:A和i=1),然后执行printf,此时板块1的缓冲区中有AA两个,i++等于2,结束板块1.

第三个板块:因为复制了板块1的,i从1开始,直接执行printf语句,缓冲区有AA两个,i++变成2,j结束板块3.

第二个板块:因为是板块1的子进程,从printf处执行,缓冲区有一个A,i++等于1,继续for循环,执行fork语句形成板块4,然后缓冲区:AA,i++->2,结束板块2

第四个板块:因为复制了板块2,从printf处执行,缓冲区:AA,i++ ->2结束板块4

所以总计8个A

 

 注意:练习一和练习二最大的区别在于缓存区的刷新

1.5.3 练习三

结果

 原因

首先执行fork()||fork()语句,复制了一份,因为父进程的id>0,根据或语句特点直接结束,打印第一个A。然后子进程中0||fork(),或语句如果第一个为1 就直接跳过了,但是为0 就要继续执行后面语句,因此复制了一份代码,由于第二个fork()返回了当前父进程的id,直接结束语句,打印第二个A。最后子进程的pid为0,所以返回值为0,0||0为假,打印最后一个A结束整个程序,所以打印三个A

 

二、操作文件的系统调用

在C语言中有fopen,fclose等文件操作

头文件:#include<fcntl.h>

2.1 open()

 文件已存在:int open(const char *pathname, int flags);
 文件之前不存在,需要创建:int open(const char *pathname, int flags, mode_t mode);

pathname :将要打开的文件路径和名称
flags : 打开标志,如 O_WRONLY 只写打开    O_RDONLY 只读打开
                                  O_RDWR 读写方式打开   O_CREAT 文件不存在则创建   
                                  O_APPEND 文件末尾追加  O_TRUNC 清空文件,重新写入
mode : 权限 如:“0600”  0是八进制,6是4 r+2 w
返回值: 为文件描述符

2.2 read()

从文件中提取数据

ssize_t read( int fd, void * buf, size_t count);
fd 对应打开的文件描述符
buf 存放数据的空间
count 计划一次从文件中读多少字节数据 
返回值 :为实际读到的字节数

2.3 write()

从文件中写入数据

ssize_t write( int fd, const void * buf, size_t count);
参数介绍
fd 对应打开的文件描述符
buf 存放待写入的数据
count 计划一次向文件中写多少数据

2.4 close()

关闭文件

int close( int fd);
参数介绍 :
fd 要关闭的文件描述符

2.5 举例

2.5.1 写文件

 fd:文件描述符,通过编号id可以找到文件,0 标准输入,1标准输出,2标准错误输出

所以fd值为3

2.5.2 读文件

2.6  父进程先打开一个文件,fork 后子进程是否可以共享使用?

2.6.1 文件表

 当不使用file.txt,把三关闭了,如果打开另外一个文件,则继续复用三。(不使用就关闭,这样就不会一直占用,使表不变大)

2.6.2 先open后fork

2.6.1.2 结果:

 父进程打开的文件,子进程也可以访问,并且共享文件偏移量,如果想要关闭文件,需要父子进程都关闭文件。

2.6.1.3原因

父子进程共用一个结构体,引用计数为2,所以文件偏移量+1,那么子进程就输出d,再+1,父进程输出,所以结果出现四个偏移。

2.6.3 先fork后open

2.6.2.2 结果

 

2.6.2.3 原因

 

 因为父和子进程各有一个结构体,打开一个文件,其偏移量并不互相影响,所以都是从a开始。

三、系统调用与库函数的区别

库函数的实现在函数库中,属于用户空间,系统调用的实现在内核中,属于内核空间。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/66550.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL高阶知识点(一)一条SQL【更新】语句是如何执行的

一条SQL【更新】语句是如何执行的 首先&#xff0c;可以确定的说&#xff0c;【查询】语句的那一套流程&#xff0c;【更新】语句也是同样会走一遍&#xff0c;与查询流程不一样的是&#xff0c; 更新语句涉及到【事务】&#xff0c;就必须保证事务的四大特性&#xff1a;ACID&…

【Megatron-DeepSpeed】张量并行工具代码mpu详解(四):张量并行版Embedding层及交叉熵的实现及测试

相关博客 【Megatron-DeepSpeed】张量并行工具代码mpu详解(四)&#xff1a;张量并行版Embedding层及交叉熵的实现及测试 【Megatron-DeepSpeed】张量并行工具代码mpu详解(三)&#xff1a;张量并行层的实现及测试 【Megatron-DeepSpeed】张量并行工具代码mpu详解(一)&#xff1a…

【C++】开源:abseil-cpp基础组件库配置使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍abseil-cpp基础组件库配置使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#…

小程序具体开发

window 导航栏 属性名类型默认值作用navigationBarTitleText string字字符串导航栏标题内容navigationBarBackgroundColorHexcolor#000000设置导航栏背景颜色&#xff08;比如荧黄色 #ffa&#xff09;navigationBarTextStylestringwhite设置导航栏标题的颜色&#xff08;仅含有…

在 Windows 上安装 OpenCV – C++ / Python

在这篇博文中&#xff0c;我们将在 Windows 上安装适用于 C 和 Python 的 OpenCV。 C 安装是在自定义安装 exe 文件的帮助下完成的。而Python的安装是通过Anaconda完成的。 在 Windows 上安装 OpenCV – C / Python&#xff08;opencv官方Wndows上安装openCV- C/ Pthon 的链接…

STM32 F103C8T6学习笔记7:双机无线串口通信

今日尝试配通俩个C8T6单片机之间的无线串口通信&#xff0c;文章提供原理&#xff0c;源码&#xff0c;测试效果图&#xff0c;测试工程下载&#xff1a; 目录 传输不规范问题&#xff1a; 串口通信资源&#xff1a; 单个串口资源理解&#xff1a; 单片机串口资源&#xf…

NIO 非阻塞式IO

NIO Java NIO 基本介绍 Java NIO 全称 Java non-blocking IO&#xff0c;是指 JDK 提供的新 API。从 JDK1.4 开始&#xff0c;Java 提供了一系列改进的输入/输出的新特性&#xff0c;被统称为 NIO&#xff08;即 NewIO&#xff09;&#xff0c;是同步非阻塞的。NIO 相关类都被…

① vue复习。从安装到使用

vue官网&#xff1a;cn.vuejs.org vue安装 cnpm install -g vue/cli 查看是否安装成功 vue --version 创建一个项目 vue create vue-demo(项目名称) 这个取消掉。空格可选中或者取消。 运行项目&#xff1a; cd 进入到项目下 npm run serve 运行成功后&#xff0c;访问这…

k8s ------存储卷(PV、PVC)

目录 一&#xff1a;为什么需要存储卷&#xff1f; 二&#xff1a;emptyDir存储卷 ​三&#xff1a;hostPath存储卷 四&#xff1a;nfs共享存储卷 五&#xff1a;PVC 和 PV 1、PVC 和 PV介绍 2、PV和PVC之间的相互作用遵循的生命周期 3、PV 的4 种状态 4、一个PV从创…

圆满收官丨“2023年度第一季万博智云云迁移架构师训练营”结营了

“2023年度第一季万博智云云迁移架构师训练营”于今日圆满落幕。百余名来自全国各地30企业的工程师报名参加学习&#xff0c;其中60工程师在忙碌工作中抽空参与考试&#xff0c;近40名工程师通过万博智云云迁移架构师OCCE认证。 为了帮助工程师们掌握云迁移基础知识&#xff0c…

Redux - Redux在React函数式组件中的基本使用

文章目录 一&#xff0c;简介二&#xff0c;安装三&#xff0c;三大核心概念Store、Action、Reducer3.1 Store3.2 Reducer3.3 Action 四&#xff0c;开始函数式组件中使用4.1&#xff0c;引入store4.1&#xff0c;store.getState()方法4.3&#xff0c;store.dispatch()方法4.4&…

Qt自定义对话框

介绍 自定义框主要通过对现有对话框QDialog类的派生&#xff0c;根据需求编写成员函数、重载信号函数、槽函数&#xff0c;进而实现在主QWidget中点击某个按钮后&#xff0c;一个对话框的弹出 流程 简化创建派生类 最后点击完成即可。 自定义ui界面&#xff0c;编写成员函数…