优化文件位置

This commit is contained in:
LazuliKao 2024-09-20 21:28:39 +08:00
parent a21bdd2287
commit cb929adfa8
269 changed files with 256 additions and 632 deletions

View file

@ -5,7 +5,7 @@ pubDate: 2022-03-27 21:38:45
categories: categories:
- 技术 - 技术
- C语言 - C语言
cover: ./assets/c10e40ab02e343e3afa9fb19b5619042/assembly.jpeg cover: ./_assets/c10e40ab02e343e3afa9fb19b5619042/assembly.jpeg
tid: c-from-asm-1 tid: c-from-asm-1
description: 反汇编C语言程序的解读。 description: 反汇编C语言程序的解读。
permalink: /pages/989a42/ permalink: /pages/989a42/
@ -58,31 +58,31 @@ mainCRTStartup 做了哪些事?
以上述程序为例,寻找其`main`函数入口。 以上述程序为例,寻找其`main`函数入口。
![image-20220327214647589](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327214647589.png) ![image-20220327214647589](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327214647589.png)
初步调试文件,可以发现许多`jmp`指令,这是编译器生成的启动代码,往下按 F8 跟随跳转。 初步调试文件,可以发现许多`jmp`指令,这是编译器生成的启动代码,往下按 F8 跟随跳转。
![image-20220327214714185](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327214714185.png) ![image-20220327214714185](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327214714185.png)
连续按`F8`来到`call tmainCRTStartuptringtionFilter`再一次按`F8`后,整个程序就会返回,因此按`F7`单步进入该函数。 连续按`F8`来到`call tmainCRTStartuptringtionFilter`再一次按`F8`后,整个程序就会返回,因此按`F7`单步进入该函数。
接下来连续按下`F8`,并且观察控制台输出: 接下来连续按下`F8`,并且观察控制台输出:
![image-20220327214738686](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327214738686.png) ![image-20220327214738686](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327214738686.png)
发现再`call hello.00241140`后控制台打出 Hello World因此在此处设下断点。 发现再`call hello.00241140`后控制台打出 Hello World因此在此处设下断点。
按下`Ctrl+F2`后重新启动程序,按下`F9`运行到该断点,按下`F7`单步进入。 按下`Ctrl+F2`后重新启动程序,按下`F9`运行到该断点,按下`F7`单步进入。
![image-20220327214803763](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327214803763.png) ![image-20220327214803763](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327214803763.png)
按几次 F8 后看到如上界面,可以看到 Hello World 字符串,程序的开头即初始化栈帧操作,显然已经成功来到了 main 函数中。 按几次 F8 后看到如上界面,可以看到 Hello World 字符串,程序的开头即初始化栈帧操作,显然已经成功来到了 main 函数中。
![image-20220327214826902](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327214826902.png) ![image-20220327214826902](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327214826902.png)
查看如上高亮的指令该指令将“Hello World”字符串的首地址压入栈中而后调用 printf将字符串打印在控制台上。 查看如上高亮的指令该指令将“Hello World”字符串的首地址压入栈中而后调用 printf将字符串打印在控制台上。
![image-20220327215012755](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327215012755.png) ![image-20220327215012755](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327215012755.png)
事实也正是如此! 事实也正是如此!
@ -126,35 +126,35 @@ int main(int argc,char* argv[])
进入 OD 后,依然要越过启动代码,寻找真正的`main`函数。 进入 OD 后,依然要越过启动代码,寻找真正的`main`函数。
![image-20220327220701475](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220701475.png) ![image-20220327220701475](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220701475.png)
连续按 F8。 连续按 F8。
按照以往的经验,调用`main`函数至少在调用`GetCommandLine`函数之后。 按照以往的经验,调用`main`函数至少在调用`GetCommandLine`函数之后。
![image-20220327220724315](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220724315.png) ![image-20220327220724315](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220724315.png)
于是这里继续往下执行。 于是这里继续往下执行。
![image-20220327220810610](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220810610.png) ![image-20220327220810610](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220810610.png)
看到这里可以 push 了 3 个参数,发现 argv 和 argc 的字样,那么下一个 call 十有八九会到达`main`函数了。 看到这里可以 push 了 3 个参数,发现 argv 和 argc 的字样,那么下一个 call 十有八九会到达`main`函数了。
按 F7 单步进入。 按 F7 单步进入。
![image-20220327220839595](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220839595.png) ![image-20220327220839595](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220839595.png)
来到这里就已经很明显了,可以明显的看到下图中由`mov ..., 0x5`和`mov ..., 0x6`两个语句,这明显是在给变量赋值上 5 和 6那么就可以推测`call test.00DD135C`实际上在调用`add`函数,将光标移动指令处,按回车键。 来到这里就已经很明显了,可以明显的看到下图中由`mov ..., 0x5`和`mov ..., 0x6`两个语句,这明显是在给变量赋值上 5 和 6那么就可以推测`call test.00DD135C`实际上在调用`add`函数,将光标移动指令处,按回车键。
![image-20220327220903701](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220903701.png) ![image-20220327220903701](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220903701.png)
如下图可以看到`add`字样,因此猜想是对的。 如下图可以看到`add`字样,因此猜想是对的。
![image-20220327220934315](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220934315.png) ![image-20220327220934315](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220934315.png)
那么回到之前的`main`函数,可以看到代码将 0x5 和 0x6 放入 rax 和 ecx 寄存器后,又对其进行了压栈操作,实际等价于`push 0x5`和`push 0x6`。 那么回到之前的`main`函数,可以看到代码将 0x5 和 0x6 放入 rax 和 ecx 寄存器后,又对其进行了压栈操作,实际等价于`push 0x5`和`push 0x6`。
![image-20220327221004603](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327221004603.png) ![image-20220327221004603](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327221004603.png)
push 操作就是 x86 架构下典型的压栈方式,符合**\_\_cdecl**调用约定(C/C++程序的默认调用约定,在此不作赘述),在该约定下,可以看到压栈顺序是逆序的,右边的参数先进栈,左边的参数后进栈,栈顶指针 esp 指向栈中第 1 个可用的数据项。 push 操作就是 x86 架构下典型的压栈方式,符合**\_\_cdecl**调用约定(C/C++程序的默认调用约定,在此不作赘述),在该约定下,可以看到压栈顺序是逆序的,右边的参数先进栈,左边的参数后进栈,栈顶指针 esp 指向栈中第 1 个可用的数据项。
@ -162,11 +162,11 @@ push 操作就是 x86 架构下典型的压栈方式,符合**\_\_cdecl**调用
现在将程序运行到 call 指令之前,查看 OD 的栈区数据,可以看到显示 Arg1=5Arg2=6显然这两个参数已经被压栈。 现在将程序运行到 call 指令之前,查看 OD 的栈区数据,可以看到显示 Arg1=5Arg2=6显然这两个参数已经被压栈。
![image-20220327221037201](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327221037201.png) ![image-20220327221037201](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327221037201.png)
进入 add 函数后,可以看到程序将 arg1 存入 eax 寄存器,再和 arg2 相加,就完成了计算。 进入 add 函数后,可以看到程序将 arg1 存入 eax 寄存器,再和 arg2 相加,就完成了计算。
![image-20220327221100245](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327221100245.png) ![image-20220327221100245](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327221100245.png)
另外还有几种调用约定,如**fastcall**和**stdcall**。 另外还有几种调用约定,如**fastcall**和**stdcall**。
@ -187,11 +187,11 @@ int add(int x,int y)
进入 OD再次回到 add 函数中。 进入 OD再次回到 add 函数中。
![image-20220327221142426](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327221142426.png) ![image-20220327221142426](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327221142426.png)
`mov eax, [local.2]`是将计算的最后结果就保存在 eax 寄存器中eax 就作为存放返回值的寄存器。 `mov eax, [local.2]`是将计算的最后结果就保存在 eax 寄存器中eax 就作为存放返回值的寄存器。
![image-20220327221206970](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327221206970.png) ![image-20220327221206970](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327221206970.png)
众所周知,带回返回值的方法不只`return`,还可传引用,查看如下代码: 众所周知,带回返回值的方法不只`return`,还可传引用,查看如下代码:
@ -216,7 +216,7 @@ int main(int argc,char* argv[])
这里定义了一个`max`函数,接收`a`和`b`的地址,将其中较大数放入变量`a`中。使用 OD进入`main`函数。 这里定义了一个`max`函数,接收`a`和`b`的地址,将其中较大数放入变量`a`中。使用 OD进入`main`函数。
![image-20220327220253195](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220253195.png) ![image-20220327220253195](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220253195.png)
进入`max`函数,`mov eax, [arg.1]`和`mov ecx, [arg.2]`是将参数`a`和`b`的值加载到两个寄存器。 进入`max`函数,`mov eax, [arg.1]`和`mov ecx, [arg.2]`是将参数`a`和`b`的值加载到两个寄存器。
@ -224,7 +224,7 @@ int main(int argc,char* argv[])
直接看到`mov dword ptr ds:[eax], edx`。`dword ptr`是指明数据宽度,而这一步操作就是将结果填入变量 a 所在的内存地址处。 直接看到`mov dword ptr ds:[eax], edx`。`dword ptr`是指明数据宽度,而这一步操作就是将结果填入变量 a 所在的内存地址处。
![image-20220327220315921](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220315921.png) ![image-20220327220315921](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220315921.png)
## 数据结构 ## 数据结构
@ -258,11 +258,11 @@ int main(void)
这里开辟后的空间一部分是用来存放变量 z 的。 这里开辟后的空间一部分是用来存放变量 z 的。
![image-20220327220210074](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220210074.png) ![image-20220327220210074](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220210074.png)
`call`调用完后,会出现`add esp,0x8`这步操作实际上是在平衡栈,可以理解为“回收现场”。 `call`调用完后,会出现`add esp,0x8`这步操作实际上是在平衡栈,可以理解为“回收现场”。
![image-20220327220111908](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220111908.png) ![image-20220327220111908](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220111908.png)
局部变量的起始值是随机的,是其他函数执行后留在栈中的垃圾数据,因此须要对其进行初始化。 局部变量的起始值是随机的,是其他函数执行后留在栈中的垃圾数据,因此须要对其进行初始化。
@ -299,11 +299,11 @@ int main(void)
这里是对 z 赋值,直接用`mov`将 7 写入一个固定的内存地址。 这里是对 z 赋值,直接用`mov`将 7 写入一个固定的内存地址。
![image-20220327220033227](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220033227.png) ![image-20220327220033227](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220033227.png)
在`add`函数中,同样直接从固定的地址中取出`z`的值到 eax 寄存器中。 在`add`函数中,同样直接从固定的地址中取出`z`的值到 eax 寄存器中。
![image-20220327220014288](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220014288.png) ![image-20220327220014288](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327220014288.png)
### 数组 ### 数组
@ -333,7 +333,7 @@ int main(void)
一般对数组的访问是通过基址加变址寻址实现的。 一般对数组的访问是通过基址加变址寻址实现的。
![image-20220327215920733](./assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327215920733.png) ![image-20220327215920733](./_assets/c10e40ab02e343e3afa9fb19b5619042/image-20220327215920733.png)
在内存中数组可存在于栈、数据段及动态内存中,本例中`a[]`数组就保存在数据段.data 中,其寻址用“基址+偏移量”实现。 在内存中数组可存在于栈、数据段及动态内存中,本例中`a[]`数组就保存在数据段.data 中,其寻址用“基址+偏移量”实现。

