Linux
未读1. 创建内存映射区如果想要实现进程间通信,可以通过函数创建一块内存映射区,和管道不同的是管道对应的内存空间在内核中,而内存映射区对应的内存空间在进程的用户区(用于加载动态库的那个区域),也就是说进程间通信使用的内存映射区不是一块,而是在每个进程内部都有一块。
由于每个进程的地址空间是独立的,各个进程之间也不能直接访问对方的内存映射区,需要通信的进程需要将各自的内存映射区和同一个磁盘文件进行映射,这样进程之间就可以通过磁盘文件这个唯一的桥梁完成数据的交互了。
如上图所示:磁盘文件数据可以完全加载到进程的内存映射区也可以部分加载到进程的内存映射区,当进程A中的内存映射区数据被修改了,数据会被自动同步到磁盘文件,同时和磁盘文件建立映射关系的其他进程内存映射区中的数据也会和磁盘文件进行数据的实时同步,这个同步机制保障了各个进程之间的数据共享。
使用内存映射区既可以进程有血缘关系的进程间通信也可以进程没有血缘关系的进程间通信。创建内存映射区的函数原型如下:
123#include <sys/mman.h>// 创建内存映射区void *mmap(void *addr, si ...
1. 管道管道的是进程间通信(IPC - InterProcess Communication)的一种方式,管道的本质其实就是内核中的一块内存(或者叫内核缓冲区),这块缓冲区中的数据存储在一个环形队列中,因为管道在内核里边,因此我们不能直接对其进行任何操作。
因为管道数据是通过队列来维护的,我们先来分析一个管道中数据的特点:
管道对应的内核缓冲区大小是固定的,默认为4k(也就是队列最大能存储4k数据)
管道分为两部分:读端和写端(队列的两端),数据从写端进入管道,从读端流出管道。
管道中的数据只能读一次,做一次读操作之后数据也就没有了(读数据相当于出队列)。
管道是单工的:数据只能单向流动, 数据从写端流向读端。
对管道的操作(读、写)默认是阻塞的
读管道:管道中没有数据,读操作被阻塞,当管道中有数据之后阻塞才能解除
写管道:管道被写满了,写数据的操作被阻塞,当管道变为不满的状态,写阻塞解除
管道在内核中, 不能直接对其进行操作,我们通过什么方式去读写管道呢?其实管道操作就是文件IO操作,内核中管道的两端分别对应两个文件描述符,通过写端的文件描述符把数据写入到管道 ...
1. 进程概述从严格意义上来讲,程序和进程是两个不同的概念,他们的状态,占用的系统资源都是不同的。
程序:就是磁盘上的可执行文件文件, 并且只占用磁盘上的空间,是一个静态的概念。
进程:被执行之后的程序叫做进程,不占用磁盘空间,需要消耗系统的内存,CPU资源,每个运行的进程的都对应一个属于自己的虚拟地址空间,这是一个动态的概念。虚拟地址空间详解
1.1 并行和并发
CPU时间片
CPU在某个时间点只能处理一个任务,但是操作系统都支持多任务的,那么在计算机CPU只有一个的情况下是怎么完成多任务处理的呢?原理和古时候救济灾民的思路是一样的,每个人分一点,但是又不叫吃饱。
CPU会给每个进程被分配一个时间段,进程得到这个时间片之后才可以运行,使各个程序从表面上看是同时进行的。如果在时间片结束时进程还在运行,CPU的使用权将被收回,该进程将会被中断挂起等待下一个时间片。如果进程在时间片结束前阻塞或结束,则CPU当即进行切换,这样就可以避免CPU资源的浪费。
因此可以得知,在我们使用的计算机中启动的多个程序,从宏观上看是同时运行的,从微观上看由于CPU一次只能处理一个进程,所有它们是轮流 ...
1. 本地软件安装1.1 MinGW 编译套件
GCC官方提供的编译套件不能直接在 windows 上使用,推荐的解决方案是使用 MinGW。
MinGW 提供了一套简单方便的 Windows 下的基于 GCC 程序开发环境,并且 收集了一系列免费的 Windows 使用的头文件和库文件。它整合了 GNU 的工具集,特别是 GNU 程序开发工具,如经典 gcc, g++, make 等。MinGW 是完全免费的自由软件,它在 Windows 平台上模拟了 Linux 下 GCC 的开发环境,为 C++ 的跨平台开发提供了良好基础支持,为了在 Windows 下工作的程序员熟悉 Linux 下的 C++ 工程组织提供了条件。
如果小伙伴本地安装了Qt,并且使用的编译套件也是 MingW,那么就不需要在安装了,配置一下环境变量即可。
Qt环境变量配置
如果本地没有,那就必须老老实实的下载一个了,下载地址如下:
MinGW官方下载地址: https://osdn.net/projects/mingw/
第一步, 运行下载到本地的 MinGW 下载器,准备编译套件的下载。
...
众所周知,Linux的目录是一个树状结构,了解数据结构的小伙伴都明白,遍历一棵树最简单的方式是递归。在我们已经掌握了递归的使用方法之后,遍历树状目录也不是一件难事儿。
Linux给我们提供了相关的目录遍历的函数,分别为:opendir(), readdir(), closedir()。目录的操作方式和标准C库提供的文件操作步骤是类似的。下面来依次介绍一下这几个函数。
1. 目录三剑客1.1 opendir
在目录操作之前必须要先通过 opendir() 函数打开这个目录,函数原型如下:
1234#include <sys/types.h>#include <dirent.h>// 打开目录DIR *opendir(const char *name);
参数: name -> 要打开的目录的名字
返回值: DIR*, 结构体类型指针。打开成功返回目录的实例,打开失败返回 NULL
1.2 readdir
目录打开之后,就可以通过 readdir() 函数遍历目录中的文件信息了。每调用一次这个函数就可以得到目录中的一个文件信息,当目录中的文件信息被全部 ...
Linux
未读在Linux中只要调用open()函数就可以给被操作的文件分配一个文件描述符,除了使用这种方式Linux系统还提供了一些其他的 API 用于文件描述符的分配,相关函数有三个:dup, dup2, fcntl。
1. dup1.1 函数详解dup函数的作用是复制文件描述符,这样就有多个文件描述符可以指向同一个文件了。函数原型如下:
12#include <unistd.h>int dup(int oldfd);
参数: oldfd 是要被复制的文件描述符
返回值:函数调用成功返回被复制出的文件描述符,调用失败返回 -1
下图展示了 dup()函数具体行为, 这样不过使用 fd1还是使用fd2都可以对磁盘文件A进行操作了。
被复制出的新文件描述符是独立于旧的文件描述符的,二者没有连带关系。也就是说当旧的文件描述符被关闭了,复制出的新文件描述符还是可以继续使用的。
1.2 示例代码下面的代码中演示了通过dup()函数进行文件描述符复制, 并验证了复制之后两个新、旧文件描述符是独立的,二者没有连带关系。
1234567891011121314151617181 ...
众所周知,Linux是一个基于文件的操作系统,因此作为文件本身也就有很多属性,如果想要查看某一个文件的属性有两种方式:命令和函数。虽然有两种方式但是它们对应的名字是相同的,叫做stat。另外使用file命令也可以查看文件的一些属性信息。
1. file 命令
该命令用来识别文件类型,也可用来辨别一些文件的编码格式。它是通过查看文件的头部信息来获取文件类型,而不是像Windows通过扩展名来确定文件类型的。
命令语法如下:
12# 参数在命令中的位置没有限制$ file 文件名 [参数]
file 命令的参数是可选项, 可以不加, 常用的参数如下表:
参数
功能
-b
只显示文件类型和文件编码, 不显示文件名
-i
显示文件的 MIME 类型
-F
设置输出字符串的分隔符
-L
查看软连接文件自身文件属性
1.1 查看文件类型和编码格式使用不带任何选项的 file 命令,即可查看指定文件的类型和文件编码信息。
123456789101112131415# 空文件$ file 11.txt 11.txt: empty# 源文件, 编码格式为: ASCII$ ...
Linux
未读每个系统都有自己的专属函数,我们习惯称其为系统函数。系统函数并不是内核函数,因为内核函数是不允许用户使用的,系统函数就充当了二者之间的桥梁,这样用户就可以间接的完成某些内核操作了。
在前面介绍了文件描述符,在Linux系统中必须要使用系统提供的IO函数才能基于这些文件描述符完成对相关文件的读写操作。这些Linux系统IO函数和标准C库的IO函数使用方法类似,函数名称也类似,下边开始一一介绍。
1. open/close1.1 函数原型
通过open函数我们即可打开一个磁盘文件,如果磁盘文件不存在还可以创建一个新的的文件,函数原型如下:
1234567891011121314#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>/*open是一个系统函数, 只能在linux系统中使用, windows不支持fopen 是标准c库函数, 一般都可以跨平台使用, 可以这样理解: - 在linux中 fopen底层封装了Linux的系统API open - 在window中, ...
1. 虚拟地址空间虚拟地址空间是一个非常抽象的概念,先根据字面意思进行解释:
它可以用来加载程序数据(数据可能被加载到物理内存上,空间不够就加载到虚拟内存中)
它对应着一段连续的内存地址,起始位置为 0。
之所以说虚拟是因为这个起始的0地址是被虚拟出来的, 不是物理内存的 0地址。
虚拟地址空间的大小也由操作系统决定,32位的操作系统虚拟地址空间的大小为 232 字节,也就是4G,64位的操作系统虚拟地址空间大小为264 字节,这是一个非常大的数,感兴趣可以自己计算一下。当我们运行磁盘上一个可执行程序, 就会得到一个进程,内核会给每一个运行的进程创建一块属于自己的虚拟地址空间,并将应用程序数据装载到虚拟地址空间对应的地址上。
进程在运行过程中,程序内部所有的指令都是通过CPU处理完成的,CPU只进行数据运算并不具备数据存储的能力,其处理的数据都加载自物理内存,那么进程中的数据是如何进出入到物理内存中的呢?其实是通过CPU中的内存管理单元MMU(Memory Management Unit)从进程的虚拟地址空间中映射过去的。
1.1 存在的意义通过上边的介绍大家会感觉到一 ...
gdb 是由 GNU 软件系统社区提供的调试器,同 gcc 配套组成了一套完整的开发环境,可移植性很好,支持非常多的体系结构并被移植到各种系统中(包括各种类 Unix 系统与 Windows 系统里的 MinGW 和 Cygwin )。此外,除了 C 语言之外,gcc/gdb 还支持包括 C++、Objective-C、Ada 和 Pascal 等各种语言后端的编译和调试。 gcc/gdb 是 Linux 和许多类 Unix 系统中的标准开发环境,Linux 内核也是专门针对 gcc 进行编码的。
gdb 的吉祥物是专门捕杀 bug 的射手鱼,官方有这样一段描述:
For a fish, the archer fish is known to shoot down bugs from low hanging plants by spitting water at them.
作为一种鱼,射手鱼以喷水射下低垂的植物上的虫子而闻名。
GDB 是一套字符界面的程序集,可以使用命令 gdb 加载要调试的程序。 下面为大家介绍一些常用的GDB调试命令。
1. 调试准备项目 ...