进程
1. 进程控制1.1 进程概述从严格意义上来讲,程序和进程是两个不同的概念,他们的状态,占用的系统资源都是不同的。
程序:就是磁盘上的可执行文件文件, 并且只占用磁盘上的空间,是一个静态的概念。
进程:被执行之后的程序叫做进程,不占用磁盘空间,需要消耗系统的内存,CPU资源,每个运行的进程的都对应一个属于自己的虚拟地址空间,这是一个动态的概念。
1.1.1 并行和并发
CPU时间片CPU在某个时间点只能处理一个任务,但是操作系统都支持多任务的,那么在计算机CPU只有一个的情况下是怎么完成多任务处理的呢?每个人分一点,但是又不叫吃饱。CPU会给每个进程被分配一个时间段,进程得到这个时间片之后才可以运行,使各个程序从表面上看是同时进行的。如果在时间片结束时进程还在运行,CPU的使用权将被收回,该进程将会被中断挂起等待下一个时间片。如果进程在时间片结束前阻塞或结束,则CPU当即进行切换,这样就可避免CPU资源的浪费。因此可以得知,在我们使用的计算机中启动的多个程序,从宏观上看是同时运行的,从微观上看由于CPU一次只能处理一个进程,所有它们是轮流执行的,只不过切换速度太快,感觉不到,因此C ...
文件IO
1. 文件描述符1.1 虚拟地址空间虚拟地址空间是一个非常抽象的概念,先根据字面意思进行解释:
它可以用来加载程序数据(数据可能被加载到物理内存上,空间不够就加载到虚拟内存中) 它对应着一段连续的内存地址,起始位置为 0。之所以说虚拟是因为这个起始的0地址是被虚拟出来的, 不是物理内存的0地址。
虚拟地址空间的大小也由操作系统决定,32位的操作系统虚拟地址空间的大小为 2^32^ 字节,也就是4G,64位的操作系统虚拟地址空间大小为2^64^ 字节,也就是16777216T。
当我们运行磁盘上一个可执行程序, 就会得到一个进程,内核会给每一个运行的进程创建一块属于自己的虚拟地址空间,并将应用程序数据装载到虚拟地址空间对应的地址上。
进程在运行过程中,程序内部所有的指令都是通过CPU处理完成的,CPU只进行数据运算并不具备数据存储的能力,其处理的数据都加载自物理内存那么进程中的数据是如何进出入到物理内存中的呢?其实是通过CPU中的内存管理单元MMU(Memory Management Unit)从进程的虚拟地址空间中映射过去的。
1.1.1 存在的意义为什么操作系统不直接将数据加 ...
线程同步异步和原子变量
1.线程的使用
C++11中增加了线程以及线程相关的类,支持了并发编程,提高了编写的多线程程序的可移植性C++11中提供的线程类叫做std::thread,基于这个类创建一个新的线程非常的简单,只需要提供线程函数或者函数对象即可,并且可以同时指定线程函数的参数。以下了解以下常用API
1.1 函数构造123456789// 1thread() noexcept;// 2thread(thread&& other) noexcept;// 3template< class Function, class... Args >explicit thread( Function&& f, Args&&... args );// 4thread( const thread& ) = delete;。
构造函数①:默认构造函数,构造一个线程对象,在这个线程中不执行任何处理动作
构造函数②:移动构造函数,将 other 的线程所有权转移给新的thread 对象。之后 other 不再表示执行线程。
构造函数③:创建线程对 ...
线程池
1. 线程池原理我们使用线程的时候就去创建一个线程,这样实现起来非常简便但是就会有一个问题:如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。
那么有没有一种办法使得线程可以复用:执行完一个任务,并不被销毁,而是可以继续执行其他的任务呢?
线程池是一种多线程处理形式,处理过程中将任务添加到队列在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。
在各个编程语言的语种中都有线程池的概念,并且很多语言中直接提供了线程池,作为程序猿直接使用就可以了,下面给大家介绍一下线程池的实现原理:
线程池的组成主要分为3个部分,这三部分配合工作 ...
线程同步
1. 线程同步的概念
假设有4个线程A、B、C、D,当前一个线程A对内存中的共享资源进行访问的时候,其他线程B, C, D都不可以对这块内存进行操作,直到线程A对这块内存访问完毕为止,B,C,D中的一个才能访问这块内存,剩余的两个需要继续阻塞等待,以此类推,直至所有的线程都对这块内存操作完毕。 线程对内存的这种访问方式就称之为线程同步通过概念的介绍,我们可以了解到所谓的同步并不是多个线程同时对内存进行访问,而是按照先后顺序依次进行的。
1.1 为什么要同步
两个线程交替数数(每个线程数50个数,交替数到100)的例子:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#in ...
tips
1. 线程介绍线程是轻量级的进程(LWP:light weight process),在Linux环境下线程的本质仍是进程。在计算机上运行的程序是一组指令及指令参数的组合,指令按照既定的逻辑控制计算机运行。操作系统会以进程为单位,分配系统资源,可以这样理解进程是资源分配的最小单位,线程是操作系统调度执行的最小单位。
从概念上来说线程和进程的区别:
进程有自己独立的地址空间, 多个线程共用同一个地址空间
线程更节省系统资源, 效率不仅可以保持, 而且能更高
在一个地址空间中多个线程独享: 每个线程都有属于自己的栈区, 寄存器(内核中管理的)
在一个地址空间中多个线程共享: 代码段, 堆区, 全局数据区, 打开的文件(文件描述符表)
线程是程序的最小执行单位, 进程是操作系统中最小的资源分配单位
每个进程对应一个虚拟地址空间,一个进程只能抢一个CPU时间片
一个地址空间中可以划分出多个线程, 能在有效的资源基础上, 抢更多的CPU时间片
CPU的调度和切换: 线程的上下文切换比进程要快的多上下文切换:进程/线程分时复用CPU时间片,在切换之前会将上一个任务的状 ...
GDB
gdb 是由 GNU 软件系统社区提供的调试器,同 gcc 配套 组成了一套完整的开发环境,可移植性好,支持非常多的体系结构并被移植到各种系统中(包括各种类 Unix 系统与 Windows 系统里的 MinGW 和 Cygwin此外,除了 C ,gcc/gdb 还支持包括 C++、Objective-C、Ada 和 Pascal 等语言后端的编译和调试。 gcc/gdb 是 Linux 和许多类 Unix 系统中的标准开发环境,Linux 内核也是专门针对 gcc 进行编码的。
GDB 是一套字符界面的程序集,可以使用命令 gdb 加载要调试的程序。
一、调试准备
项目程序如果是为调试而编译时, 必须要打开调试选项(-g)。-g选项的作用是在可执行文件中加入源代码信息,比如可执行文件中第几条机器指令对应源代码的第几行,但并不是把整个源文件嵌入到可执行文件中,所以在调试时必须保证gdb能找到源文件。习惯上如果是c程序就使用gcc编译, c++程序使用g++编译, 编译命令中添加上边提到的参数即可。另外还有一些可选项,eg: 在尽量不影响程序行为的情况下关掉 ...
Makefile
gcc命令进行单个文件的编译是比较方便的,但是如果文件数目众多就会显得冗余此时就可以借助make这个命令工具make就好比建筑工人,makefile就是蓝图,make照着makefile进行工程makefile文件的命名有Makefile和makefile
一、规则规则的基本语法格式
1234target1,target2,...:depend1,depend2,... command ....... .......
规则主要有三部分组成:目标(target),依赖(depend),命令(command)
目标(target) 通过执行规则中的命令,可以生成一个和目标同名的文件 规则可以有多个命令, 通过这多条命令来生成多个目标, 所有目标也可有很多个 通过执行命令,可以只执行一个动作,不生成任何文件,这样的目标被称为伪目标
依赖(depend) 如果规则的命令中不需要任何依赖,那么规则的依赖可以为空 当前规则中的依赖可以是其他规则中的某个目标,这样就形成了规则之间的嵌套 依赖可以根据要执行的命令的实际需求, 指定很多个
命令(command):一般来说是一 ...
静态库和动态库
一、静态库
Linux中静态库是由 ar 生成的现在的静态库已经不再普遍了,大部分程序都在使用动态库
Linux中静态库以 lib作为前缀, .a 作为后缀,即 libxxx.a
Windows中静态库一般以lib作为前缀, 以lib作为后缀,, 即 libxxx.lib
1.生成静态链接库
静态库的生成需要先对源文件进行汇编操作(gcc -c) 以得到二进制文件格式(.o) 然后通过ar工具将目标文件打包以得到静态库文件(libxxx.a)
ar工具创建静态库有三个参数
参数c:创建一个库,不管库是否存在,都将创建。
参数s:创建目标文件索引,这在创建较大的库时能加快时间。
参数r:在库中插入模块(替换)。默认新的成员添加在库的结尾处,如果模块名已经在库中存在,则替换同名的模块。
具体步骤如下
123456789#1.对源文件进行汇编,得到二进制(.o)文件gcc 源文件(*.c) -c #-c位置没有要求#2.将.o文件进行打包,得到静态库ar csr 静态库的名字(libxxx.a) 原材料(*.o)#3.发布静态库提供头文件 **.h文件提供静态库 l ...
gcc/g++
一、安装gcc1234567#Ubuntusudo apt update #更新本地的软件下载列表, 得到最新的下载地址sudo apt install gcc g++#centossudo yum update sudo yum install gcc g++
之所以更新下载列表,是因为这样可以下载最新的gcc g++ 以支持c++11
123456#两种方法查看gcc g++版本gcc -vgcc --versiong++ -vg++ --version
最低4.8.5的版本才支持C++11
二、gcc工作流程
gcc工作分为四步1.预处理: 在这个阶段主要做了三件事: 展开头文件 、宏替换 、去掉注释行这个阶段需要GCC调用预处理器来完成, 最终得到的还是源文件, 文本格式2.编译: 这个阶段需要GCC调用编译器对文件进行编译, 最终得到一个汇编文件3.汇编: 这个阶段需要GCC调用汇编器对文件进行汇编, 最终得到一个二进制文件4.链接: 这个阶段需要GCC调用链接器对程序需要调用的库进行链接, 最终得到一个可执行的二进制文件
文件名后缀
说明
gcc参数 ...