View file

@ -6,7 +6,7 @@ tid: tools-to-write-c
categories: categories:
- 技术 - 技术
- C语言 - C语言
cover: ./assets/994555a5411c427da8f39428f49b12fb/PYVEjWmMy6tkqdQ.png cover: ./_assets/994555a5411c427da8f39428f49b12fb/PYVEjWmMy6tkqdQ.png
description: 写C语言的千奇百怪的编辑器推荐一些在机房使用的编辑器。 description: 写C语言的千奇百怪的编辑器推荐一些在机房使用的编辑器。
permalink: /pages/0066b6/ permalink: /pages/0066b6/
author: author:
@ -49,31 +49,31 @@ tags:
点击**文件** -> **新建** -> **源代码**即可直接开始打代码。 点击**文件** -> **新建** -> **源代码**即可直接开始打代码。
![image-20220309220255982](./assets/994555a5411c427da8f39428f49b12fb/bYGImLQAe6NnvB9.png) ![image-20220309220255982](./_assets/994555a5411c427da8f39428f49b12fb/bYGImLQAe6NnvB9.png)
点击**编译并运行**按钮(默认快捷键为`F11`)即可运行你的 C/C++代码。 点击**编译并运行**按钮(默认快捷键为`F11`)即可运行你的 C/C++代码。
![image-20220309220436198](./assets/994555a5411c427da8f39428f49b12fb/OyXFgwLKNa3uRWY.png) ![image-20220309220436198](./_assets/994555a5411c427da8f39428f49b12fb/OyXFgwLKNa3uRWY.png)
#### 中文设置 #### 中文设置
主界面工具栏 **Tools** -> **Environment Options** (或者键盘依次按下 Alt, t, v)。 主界面工具栏 **Tools** -> **Environment Options** (或者键盘依次按下 Alt, t, v)。
![image-20220308155922714](./assets/994555a5411c427da8f39428f49b12fb/iWhrt48meZqUJPF.png) ![image-20220308155922714](./_assets/994555a5411c427da8f39428f49b12fb/iWhrt48meZqUJPF.png)
直接在新窗口**General**一栏**Language**一栏选择**简体中文**即可。 直接在新窗口**General**一栏**Language**一栏选择**简体中文**即可。
![image-20220308160536079](./assets/994555a5411c427da8f39428f49b12fb/VbXLmk2Ox9dScW3.png) ![image-20220308160536079](./_assets/994555a5411c427da8f39428f49b12fb/VbXLmk2Ox9dScW3.png)
如果你是**新安装**的,就很简单了,开启界面就会询问语言: 如果你是**新安装**的,就很简单了,开启界面就会询问语言:
![image-20220308154537126](./assets/994555a5411c427da8f39428f49b12fb/aZTwu1gLAJKOe6S.png) ![image-20220308154537126](./_assets/994555a5411c427da8f39428f49b12fb/aZTwu1gLAJKOe6S.png)
#### 格式化代码 #### 格式化代码
默认快捷键`Ctrl + Shift + A`,能让你的代码非常**整洁**。 默认快捷键`Ctrl + Shift + A`,能让你的代码非常**整洁**。
![dev-cpp-format](./assets/994555a5411c427da8f39428f49b12fb/Md9EaDczrFWtxhU.gif) ![dev-cpp-format](./_assets/994555a5411c427da8f39428f49b12fb/Md9EaDczrFWtxhU.gif)
#### 代码补全 #### 代码补全
@ -81,7 +81,7 @@ tags:
不像其他 IDE 的**自动提示**Dev C++需要**先按下快捷键**才能出现提示。 不像其他 IDE 的**自动提示**Dev C++需要**先按下快捷键**才能出现提示。
![dev-cpp-completion](./assets/994555a5411c427da8f39428f49b12fb/HmnCUGIAvLfJKz1.gif) ![dev-cpp-completion](./_assets/994555a5411c427da8f39428f49b12fb/HmnCUGIAvLfJKz1.gif)
除此之外,**C++**也有补全(包括 STL 除此之外,**C++**也有补全(包括 STL
@ -119,33 +119,33 @@ tags:
点击工具栏的中的**File** -> **New** -> **File...** 点击工具栏的中的**File** -> **New** -> **File...**
![image-20220308225001977](./assets/994555a5411c427da8f39428f49b12fb/7Hj84ignasekXy2.png) ![image-20220308225001977](./_assets/994555a5411c427da8f39428f49b12fb/7Hj84ignasekXy2.png)
弹出的窗口中选择**C/C++**然后点击**Go** 弹出的窗口中选择**C/C++**然后点击**Go**
![image-20220309203617508](./assets/994555a5411c427da8f39428f49b12fb/hAaxqHEBoZJrYeg.png) ![image-20220309203617508](./_assets/994555a5411c427da8f39428f49b12fb/hAaxqHEBoZJrYeg.png)
![image-20220309203903355](./assets/994555a5411c427da8f39428f49b12fb/bToElJW8qcFCBVn.png) ![image-20220309203903355](./_assets/994555a5411c427da8f39428f49b12fb/bToElJW8qcFCBVn.png)
![image-20220309204103773](./assets/994555a5411c427da8f39428f49b12fb/y6IwrJAGpq4uSFj.png) ![image-20220309204103773](./_assets/994555a5411c427da8f39428f49b12fb/y6IwrJAGpq4uSFj.png)
![image-20220309204314041](./assets/994555a5411c427da8f39428f49b12fb/2ra5ycmElG4OLwo.png) ![image-20220309204314041](./_assets/994555a5411c427da8f39428f49b12fb/2ra5ycmElG4OLwo.png)
点击**Build and Run**(默认快捷键为`F9`)即可运行程序。 点击**Build and Run**(默认快捷键为`F9`)即可运行程序。
![image-20220309205239545](./assets/994555a5411c427da8f39428f49b12fb/ns3XE8fithJSgc6.png) ![image-20220309205239545](./_assets/994555a5411c427da8f39428f49b12fb/ns3XE8fithJSgc6.png)
#### 格式化 #### 格式化
在编辑器中**右键** -> **Format use AStyle** 即可直接格式化代码。 在编辑器中**右键** -> **Format use AStyle** 即可直接格式化代码。
![cb-format](./assets/994555a5411c427da8f39428f49b12fb/rA2KMziYGCTq367.gif) ![cb-format](./_assets/994555a5411c427da8f39428f49b12fb/rA2KMziYGCTq367.gif)
#### 代码补全 #### 代码补全
默认开启代码补全,按`tab`或`Enter`都可以完成代码。 默认开启代码补全,按`tab`或`Enter`都可以完成代码。
![cb-completion](./assets/994555a5411c427da8f39428f49b12fb/LwG8sKiVemIpqJn.gif) ![cb-completion](./_assets/994555a5411c427da8f39428f49b12fb/LwG8sKiVemIpqJn.gif)
从测试可以看到代码补全**功能有限**,仅限**头文件****类型****数据结构**和一些**标识符****函数基本无补全**。 从测试可以看到代码补全**功能有限**,仅限**头文件****类型****数据结构**和一些**标识符****函数基本无补全**。
@ -187,7 +187,7 @@ tags:
想要入门或了解 vs code 的强大功能可以看另一篇文章。 想要入门或了解 vs code 的强大功能可以看另一篇文章。
![vscode-w-clang](./assets/994555a5411c427da8f39428f49b12fb/8cWuBzF4XeAjdE2.gif) ![vscode-w-clang](./_assets/994555a5411c427da8f39428f49b12fb/8cWuBzF4XeAjdE2.gif)
配置相对比较复杂,可以检索网上各种 vs code 配置 C/C++的文章。 配置相对比较复杂,可以检索网上各种 vs code 配置 C/C++的文章。
@ -219,7 +219,7 @@ tags:
安装时只需要**选择自己需要的模块**,之后也可以随时安装卸载其他模块,不需要纠结太多。 安装时只需要**选择自己需要的模块**,之后也可以随时安装卸载其他模块,不需要纠结太多。
![image-20220309201453870](./assets/994555a5411c427da8f39428f49b12fb/WoaDQnP7rtGB2vq.png) ![image-20220309201453870](./_assets/994555a5411c427da8f39428f49b12fb/WoaDQnP7rtGB2vq.png)
### 优缺点总结 ### 优缺点总结
@ -263,11 +263,11 @@ JetBrains 开发的 IDE。
- 计协有自己的博客啦https://nbtca.space/ - 计协有自己的博客啦https://nbtca.space/
- 如果你**碰到学习中的种种问题**,想更加**深入学习计算机软硬件知识**;做**网页**,做**游戏**,做**应用**;修**电脑**,玩**硬件**,做**志愿者活动**;不妨来**计算机协会之家**看看,总有热心的程序员~~秃头~~会解决你的问题! - 如果你**碰到学习中的种种问题**,想更加**深入学习计算机软硬件知识**;做**网页**,做**游戏**,做**应用**;修**电脑**,玩**硬件**,做**志愿者活动**;不妨来**计算机协会之家**看看,总有热心的程序员~~秃头~~会解决你的问题!
![image-20220309214828491](./assets/994555a5411c427da8f39428f49b12fb/17Yizy52PBMZarL.png) ![image-20220309214828491](./_assets/994555a5411c427da8f39428f49b12fb/17Yizy52PBMZarL.png)
- 关注我们定期举办的**理工维修日**(不仅仅是维修),成为**志愿者**,或是来这里进行**软件配置**问题和**硬件**咨询,我们非常欢迎! - 关注我们定期举办的**理工维修日**(不仅仅是维修),成为**志愿者**,或是来这里进行**软件配置**问题和**硬件**咨询,我们非常欢迎!
![image-20220309222044480](./assets/994555a5411c427da8f39428f49b12fb/3TX1Jiphz5MGHKA.png) ![image-20220309222044480](./_assets/994555a5411c427da8f39428f49b12fb/3TX1Jiphz5MGHKA.png)
<!-- for wechat --> <!-- for wechat -->
<!-- ![image-20220309222044480](./assets/994555a5411c427da8f39428f49b12fb/3989f49d21f44a0fa06e1d39c9cc8e5d.png) --> <!-- ![image-20220309222044480](./_assets/994555a5411c427da8f39428f49b12fb/3989f49d21f44a0fa06e1d39c9cc8e5d.png) -->

View file

@ -5,7 +5,7 @@ pubDate: 2022-04-19 10:11:26
categories: categories:
- 技术 - 技术
- Go语言 - Go语言
cover: ./assets/5973f095d19f42f3b0649a0e2f52f006/image-20220419101405456.png cover: ./_assets/5973f095d19f42f3b0649a0e2f52f006/image-20220419101405456.png
tid: go-first-tutorial tid: go-first-tutorial
description: Go语言入门教程。 description: Go语言入门教程。
permalink: /pages/bd144d/ permalink: /pages/bd144d/

View file

@ -5,7 +5,7 @@ pubDate: 2022-04-05 13:13:28
categories: categories:
- 技术 - 技术
- Linux - Linux
cover: ./assets/dfc39c2948664aa78df4a4b4aa11bb2c/20220320105749.png cover: ./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/20220320105749.png
tid: linux-note-signal tid: linux-note-signal
description: 有关linux信号的一系列笔记。 description: 有关linux信号的一系列笔记。
permalink: /pages/aff776/ permalink: /pages/aff776/
@ -55,21 +55,21 @@ int main()
如下所示,现在使用 Ctrl+C 是没办法中断这个程序的: 如下所示,现在使用 Ctrl+C 是没办法中断这个程序的:
![signal-1](./assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-1.png) ![signal-1](./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-1.png)
这里可以用 man 命令查看一下 signal 函数的帮助文档: 这里可以用 man 命令查看一下 signal 函数的帮助文档:
![signal-2](./assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-2.png) ![signal-2](./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-2.png)
signal 关联上了一个信号处理函数,来处理信号。 signal 关联上了一个信号处理函数,来处理信号。
现在修改这个代码,添加一行打印当前进程号,然后打开两个终端,一个终端运行上面的程序,一个终端尝试`kill`命令来发送信号: 现在修改这个代码,添加一行打印当前进程号,然后打开两个终端,一个终端运行上面的程序,一个终端尝试`kill`命令来发送信号:
![signal-3](./assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-3.png) ![signal-3](./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-3.png)
kill 要指定参数: kill 要指定参数:
![signal-4](./assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-4.png) ![signal-4](./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-4.png)
这是可行的,结果如上。 这是可行的,结果如上。
@ -79,7 +79,7 @@ kill 要指定参数:
Linux 有哪些信号类型: Linux 有哪些信号类型:
![signal-5](./assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-5.png) ![signal-5](./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-5.png)
Linux 信号有 64 个,分为不可靠信号(非实时1-31Unix 提供)和可靠信号(32-64后来扩充的)。又有系统自带的标准信号和用户自定义的信号。 Linux 信号有 64 个,分为不可靠信号(非实时1-31Unix 提供)和可靠信号(32-64后来扩充的)。又有系统自带的标准信号和用户自定义的信号。
@ -109,19 +109,19 @@ int main(int argc,char* argv[])
} }
``` ```
![signal-6](./assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-6.png) ![signal-6](./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-6.png)
![signal-7](./assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-7.png) ![signal-7](./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-7.png)
成功发送了信号。 成功发送了信号。
`sigaction`函数有所不同,功能更多: `sigaction`函数有所不同,功能更多:
![signal-8](./assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-8.png) ![signal-8](./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-8.png)
这里用到了一个结构体: 这里用到了一个结构体:
![signal-9](./assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-9.png) ![signal-9](./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-9.png)
结构体的第一个成员依然是原来的信号处理函数,第二个成员被称作高级信号处理函数,第三个成员用于信号屏蔽,剩下两个暂时还用不到。 结构体的第一个成员依然是原来的信号处理函数,第二个成员被称作高级信号处理函数,第三个成员用于信号屏蔽,剩下两个暂时还用不到。
@ -171,11 +171,11 @@ int main(void)
同时还要实现高级的信号发送,采用`sigqueue` 同时还要实现高级的信号发送,采用`sigqueue`
![signal-10](./assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-10.png) ![signal-10](./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-10.png)
这里有个重要的联合体,用来存储数据和信号一起发送: 这里有个重要的联合体,用来存储数据和信号一起发送:
![signal-11](./assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-11.png) ![signal-11](./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-11.png)
```c ```c
#include <stdio.h> #include <stdio.h>
@ -197,9 +197,9 @@ int main(int argc,char* argv[])
运行结果如下: 运行结果如下:
![](./assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-12.png) ![](./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-12.png)
![signal-13](./assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-13.png) ![signal-13](./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-13.png)
可以看到程序接收到了信号和数据。 可以看到程序接收到了信号和数据。
@ -213,9 +213,9 @@ int main(int argc,char* argv[])
首先看信号的具体作用: 首先看信号的具体作用:
![signal-14](./assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-14.png) ![signal-14](./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-14.png)
![signal-15](./assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-15.png) ![signal-15](./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/signal-15.png)
如上文所提,处理信号有 3 种方式:执行默认操作,捕获信号和忽略信号 如上文所提,处理信号有 3 种方式:执行默认操作,捕获信号和忽略信号
@ -336,4 +336,4 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
总结: 总结:
![](./assets/dfc39c2948664aa78df4a4b4aa11bb2c/7cb86c73b9e73893e6b0e0433d476928.png) ![](./_assets/dfc39c2948664aa78df4a4b4aa11bb2c/7cb86c73b9e73893e6b0e0433d476928.png)

