Linux 第十九章

🐶博主主页:@ᰔᩚ. 一怀明月ꦿ 

❤️‍🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++,linux

🔥座右铭:“不要等到什么都没有了,才下定决心去做”

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀

目录

mm_struct

写时拷贝

fork

fork常规用法​​​​​​​

fork调用失败的原因

创建一个多进程

进程终止

main函数的返回值

strerror

​​​​​​​有时候用echo $?显示退出码并不和库里标准的对应

C语言的错误码


mm_struct

写时拷贝

父进程创建子进程的时候,首先将自己的页表读写权限改为只读,然后再创建子进程

(注意:代码段一直是只读的),但是这个过程用户是不知道的!用户就有可能对某一批数据进行写入!

此时,页表就会因为权限问题出错

1)真的出错了,例如用户想要修改代码的数据

2)例如用户想要修改数据段的数据,操作系统就会重新申请内存

注意:

1.在地址空间里面绝对不会出现划分的区域重叠的

2.Os操作系统肯定知道我们在读还是在写

为什么子进程发生写时拷贝的时候,需要拷贝父进程数据段的代码再进行写入,而不是直接申请空间直接写入呢?

子进程不一定要对父进程数据段全部进行修改,可能修改一部分

fork

fork常规用法​​​​​​​

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

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

fork调用失败的原因

fork失败的返回值小于0

1.系统进程太多

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