View file

@ -5,7 +5,7 @@ pubDate: 2022-03-19 22:38:56
categories: categories:
- 技术 - 技术
- Linux - Linux
cover: ./assets/cbea6761a0164906b8396942cf61c664/20220320105749.png cover: ./_assets/cbea6761a0164906b8396942cf61c664/20220320105749.png
tid: linux-note-file-io tid: linux-note-file-io
description: 有关linux文件io的一系列笔记。 description: 有关linux文件io的一系列笔记。
permalink: /pages/82d273/ permalink: /pages/82d273/
@ -29,13 +29,13 @@ Linux 文件系统是目录和文件的一种层次安排,目录的起点称
Linux 是一个**多用户系统**,操作系统本身的驻留程序存放在以根目录开始的专用目录中,有时被指定为系统目录。 **内核**、**Shell**和**文件结构**一起形成了 Linux 的基本操作系统结构。它们使得用户可以允许程序, 管理文件及使用系统。 Linux 是一个**多用户系统**,操作系统本身的驻留程序存放在以根目录开始的专用目录中,有时被指定为系统目录。 **内核**、**Shell**和**文件结构**一起形成了 Linux 的基本操作系统结构。它们使得用户可以允许程序, 管理文件及使用系统。
![image-20220320093722657](./assets/cbea6761a0164906b8396942cf61c664/image-20220320093722657.png) ![image-20220320093722657](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320093722657.png)
### 文件类型 ### 文件类型
在终端输入`ls -l`命令 系统会打印处当前目录下所有文件的信息。 在终端输入`ls -l`命令 系统会打印处当前目录下所有文件的信息。
![image-20220320100405899](./assets/cbea6761a0164906b8396942cf61c664/image-20220320100405899.png) ![image-20220320100405899](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320100405899.png)
这些信息包括:**文件类型**、**文件属性**、**用户名**、**用户所在组**、**文件大小**、**修改时间**、**文件名**等。 这些信息包括:**文件类型**、**文件属性**、**用户名**、**用户所在组**、**文件大小**、**修改时间**、**文件名**等。
@ -59,7 +59,7 @@ Linux 是一个**多用户系统**,操作系统本身的驻留程序存放在
文件系统的创建: 文件系统的创建:
![image-20220320100449488](./assets/cbea6761a0164906b8396942cf61c664/image-20220320100449488.png) ![image-20220320100449488](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320100449488.png)
### 基于文件描述符的 IO 操作 ### 基于文件描述符的 IO 操作
@ -97,35 +97,35 @@ Linux 是一个**多用户系统**,操作系统本身的驻留程序存放在
返回值:若成功则返回文件描述符,若出错则返回-1。其中参数`pathname`是一个字符串指针,指向需要打开(或创建)文件的**绝对路径名**或**相对路径名**。 返回值:若成功则返回文件描述符,若出错则返回-1。其中参数`pathname`是一个字符串指针,指向需要打开(或创建)文件的**绝对路径名**或**相对路径名**。
![image-20220320101157474](./assets/cbea6761a0164906b8396942cf61c664/image-20220320101157474.png) ![image-20220320101157474](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320101157474.png)
![image-20220320102217610](./assets/cbea6761a0164906b8396942cf61c664/image-20220320102217610.png) ![image-20220320102217610](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320102217610.png)
`mode`取值: `mode`取值:
![image-20220320102222415](./assets/cbea6761a0164906b8396942cf61c664/image-20220320102222415.png) ![image-20220320102222415](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320102222415.png)
###### 案例程序 ###### 案例程序
![image-20220320102302686](./assets/cbea6761a0164906b8396942cf61c664/image-20220320102302686.png) ![image-20220320102302686](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320102302686.png)
将`FLAGS`定义为:只写,不存在则创建,文件长度截短为 0。 将`FLAGS`定义为:只写,不存在则创建,文件长度截短为 0。
定义`mode`:创建文件的权限为用户读写执行,组读、执行,其他用户读、执行。 定义`mode`:创建文件的权限为用户读写执行,组读、执行,其他用户读、执行。
![image-20220320102333633](./assets/cbea6761a0164906b8396942cf61c664/image-20220320102333633.png) ![image-20220320102333633](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320102333633.png)
运行程序后创建一个新文件:`test.txt`。 运行程序后创建一个新文件:`test.txt`。
查看其权限属性,可见恰好与创建时定义的 mode 吻合。 查看其权限属性,可见恰好与创建时定义的 mode 吻合。
![image-20220320102355312](./assets/cbea6761a0164906b8396942cf61c664/image-20220320102355312.png) ![image-20220320102355312](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320102355312.png)
##### creat 函数 ##### creat 函数
用于创建文件。 用于创建文件。
![image-20220320101227035](./assets/cbea6761a0164906b8396942cf61c664/image-20220320101227035.png) ![image-20220320101227035](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320101227035.png)
函数原型:`creat(const char *pathname,int flags);` 函数原型:`creat(const char *pathname,int flags);`
@ -139,7 +139,7 @@ Linux 是一个**多用户系统**,操作系统本身的驻留程序存放在
close 函数用于关闭一个文件。 close 函数用于关闭一个文件。
![image-20220320101434997](./assets/cbea6761a0164906b8396942cf61c664/image-20220320101434997.png) ![image-20220320101434997](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320101434997.png)
若成功则返回 0若出错则返回-1。 若成功则返回 0若出错则返回-1。
@ -153,23 +153,23 @@ close 函数用于关闭一个文件。
系统默认设置位移量为 0。 系统默认设置位移量为 0。
![image-20220320101454081](./assets/cbea6761a0164906b8396942cf61c664/image-20220320101454081.png) ![image-20220320101454081](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320101454081.png)
可以调用`lseek`函数显式地定位一个打开文件 若成功则返回新的文件位移量,出错则返回-1。 可以调用`lseek`函数显式地定位一个打开文件 若成功则返回新的文件位移量,出错则返回-1。
l 表示长整型 参数`fd`表示已打开文件的描述符,参数`offset`表示位移量大小,单位字节,对参数`offset`的解释于参数`whence`的取值有关。 l 表示长整型 参数`fd`表示已打开文件的描述符,参数`offset`表示位移量大小,单位字节,对参数`offset`的解释于参数`whence`的取值有关。
![image-20220320101504852](./assets/cbea6761a0164906b8396942cf61c664/image-20220320101504852.png) ![image-20220320101504852](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320101504852.png)
可见当`whence`取`SEEK_CUR`和`SEEK_END`时,可以取负值。 可见当`whence`取`SEEK_CUR`和`SEEK_END`时,可以取负值。
###### 测试程序 ###### 测试程序
![image-20220320102440403](./assets/cbea6761a0164906b8396942cf61c664/image-20220320102440403.png) ![image-20220320102440403](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320102440403.png)
该程序可测试标准输入能否被设置成偏移量: 该程序可测试标准输入能否被设置成偏移量:
![image-20220320102453240](./assets/cbea6761a0164906b8396942cf61c664/image-20220320102453240.png) ![image-20220320102453240](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320102453240.png)
默认标准输入是键盘 从程序的运行结果看出 对于标准输入一般不能设置位移量。 默认标准输入是键盘 从程序的运行结果看出 对于标准输入一般不能设置位移量。
@ -189,7 +189,7 @@ l 表示长整型 参数`fd`表示已打开文件的描述符,参数`offset`
从打开文件中读取数据返回:读到的字节数,若已到文件尾返回 0若出错为-1。 从打开文件中读取数据返回:读到的字节数,若已到文件尾返回 0若出错为-1。
![image-20220320095118775](./assets/cbea6761a0164906b8396942cf61c664/image-20220320095118775.png) ![image-20220320095118775](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320095118775.png)
- 其中参数`fd`表示要进行读操作的文件的描述符; - 其中参数`fd`表示要进行读操作的文件的描述符;
- `buf`是一个指向缓冲区的指针,该缓冲区存放将要读取到中断的数据; - `buf`是一个指向缓冲区的指针,该缓冲区存放将要读取到中断的数据;
@ -206,29 +206,29 @@ l 表示长整型 参数`fd`表示已打开文件的描述符,参数`offset`
##### write 函数 ##### write 函数
![image-20220320095155376](./assets/cbea6761a0164906b8396942cf61c664/image-20220320095155376.png) ![image-20220320095155376](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320095155376.png)
打开文件写入数据,若成功则返回写的字节数,若出错为-1。 打开文件写入数据,若成功则返回写的字节数,若出错为-1。
![image-20220320095200261](./assets/cbea6761a0164906b8396942cf61c664/image-20220320095200261.png) ![image-20220320095200261](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320095200261.png)
对于普通文件 ,写操作从文件的当前位移量处开始,如果在打开该文件时,指定了 O_APPEND 选择项,则在每次写操作之前,将文件位移量设置在文件的当前结尾处。在一次成功操作写之后,该文件位移量增加实际写的字节数。 对于普通文件 ,写操作从文件的当前位移量处开始,如果在打开该文件时,指定了 O_APPEND 选择项,则在每次写操作之前,将文件位移量设置在文件的当前结尾处。在一次成功操作写之后,该文件位移量增加实际写的字节数。
###### 案例程序 ###### 案例程序
![image-20220320103210374](./assets/cbea6761a0164906b8396942cf61c664/image-20220320103210374.png) ![image-20220320103210374](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320103210374.png)
![image-20220320103621058](./assets/cbea6761a0164906b8396942cf61c664/image-20220320103621058.png) ![image-20220320103621058](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320103621058.png)
###### 另外的程序 ###### 另外的程序
![image-20220320105413049](./assets/cbea6761a0164906b8396942cf61c664/image-20220320105413049.png) ![image-20220320105413049](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320105413049.png)
该程序首先打开(或创建)文件`/home/hwx/test.txt`接着调用 write 函数将缓冲区 1 的数据写入文件,此时写入的数据长度为 10然后调用 lseek 定位文件,文件偏移量为 50并从文件开头计算偏移值最后调用 write 将缓冲区 2 的数据也写入文件,写入的数据长度也为 10。 该程序首先打开(或创建)文件`/home/hwx/test.txt`接着调用 write 函数将缓冲区 1 的数据写入文件,此时写入的数据长度为 10然后调用 lseek 定位文件,文件偏移量为 50并从文件开头计算偏移值最后调用 write 将缓冲区 2 的数据也写入文件,写入的数据长度也为 10。
在第二次写入数据时 之间 40 字节的内容为空 文件的总长度为 60 成功运行程序后 利用 ls 和 od 命令可以检验出: 在第二次写入数据时 之间 40 字节的内容为空 文件的总长度为 60 成功运行程序后 利用 ls 和 od 命令可以检验出:
![image-20220320105426083](./assets/cbea6761a0164906b8396942cf61c664/image-20220320105426083.png) ![image-20220320105426083](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320105426083.png)
使用 od 命令观察该文件的实际内容。(命令行中的-c 标志表示以字符方式打印文件内容) 使用 od 命令观察该文件的实际内容。(命令行中的-c 标志表示以字符方式打印文件内容)
@ -238,7 +238,7 @@ l 表示长整型 参数`fd`表示已打开文件的描述符,参数`offset`
Linux 的文件系统具有比较复杂的属性,包括**文件访问权限**、**文件所有者**、**文件名本身**、**文件长度**等。 Linux 的文件系统具有比较复杂的属性,包括**文件访问权限**、**文件所有者**、**文件名本身**、**文件长度**等。
![image-20220320101732493](./assets/cbea6761a0164906b8396942cf61c664/image-20220320101732493.png) ![image-20220320101732493](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320101732493.png)
改变文件访问权限:`chmod`、`fchmod`这两个函数使用户可以更改现存文件的存取许可权 改变文件访问权限:`chmod`、`fchmod`这两个函数使用户可以更改现存文件的存取许可权
@ -248,13 +248,13 @@ Linux 的文件系统具有比较复杂的属性,包括**文件访问权限**
为了改变一个文件的访问许可权位 进位的有效用户 ID 必须等于文件的所有者(User)或者该进程必须具有 root 权限。 为了改变一个文件的访问许可权位 进位的有效用户 ID 必须等于文件的所有者(User)或者该进程必须具有 root 权限。
![image-20220320101745292](./assets/cbea6761a0164906b8396942cf61c664/image-20220320101745292.png) ![image-20220320101745292](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320101745292.png)
当前`test.txt`文件权限: 当前`test.txt`文件权限:
![image-20220320101820792](./assets/cbea6761a0164906b8396942cf61c664/image-20220320101820792.png) ![image-20220320101820792](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320101820792.png)
![image-20220320101824816](./assets/cbea6761a0164906b8396942cf61c664/image-20220320101824816.png) ![image-20220320101824816](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320101824816.png)
可见运行程序后文件权限被改变。 可见运行程序后文件权限被改变。
@ -264,9 +264,9 @@ Linux 系统中所有文件都有一个与之对应的索引节点,该节点
这些信息被保存在 stat 结构体中,可以通过调用下面 3 个 stat 函数来返回文件的信息: 这些信息被保存在 stat 结构体中,可以通过调用下面 3 个 stat 函数来返回文件的信息:
![image-20220320101844194](./assets/cbea6761a0164906b8396942cf61c664/image-20220320101844194.png) ![image-20220320101844194](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320101844194.png)
![image-20220320101854044](./assets/cbea6761a0164906b8396942cf61c664/image-20220320101854044.png) ![image-20220320101854044](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320101854044.png)
**stat**函数、**fstat**函数和**lstat**函数。 **stat**函数、**fstat**函数和**lstat**函数。
@ -312,4 +312,4 @@ Linux 系统中所有文件都有一个与之对应的索引节点,该节点
这提供了一种机制,保证进程是打开文件的创建者。对文件是否存在的检查和创建文件属于同一原子操作。 这提供了一种机制,保证进程是打开文件的创建者。对文件是否存在的检查和创建文件属于同一原子操作。
![image-20220320100348242](./assets/cbea6761a0164906b8396942cf61c664/image-20220320100348242.png) ![image-20220320100348242](./_assets/cbea6761a0164906b8396942cf61c664/image-20220320100348242.png)

View file

@ -5,7 +5,7 @@ pubDate: 2022-04-05 13:13:35
categories: categories:
- 技术 - 技术
- Linux - Linux
cover: ./assets/f835945d5de246bcabdff51dd984aaf2/20220320105749.png cover: ./_assets/f835945d5de246bcabdff51dd984aaf2/20220320105749.png
tid: linux-note-process tid: linux-note-process
description: 有关linux进程的一系列笔记。 description: 有关linux进程的一系列笔记。
permalink: /pages/324bec/ permalink: /pages/324bec/
@ -29,21 +29,21 @@ tags:
可以输入`ps`命令来查看正在运行的进程: 可以输入`ps`命令来查看正在运行的进程:
![process-1](./assets/f835945d5de246bcabdff51dd984aaf2/process-1.png) ![process-1](./_assets/f835945d5de246bcabdff51dd984aaf2/process-1.png)
![process-2](./assets/f835945d5de246bcabdff51dd984aaf2/process-2.png) ![process-2](./_assets/f835945d5de246bcabdff51dd984aaf2/process-2.png)
`ps -aue`命令可以查看更为详细的信息: `ps -aue`命令可以查看更为详细的信息:
![process-3](./assets/f835945d5de246bcabdff51dd984aaf2/process-3.png) ![process-3](./_assets/f835945d5de246bcabdff51dd984aaf2/process-3.png)
`top`命令可以实时查看正在运行的程序: `top`命令可以实时查看正在运行的程序:
![process-4](./assets/f835945d5de246bcabdff51dd984aaf2/process-4.png) ![process-4](./_assets/f835945d5de246bcabdff51dd984aaf2/process-4.png)
在终端输入`top`,输入 q 可以退出: 在终端输入`top`,输入 q 可以退出:
![process-5](./assets/f835945d5de246bcabdff51dd984aaf2/process-5.png) ![process-5](./_assets/f835945d5de246bcabdff51dd984aaf2/process-5.png)
Linux 系统上可以管理多个进程,进程被分时分片处理。 Linux 系统上可以管理多个进程,进程被分时分片处理。
@ -51,15 +51,15 @@ Linux 系统上可以管理多个进程,进程被分时分片处理。
1. `system`函数可以在命令行中执行命令,可以借此来创建一个进程,不作赘述 1. `system`函数可以在命令行中执行命令,可以借此来创建一个进程,不作赘述
![process-6](./assets/f835945d5de246bcabdff51dd984aaf2/process-6.png) ![process-6](./_assets/f835945d5de246bcabdff51dd984aaf2/process-6.png)
2. `fork`函数、`vfork`函数 创建子进程: 当前进程是父进程,被创建进程是子进程,创建完后父子进程通知执行 2. `fork`函数、`vfork`函数 创建子进程: 当前进程是父进程,被创建进程是子进程,创建完后父子进程通知执行
![process-7](./assets/f835945d5de246bcabdff51dd984aaf2/process-7.png) ![process-7](./_assets/f835945d5de246bcabdff51dd984aaf2/process-7.png)
3. `exec`家族 3. `exec`家族
![process-8](./assets/f835945d5de246bcabdff51dd984aaf2/process-8.png) ![process-8](./_assets/f835945d5de246bcabdff51dd984aaf2/process-8.png)
这些函数都可以创建一个进程,暂且不展开描述。 这些函数都可以创建一个进程,暂且不展开描述。
@ -91,11 +91,11 @@ int main(void)
运行这个程序,程序已经打印出了进程号: 运行这个程序,程序已经打印出了进程号:
![process-9](./assets/f835945d5de246bcabdff51dd984aaf2/process-9.png) ![process-9](./_assets/f835945d5de246bcabdff51dd984aaf2/process-9.png)
这里有必要明确一下`fork`函数的返回值: 这里有必要明确一下`fork`函数的返回值:
![process-10](./assets/f835945d5de246bcabdff51dd984aaf2/process-10.png) ![process-10](./_assets/f835945d5de246bcabdff51dd984aaf2/process-10.png)
根据 fork 函数的返回值来看是在子进程中还是父进程中,调用成功的话,父进程中返回值是子进程的 ID子进程中是 0。实际上这里 fork 返回了两次。 根据 fork 函数的返回值来看是在子进程中还是父进程中,调用成功的话,父进程中返回值是子进程的 ID子进程中是 0。实际上这里 fork 返回了两次。
@ -136,7 +136,7 @@ int main(void)
在代码中定义了一个变量 n初始值为 10子进程的 n 同样初始为 10 在代码中定义了一个变量 n初始值为 10子进程的 n 同样初始为 10
![process-11](./assets/f835945d5de246bcabdff51dd984aaf2/process-11.png) ![process-11](./_assets/f835945d5de246bcabdff51dd984aaf2/process-11.png)
下面谈谈僵尸进程。 下面谈谈僵尸进程。
@ -144,7 +144,7 @@ int main(void)
子进程结束前,会向父进程发送 SIGCHILD 信号,父进程收到信号后,回收子进程资源,然后父进程再结束。父进程可以写一个 wait 函数,等待子进程发送 SIGCHILD 信号。 子进程结束前,会向父进程发送 SIGCHILD 信号,父进程收到信号后,回收子进程资源,然后父进程再结束。父进程可以写一个 wait 函数,等待子进程发送 SIGCHILD 信号。
![process-12](./assets/f835945d5de246bcabdff51dd984aaf2/process-12.png) ![process-12](./_assets/f835945d5de246bcabdff51dd984aaf2/process-12.png)
如下是代码演示: 如下是代码演示:
@ -176,7 +176,7 @@ int main(void) {
终端输入`ps axj`可以查看系统中的守护进程: 终端输入`ps axj`可以查看系统中的守护进程:
![process-13](./assets/f835945d5de246bcabdff51dd984aaf2/process-13.png) ![process-13](./_assets/f835945d5de246bcabdff51dd984aaf2/process-13.png)
TPGID 为-1 的话,就说明是守护进程。 TPGID 为-1 的话,就说明是守护进程。
@ -259,11 +259,11 @@ int main(void)
在终端中编译运行: 在终端中编译运行:
![process-14](./assets/f835945d5de246bcabdff51dd984aaf2/process-14.png) ![process-14](./_assets/f835945d5de246bcabdff51dd984aaf2/process-14.png)
现在关闭终端,在命令行输入`ps -axj`,可以看到运行起来的守护进程还在运行: 现在关闭终端,在命令行输入`ps -axj`,可以看到运行起来的守护进程还在运行:
![process-15](./assets/f835945d5de246bcabdff51dd984aaf2/process-15.png) ![process-15](./_assets/f835945d5de246bcabdff51dd984aaf2/process-15.png)
这里要用`kill`杀掉进程。 这里要用`kill`杀掉进程。
@ -335,7 +335,7 @@ int main(void)
运行程序,可以看见子进程将父进程写入文件的数据都打印了出来: 运行程序,可以看见子进程将父进程写入文件的数据都打印了出来:
![process-16](./assets/f835945d5de246bcabdff51dd984aaf2/process-16.png) ![process-16](./_assets/f835945d5de246bcabdff51dd984aaf2/process-16.png)
下面讨论管道。 下面讨论管道。
@ -347,7 +347,7 @@ int main(void)
2. 将文件描述符号变成管道。 2. 将文件描述符号变成管道。
![process-17](./assets/f835945d5de246bcabdff51dd984aaf2/process-17.png) ![process-17](./_assets/f835945d5de246bcabdff51dd984aaf2/process-17.png)
```c ```c
#include <unistd.h> #include <unistd.h>
@ -394,7 +394,7 @@ int main(void)
上述代码的功能是父进程接收用户输入后传入管道,子进程从管道读出并显示。 上述代码的功能是父进程接收用户输入后传入管道,子进程从管道读出并显示。
![process-18](./assets/f835945d5de246bcabdff51dd984aaf2/process-18.png) ![process-18](./_assets/f835945d5de246bcabdff51dd984aaf2/process-18.png)
接着演示有名管道,流程如下: 接着演示有名管道,流程如下:
@ -407,7 +407,7 @@ int main(void)
| 删除管道文件 | | | 删除管道文件 | |
| | | | | |
![process-19](./assets/f835945d5de246bcabdff51dd984aaf2/process-19.png) ![process-19](./_assets/f835945d5de246bcabdff51dd984aaf2/process-19.png)
进程 A 的代码: 进程 A 的代码:
@ -491,10 +491,10 @@ int main(void)
运行结果: 运行结果:
![process-20](./assets/f835945d5de246bcabdff51dd984aaf2/process-20.png) ![process-20](./_assets/f835945d5de246bcabdff51dd984aaf2/process-20.png)
![process-21](./assets/f835945d5de246bcabdff51dd984aaf2/process-21.png) ![process-21](./_assets/f835945d5de246bcabdff51dd984aaf2/process-21.png)
![process-22](./assets/f835945d5de246bcabdff51dd984aaf2/process-22.png) ![process-22](./_assets/f835945d5de246bcabdff51dd984aaf2/process-22.png)
这里要注意的是,这个程序不能在共享的文件夹下运行,因为共享文件夹下不能创建管道。同时必须两个进程都打开,这个程序才能返回,否则会阻塞。先关闭读取端,会导致写入端结束而先关写入端,不会对读取端造成影响。 这里要注意的是,这个程序不能在共享的文件夹下运行,因为共享文件夹下不能创建管道。同时必须两个进程都打开,这个程序才能返回,否则会阻塞。先关闭读取端,会导致写入端结束而先关写入端,不会对读取端造成影响。

Some files were not shown because too many files have changed in this diff Show more