创建一个多进程

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#define N 10
typedef void (*callback_t)();//函数指针void Worker()//子进程执行的方法
{int cnt=10;while(cnt){printf("I am child process,pid:%d ,ppid: %d ,cnt:%d\n",getpid(),getppid(),cnt);sleep(1);cnt--;}}
void createSubProcess(int n,callback_t cb)//创建n个子进程+
{int i=0;for(i=0;i<n;i++){sleep(1);pid_t id=fork();if(id==0){printf("create child process success:%d\n",i);//childcb();exit(0);}}}int main()
{createSubProcess(N,Worker);//只有父进程走到这里sleep(100);return 0;
}当n个子进程运行完之后,父进程并没有结束(因为sleep(100)),所以子进程就会形成僵尸进程PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
17831 26353 26353 17831 pts/0    26353 S+    1000   0:00 ./myprocess
26353 26380 26353 17831 pts/0    26353 Z+    1000   0:00 [myprocess] <defunct>
26353 26458 26353 17831 pts/0    26353 Z+    1000   0:00 [myprocess] <defunct>
26353 26540 26353 17831 pts/0    26353 Z+    1000   0:00 [myprocess] <defunct>
26353 26555 26353 17831 pts/0    26353 Z+    1000   0:00 [myprocess] <defunct>
26353 26629 26353 17831 pts/0    26353 Z+    1000   0:00 [myprocess] <defunct>
26353 26711 26353 17831 pts/0    26353 Z+    1000   0:00 [myprocess] <defunct>
26353 26758 26353 17831 pts/0    26353 Z+    1000   0:00 [myprocess] <defunct>
26353 26808 26353 17831 pts/0    26353 Z+    1000   0:00 [myprocess] <defunct>
26353 26882 26353 17831 pts/0    26353 Z+    1000   0:00 [myprocess] <defunct>
26353 26929 26353 17831 pts/0    26353 Z+    1000   0:00 [myprocess] <defunct>

进程终止

main函数的返回值

[BCH@hcss-ecs-6176 ~]$ cat test.c
#include<stdio.h>
int main()
{return 10;
}[BCH@hcss-ecs-6176 ~]$ ./mytest
[BCH@hcss-ecs-6176 ~]$ echo $?//获取main函数的返回值
10

?:保存的就是最近一个子进程执行完毕时的退出码
就类似于 echo $环境变量 将环境变量的内容输出到屏幕上
echo $?将最近一个子进程执行完毕时的退出码输出到屏幕上

在多进程环境中,我们(父进程)创建子进程的目的是什么?
帮我们办事


子进程把事情办得怎么样呢??

main函数的返回值,就叫做进程的退出码,0->成功,非0表示失败
非0的时候,这个进程因为什么原因失败!
1,2,3,4,5,6……我们可以用不同的数字表示不同的原因!!

纯数字能表示出错原因,但是不便于人阅读,exit code->exit code string (将数字转化为字符串的形式便于人去阅读)

strerror

在C语言中,strerror是一个库函数,用于将错误码或退出码转换为对应的错误消息字符串。

通过strerror查看linux中c的退出码(错误码)
[BCH@hcss-ecs-6176 ~]$ cat test.c
#include<stdio.h>
#include<string.h>
int main()
{int i=0;for(i=0;i<200;i++)//之所以是200,因为我不知道linux中退出码的范围(实际上退出码的范围0-133){printf("%d:%s\n",i,strerror(i));}return 10;
}[BCH@hcss-ecs-6176 ~]$ ./mytest
0:Success
1:Operation not permitted
2:No such file or directory
3:No such process
4:Interrupted system call
5:Input/output error
6:No such device or address
7:Argument list too long
8:Exec format error
9:Bad file descriptor
10:No child processes
11:Resource temporarily unavailable
12:Cannot allocate memory
13:Permission denied
14:Bad address
15:Block device required
16:Device or resource busy
17:File exists
18:Invalid cross-device link
19:No such device
20:Not a directory
21:Is a directory
22:Invalid argument
23:Too many open files in system
24:Too many open files
25:Inappropriate ioctl for device
26:Text file busy
27:File too large
28:No space left on device
29:Illegal seek
30:Read-only file system
31:Too many links
32:Broken pipe
33:Numerical argument out of domain
34:Numerical result out of range
35:Resource deadlock avoided
36:File name too long
37:No locks available
38:Function not implemented
39:Directory not empty
40:Too many levels of symbolic links
41:Unknown error 41
42:No message of desired type
43:Identifier removed
44:Channel number out of range
45:Level 2 not synchronized
46:Level 3 halted
47:Level 3 reset
48:Link number out of range
49:Protocol driver not attached
50:No CSI structure available
51:Level 2 halted
52:Invalid exchange
53:Invalid request descriptor
54:Exchange full
55:No anode
56:Invalid request code
57:Invalid slot
58:Unknown error 58
59:Bad font file format
60:Device not a stream
61:No data available
62:Timer expired
63:Out of streams resources
64:Machine is not on the network
65:Package not installed
66:Object is remote
67:Link has been severed
68:Advertise error
69:Srmount error
70:Communication error on send
71:Protocol error
72:Multihop attempted
73:RFS specific error
74:Bad message
75:Value too large for defined data type
76:Name not unique on network
77:File descriptor in bad state
78:Remote address changed
79:Can not access a needed shared library
80:Accessing a corrupted shared library
81:.lib section in a.out corrupted
82:Attempting to link in too many shared libraries
83:Cannot exec a shared library directly
84:Invalid or incomplete multibyte or wide character
85:Interrupted system call should be restarted
86:Streams pipe error
87:Too many users
88:Socket operation on non-socket
89:Destination address required
90:Message too long
91:Protocol wrong type for socket
92:Protocol not available
93:Protocol not supported
94:Socket type not supported
95:Operation not supported
96:Protocol family not supported
97:Address family not supported by protocol
98:Address already in use
99:Cannot assign requested address
100:Network is down
101:Network is unreachable
102:Network dropped connection on reset
103:Software caused connection abort
104:Connection reset by peer
105:No buffer space available
106:Transport endpoint is already connected
107:Transport endpoint is not connected
108:Cannot send after transport endpoint shutdown
109:Too many references: cannot splice
110:Connection timed out
111:Connection refused
112:Host is down
113:No route to host
114:Operation already in progress
115:Operation now in progress
116:Stale file handle
117:Structure needs cleaning
118:Not a XENIX named type file
119:No XENIX semaphores available
120:Is a named type file
121:Remote I/O error
122:Disk quota exceeded
123:No medium found
124:Wrong medium type
125:Operation canceled
126:Required key not available
127:Key has expired
128:Key has been revoked
129:Key was rejected by service
130:Owner died
131:State not recoverable
132:Operation not possible due to RF-kill
133:Memory page has hardware error
134:Unknown error 134//这里已经没有了

连续echo $?

[BCH@hcss-ecs-6176 ~]$ echo $?
10
[BCH@hcss-ecs-6176 ~]$ echo $?
0
[BCH@hcss-ecs-6176 ~]$ echo $?
0

为什么第一个echo $?输出的就是10,第二个echo $?输出就是0呢?

因为第一个echo $?中的?保留的是./mytest进程的退出码,而./mytest进程的退出码是10,

第二个echo $?中的?保留的是第一个echo $?这个进程的退出码,因为第一个echo $?进程退出码是0

​​​​​​​有时候用echo $?显示退出码并不和库里标准的对应

[BCH@hcss-ecs-6176 ~]$cd /home/wcq
bash: cd: /home/wcq: Permission denied
[BCH@hcss-ecs-6176 ~]$echo $?
1
库里13:Permission denied,Permission denied表示的退出码是13
但是echo $?显示的值是1
所以这里用退出码不是使用的C语言标准库的,而是使用的自定义的

main函数的退出码是可以被父进程获取的,用来判断子进程的运行结果

C语言的错误码

c语言中的全局变量errno
在C语言中,errno是一个全局变量,用于表示最近一次发生的错误码。它定义在 <errno.h> 头文件中。


错误码VS退出码
错误码通常是衡量一个库函数或者是一个系统调用一个函数的调用的情况
退出码通常是一个进程退出的时候,他退出结果

当失败的时候,用来衡量函数,进程出错时的出错详细信息原因

linux内核是c语言写的,linux中很多的系统调用就设置了errno

一般代码出异常,代码是没有运行完的

异常问题——引入一下
[BCH@hcss-ecs-6176 ~]$ cat test.c
#include<stdio.h>
#include<string.h>
int main()
{int a=10;a/=0; 
}
[BCH@hcss-ecs-6176 ~]$ ./mytest
浮点数例外//异常[BCH@hcss-ecs-6176 ~]$ cat test.c
#include<stdio.h>
#include<string.h>
int main()
{int *p=NULL;*p=100;return 10;
}
[BCH@hcss-ecs-6176 ~]$ ./mytest
段错误//异常
进程异常会被os杀掉这个进程(kill)
进程异常的时候,会转化成信号,会被os检测到的

结论:进程出异常,本质是进程收到了对应的信号,自己终止了!!

  🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸 

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

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

相关文章

QtWindows任务栏

目录 引言任务栏进度右键菜单缩略图工具栏完整代码 引言 针对Windows系统的任务栏&#xff0c;Qt基于系统的原生接口封装有一些非常见类&#xff0c;如QWinTaskbarButton、QWinTaskbarButton、QWinThumbnailToolBar等&#xff0c;用于利用工具栏提供更多的信息&#xff0c;诸如…

报错(已解决):无法加载文件 D:\code\NodeJs\pnpm.ps1,因为在此系统上禁止运行脚本。

问题&#xff1a; 在vscode运行uniapp项目需要拉取全部依赖&#xff0c;需要使用到pnpm&#xff0c;在vscode终端运行命令&#xff1a;pnpm install后报错&#xff1a; 解决办法&#xff1a; 1&#xff1a;我未安装pnpm&#xff0c;首先打开电脑cmd&#xff0c;运行下列命令&a…

On Hold 频发!又3本期刊被标记为On Hold ,大家谨慎投递!

【SciencePub学术】On Hold 频发&#xff01;小编在查阅资料的时候发现又有3本期刊被标记为On Hold 了&#xff0c;今天小编给大家详细介绍一下这3本期刊。 来源&#xff1a;科睿唯安官网 Results in Physics 1 期刊概况 【期刊简介】IF&#xff1a;5.3&#xff0c;JCR1区&am…

CSS Web服务器、2D、动画和3D转换

Web服务器 我们自己写的网站只能自己访问浏览&#xff0c;但是如果想让其他人也浏览&#xff0c;可以将它放到服务器上。 什么是Web服务器 服务器(我们也会称之为主机)是提供计算服务的设备&#xff0c;它也是一台计算机。在网络环境下&#xff0c;根据服务器提供的服务类型不…

ubuntu20.04搭建Fabric教程

本章节环境配置 ubuntu: 20.04 go&#xff1a;1.16.3 docker: 20.10.6 docker-compose: 1.27.2 fabric&#xff1a;2.2.0 fabric-ca: 1.4.9 一 搭建通道 新建工作目录 mkdir fabric && cd fabric配置go代理 go env -w GO111MODULEon ​ #更新下载包的镜像 go env …

【Docker】★★★

docker 的网络模式 ●host模式&#xff1a;使用 --nethost 指定 容器与宿主机共享网络命名空间、ip和端口 ●container模式&#xff1a;使用 --netcontainer:NAME_or_ID 指定 新建的容器共享已有容器的网络命名空间、ip和端口 ●none模式&#xff1a;使用 --netnone 指定 不进行…

Mybatis进阶3--注解开发

先看&#xff1a; Mybatis进阶1-CSDN博客 Mybatis进阶2-CSDN博客 mybatis注解开发 前置&#xff1a;不需要xxxMapper..xml文件&#xff08;映射文件&#xff09; 在核心配置文件中&#xff1a;<mappers>标签只能使用&#xff1a;<package name"扫描的包&quo…

使用docker安装redis

使用docker安装redis ①拉取镜像 docker pull redis:6.2.6② 创建容器 docker run -d --name forum-redis --restartalways -p 6379:6379 redis:6.2.6 redis-server --requirepass "dong97"③链接测试 打开Redis Desktop Manager&#xff0c;输入host、port、pas…

MySQL之查询 拿下 * 。*

DQL数据查询语言 对上述的的查询操作进行代码演示&#xff08;续上一篇学生表代码进行处理&#xff09; 下面是上一篇的代码分享 下面进行简单的查询操作 字符串如果强行进行算数运算默认只为0 查询时常用的单行函数列举 未完待续

【005_音频开发_基础篇_ALSA_Codec_驱动-MA120x0P功放】

005_音频开发_基础篇_ALSA_Codec_驱动-MA120x0P功放 文章目录 005_音频开发_基础篇_ALSA_Codec_驱动-MA120x0P功放创作背景MA120X0P输出模式BTLSEPBTLSEBTL 硬件配置方式/硬件Limiter限幅器限幅器作用过程 主要寄存器操作指令 ma120x0p.cma120x0p.h 创作背景 学历代表过去、能…

OpenNJet应用引擎——云原生时代的Web服务新选择

文章目录 OpenNJet应用引擎——云原生时代的Web服务新选择引言&#xff1a;数字化转型的推动力&#xff1a;OpenNJet应用引擎为什么选择OpenNJet&#xff1f; OpenNJet的核心优势1. 云原生功能增强2. 安全加固3. 代码重构与性能优化4. 动态加载机制5. 多样化的产品形态6. 易于集…

Python批量修改图片文件名中的指定名称

批量处理图像时&#xff0c;图片名有时需要统一&#xff0c;本教程仅针对图片中名如&#xff1a;0001x4.png&#xff0c;批量将图片名中的x4去除&#xff0c;只留下0001.png的情况。 如果想要按照原图片顺序批量修改图片名&#xff0c;参考其它博文&#xff1a;按照原顺序批量…