![](https://img-blog.csdnimg.cn/20201014180756928.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
Linux
文章平均质量分 89
HHYX.
这个作者很懒,什么都没留下…
展开
-
线程池的简单实现
在学习使用stl容器的时候,我们见到了stl容器使用了内存池来进行时间优化,因为用户在使用new、malloc等向系统申请空间的时候,身份会发生变化,同时有可能要执行操作系统内的内存处理算法,这可能会比较耗时。于是使用了内存池来提前申请好大块内存空间,需要用户自行进行管理。与内存池类似,提前准备好的线程,用来随时处理任务,这就被称作线程池。线程池是线程的一种使用模式。线程过多会带来调度开销,从而影响缓存局部性和整体性能。而线程池中维护着多个线程,等待分配可并发执行的任务。这就避免了在处理短时间任务时创建和原创 2022-07-11 10:58:50 · 391 阅读 · 0 评论 -
Linux线程信号量
信号量的本质实际上就是一把计数器,可以用来描述临界资源中资源数目的大小,即最多能有多少资源可以分配给线程。临界资源可以被划分为一个一个的小资源,如果处理得当,有可能让多个线程同时访问临界资源的不同区域,从而实现并发。每个线程想访问临界资源,都需要先申请信号量资源,使用这个计数器可以实现对临界资源的预定机制。信号量也是一种特殊的数据类型—sem_t,信号量需要对其进行初始化操作,上图是对信号量进行初始化的函数,使用该参数需要控制的只有第一个和第三个参数即第一个参数传入需要进行初始化的信号量第二个参数p原创 2022-06-28 09:35:59 · 429 阅读 · 0 评论 -
生产者/消费者模型
生产者消费者模式是通过一个容器来解决生产者和消费者之间强耦合的关系。生产者和消费者彼此之间不直接通讯,而是通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者进行消费,而是先存到阻塞队列中。消费者不直接找生产者要数据,而是从阻塞队列中拿数据。阻塞队列就相当于一个缓冲区,将生产者和消费者之间进行解耦。如果有多个生产者或者多个消费者那么他们之间的关系如下:下面来简单实现一下生产者和消费者模型这里是使用阻塞队列来作为生产者和消费者的“交易场所”。因此需要先创建一个类。由于其可能存放的各种类型的数据或者原创 2022-06-23 16:47:58 · 1769 阅读 · 0 评论 -
Linux下的线程同步
在之前的博客中有介绍过线程互斥的概念,为了能安全的访问临界区资源,Linux可以对临界区资源进行加锁操作,但是这种操作可能会导致某个线程反复的申请锁,从而使其他线程没办法申请到锁,导致线程饥饿问题。为了解决这个问题,Linux引入了同步这个概念。同步指的是在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从而有效的避免饥饿问题。当一个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了。例如一个线程访问队列时,发现队列为空,它只能等待,直到其它线程将一个节点添加到队原创 2022-06-21 13:25:47 · 211 阅读 · 0 评论 -
Linux线程互斥
运行如下代码可以看到,这里是一个抢票的逻辑,让五个线程同时去抢100张票,如果对线程不加以限制的话,会产生票会变为负数也就是过度抢票的情况。这里就需要提到几个概念,例如像这里可以被多个线程的执行流共享的资源就叫做临界资源,其中每个线程对临界资源进行访问的代码就被叫做临界区。如果不对线程进行相关的限制,则会可能出现对临界资源的过度访问从而引发错误。因此Linux下的线程便有了互斥这个概念。互斥指的是在任何时刻,互斥可以保证有且仅有一个执行流能够进入临界区来访问临界资源,这样可以对临界资源起到保护作用。同时这原创 2022-06-07 22:26:21 · 536 阅读 · 0 评论 -
Linux线程控制
Linux下程序的执行被称为进程,而在一个进程内的一条执行路线就被称为线程,线程是一个进程内部的控制序列。每个进程最少有一个线程,这个线程被称为主线程。线程在进程内部运行,本质也是在进程地址空间内运行。进程是系统资源分配的基本单位,而线程是调度的基本单位,虽然线程共享进程数据,但是各个线程也有自己独有的一部分数据例如:上下文数据,栈,线程ID,寄存器等。进程和线程的关系如下图所示:线程作为一个执行流,理论上来说他也需要进程控制块类似的东西来进行控制线程的执行。但是Linux下的线程与Windows的不原创 2022-06-04 22:25:42 · 196 阅读 · 0 评论 -
信号的处理与捕捉
信号的处理与捕捉信号处理信号的产生信号的存放信号集信号集操作函数sigprocmasksigpending信号的捕捉signalsigaction信号处理信号的产生一般而言,Linux系统下信号产生有如下四种方式:键盘输入产生进程异常产生信号系统调用接口,如(kill,raise等)软件条件(管道,alarm等)信号的存放由于信号产生是异步的,信号可能随时会产生,但是操作系统并不能及时的去处理,这就需要要求进程有保存信号的能力。上一篇信号博客中讲解了进程存放信号的pending位图结构原创 2022-05-28 13:04:30 · 164 阅读 · 0 评论 -
信号的产生
信号产生信号概念信号捕捉信号产生键盘产生程序异常core dump系统调用产生信号软件条件产生信号总结信号概念在Linux系统下,信号是进程之间事件异步通知的一种方式,例如我们终止前台进程使用的ctrl+c,就是一种信号。再比如在管道通信中,读端关闭,写端也是收到了信号然后将进程关闭。包括在进行调试代码时,遇到的段错误或者浮点错误,都是操作系统发送了相对应的信号从而对进程进行相应的处理。Linux下的信号种类可以通过kill -l命令进行查询。信号一共有62种,前31种为普通信号,后31种为实时信号原创 2022-05-25 10:30:42 · 295 阅读 · 0 评论 -
system V——共享内存
共享内存system V共享内存共享内存函数接口shmgetkey手动查看/释放共享内存key和shmid区别shmctl挂接shmdtsystem VSystemV标准的进程间通信方式是在操作系统层面专门为进程间通信设计的一个方案。进程间通信的本质就是让不同的进程能够看到同一份资源。常见的system V结构的通信方式有如下几种:共享内存消息队列信号量这篇博客主要介绍基于共享内存的进程间通信方式。共享内存共享内存是通过某种调用,在内存中创建一份内存空间,然后通过函数调用,让需要参与进程通原创 2022-05-21 19:52:38 · 1252 阅读 · 0 评论 -
进程间通信——命名管道
命名管道命名管道定义命名管道创建命令行上创建程序内创建命名管道间通信匿名管道和命名管道区别命名管道定义上一篇博客中介绍了匿名管道的用法以及他的特点,但是它存在一定的限制,例如他只能在两个具有公共祖先的进程间进行通信例如父子进程。但是如果想要在不相关的两个进程之间进行数据交互,这可以使用命名管道。命名管道是一种特殊类型的文件命名管道创建命令行上创建创建命名管道可以直接在命令行上使用mkfifo命令来创建。创建结果如下,注意的是这里的文件类型是以p开头的。为了测试这个管道功能,可以将Linux原创 2022-05-06 10:20:04 · 3394 阅读 · 0 评论 -
进程间通信-匿名管道
匿名管道进程间通信进程间通信方式管道System V IPCPOSIX IPC管道创建管道匿名管道子进程不断写入,父进程不进行读取写端一直写入,读端完成一次读取后退出写端关闭,读端一直读取总结匿名管道特点进程间通信计算机系统中有很多进程,这些进程之间可能会存在特定的需要协同工作的场景,而这种一个进程把自己的数据交付给另一个进程,让其进行处理这就叫做进程间通信。但是进程具有独立性,我们想要让进程之间进行交互,成本一定很高,因此操作系统需要对通信方式进行一定的设计。那么如何设计才能让两个进程之间互相通信呢?原创 2022-05-04 10:01:06 · 288 阅读 · 0 评论 -
动/静态库初识
动/静态库三种时间AccessModifyChange应用动/静态库动/静态库概念库的命名动静态链接库的内容生成静态库静态库的使用安装库的命令指定库文件制作动态库动态库使用方法编译时给出路径设置环境变量设置系统路径设置配置文件三种时间之前Linux指令操作的博客中有提到过可以通过stat命令查看文件/目录的属性信息,其中有3种时间分别是Access、Modify以及Change时间,这三种时间有什么区别呢?AccessAccess为最后访问时间,但是在较新的Linux内核中,Access时间不会被原创 2022-05-02 10:33:34 · 217 阅读 · 0 评论 -
软/硬链接
软硬链接磁盘文件结构管理方式Super BlockGroup Descriptor TableData blocksinode Tableinode BitmapBlock Bitmap目录删除文件软硬链接软链接硬链接软硬链接区别硬链接数目录链接数磁盘文件结构磁盘是计算机中的一个重要的机械设备,文件在没有运行起来的时候,一般都是存放在磁盘上的。一个文件的构成是由文件属性和文件内容构成的。磁盘可以认为是一种线性结构,他的基本单元是扇区,各个扇区可以近似的认为是类似于数组的一种结构。管理方式磁盘是一个原创 2022-04-30 10:55:21 · 139 阅读 · 0 评论 -
缓冲区概念
缓冲区标准错误缓冲区刷新策略重定向问题fork子进程标准错误上一篇系统IO的博客中,介绍了系统默认打开的三种文件描述符:标准输入,标准输出和标准错误,但是在测试的时候发现,把文件内容重定向到标准输出和标准错误时,都能在屏幕上打印出来,例如: const char* msg1="hello 标准输出\n"; write(1,msg1,strlen(msg1)); const char* msg2="hello 标准错误\n"; write(2,msg2,strlen(msg2));那原创 2022-04-28 09:55:31 · 374 阅读 · 0 评论 -
系统 IO
系统IOopen系统调用和库函数文件描述符文件描述符分配规则重定向dup2输出重定向追加重定向输入重定向open上一篇系统和文件IO博客中,我们使用过open这个函数接口,那么这个接口里面的参数和返回值又有什么意义呢?和文件IO使用的fopen又有什么区别呢?根据man手册查询结果来看,其中pathname即为要打开或者创建的目标文件的路径。flags为打开文件的各种选项类似于文件IO中的只读只写等选项,这里可以传入多个常量使用或运算构成flags。O_RDONLY: 只读打开O_WRONLY原创 2022-04-26 10:20:50 · 110 阅读 · 0 评论 -
文件/系统IO操作
文件/系统IO文件读写操作写文件读文件追加写入标准输入输出流系统IO写文件读文件接口函数openflagclosewriteread文件读写操作C语言中有介绍过进行文件读写的操作,下面来一段代码演示一下文件读写操作。写文件这里向log.txt文件中写入信息,如果文件不存在则会自动创建 FILE* fp=fopen("./log.txt","w"); if(fp==NULL) { perror("fopen"); return 1; } int count=10; wh原创 2022-04-24 10:38:23 · 140 阅读 · 0 评论 -
模拟实现shell
shellshell原理打印提示符获取命令行字符串解析字符串内建命令执行第三方命令总结这里我们可以看到,运行我们模拟实现的简易的shell之后可以像正常使用一样,在命令行上输入各种命令,来实现我们需要的功能。shell原理一个shell的运行大概需要分为如下几个阶段:获取命令行解析命令行建立一个子进程(fork)替换子进程(execvp)父进程等待子进程退出(wait)根据这些阶段,结合之前所学的进程相关知识,我们用代码来实现一个简易的shell。打印提示符我们在使用Linux时原创 2022-04-18 12:40:12 · 1614 阅读 · 0 评论 -
进程控制——进程替换
进程替换替换函数替换函数参数替换函数实例execlexecvexeclpexecvpexecve子进程发生程序替换总结之前我们学过使用fork来创建子进程,这种创建后的子进程会和父进程执行相同的程序,但有可能执行不同的代码分支,但是创建子进程仅仅只是为了做到这一点么?我们还可以使用进程替换,使用进程替换后的子进程会开始执行另外一个程序,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。使用进程替换并不创建新进程,所以进程替换前后该进程的id并未改变。替换函数使用替换函数后,进程原创 2022-04-16 09:31:19 · 498 阅读 · 0 评论 -
进程控制—终止和等待
进程控制进程终止进程退出场景退出码错误码退出程序exitreturn_exit总结进程等待进程等待必要性等待命令waitwaitpid退出状态阻塞等待进程终止进程退出场景我们常见的进程退出场景有如下几种:代码运行完毕,结果正确代码运行完毕,结果不正确代码异常终止退出码我们可以通过echo $?来查看最近一次进程退出时的退出码。这里使用一段代码来看看我们编写的函数的退出码是什么?#include<stdio.h>int main(){ printf("hello wor原创 2022-04-14 10:58:04 · 1178 阅读 · 0 评论 -
进程地址空间
进程地址空间空间结构进程虚拟地址空间虚拟地址空间地址空间存在意义空间结构这样的空间分配图我想很多人都见过,那么可能有的人对这个不同区域空间增长的概念还没有清除的认识,下面我用代码来演示各种类型的变量地址的分布情况。#include<stdio.h>#include<unistd.h>#include<string.h>#include<stdlib.h>int g_unval;int g_val=100;int main(){ co原创 2022-04-12 08:57:14 · 99 阅读 · 0 评论 -
环境 变量
环境变量环境变量常见的环境变量PATH添加环境变量路径HOMESHELL查看环境变量环境变量常见命令echoexportenvunsetset命令行参数通过代码获取环境变量env[]environgetenv环境变量全局属性经过之前的学习我们知道在Linux系统下命令、程序、工具本质都是一个可执行文件,但是为什么我们在自己生成的可执行文件时,需要指定路径(加上./),而使用系统命令(ls,touch,mkdir等)时候直接使用即可呢?这是因为系统设置了环境变量。环境变量环境变量:一般是指在操作系统中用原创 2022-04-10 10:34:04 · 598 阅读 · 0 评论 -
进程的状态
进程状态意义具体状态状态演示R状态S状态Z状态孤儿进程kill命令常见kill命令使用kill -19:暂停进程kill -18:继续进程运行队列和等待队列如上,这是一幅常见的进程执行状态的示意图,在进程控制块一节中讲过进程的状态信息存储在task_struct也就是PCB 中。意义进程状态的意义:方便操作系统快速判断进程,完成特定的功能,比如调度,本质是一种分类具体状态R:运行态,不一定正在占用CPU: 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里S:睡眠状态,意味着原创 2022-04-08 08:48:07 · 2064 阅读 · 0 评论 -
fork创建子进程
创建子进程fork的使用子进程创建原理子进程用途fork常规用法fork失败原因从man手册来看,fork命令是用来创建子进程的,那么怎么使用fork命令以及子进程和父进程有什么区别呢?fork的使用从手册中看到,fork命令使用时需要包含一个unistd.h的头文件,并且返回值是pid_t的类型。这里的pid_t类型可以简单的被认为是一个整型。这里的返回值一般有3种,fork命令会给父进程返回子进程的pid一般是大于0的数字,给子进程返回0,如果创建失败则会返回小于0的数字。代码样例如下:原创 2022-04-06 09:04:45 · 942 阅读 · 0 评论 -
进程控制块
进程控制模块查看进程PCB内部构成标识符ppid状态优先级查看优先级方式优先级确定原理调整优先级nice值范围程序计数器内存指针上下文数据时间片上下文数据I/O状态信息记账信息查看进程信息进程:加载到内存的程序,就叫做进程,系统中会存在大量进程,操作系统要对进程进行管理,操作系统管理进程的方式:先描述再组织,因此任何进程在形成的时候,操作系统要为该进程创建PCB(进程控制块)。查看进程ps axj | head -1 && ps axj | grep "test"该命令可以查看g原创 2022-04-04 08:55:35 · 4501 阅读 · 0 评论 -
Linux的系统概念
冯.诺依曼体系我们常见的计算机以及服务器大部分都遵守冯诺依曼体系结构,他们都是由一个个硬件组成的,下面是冯诺依曼体系的结构图与数据流向图其中,输入设备有键盘、磁盘、网卡、显卡等设备输出设备有显示器、磁盘、网卡、显卡、音响等设备存储器(内存):需要注意的是这里的存储器指的是内存运算器和处理器(中央控制器):CPU内存这里的存储器指的是内存。不考虑缓存情况,CPU能且只能对内存进行读写,不能访问外设(输入或输出设备)外设(输入或输出设备)要输入或者输出数据,也只能写入内存或者从内存中读取。原创 2022-04-02 09:54:09 · 131 阅读 · 0 评论 -
制作进度条小程序
进度条程序注意事项回车和换行Linux刷新策略fflush编写思路代码样例编译代码make原理make使用这里我们来看一下如何制作一个动态增长的进度条小程序注意事项回车和换行要想做一个动态增长的进度条程序,我们需要了解一下Linux下的屏幕刷新策略执行下面一行代码我们可以看到程序在每间隔1秒的时候会换行打印从10到1的数字,但是进度条程序可不能进行换行打印,需要在同一行上打印,这时候就需要了解一下回车和换行的区别了。#include<stdio.h>#include<uni原创 2022-03-31 09:20:07 · 2288 阅读 · 0 评论 -
gdb:Linux下的调试器
gdb:Linux下的调试器gdb的使用常用选项:众所周知程序发布的模式一般有两种,debug模式和release模式。debug模式可以进行程序的调试,而release版本下编译器会对代码进行一些优化,调试起来某些细节可能容易忽略,所以一般使用debug模式对代码进行调试gdb的使用Linux gcc/g++编译出来的二进制程序,默认是release模式 ,要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项这是未加-g选项默认是release版本的调试情况,可以看到这里显示缺少原创 2022-03-29 08:53:03 · 258 阅读 · 0 评论 -
gcc/g++过程解析
gcc/g++的编译解析gcc使用方法gcc编译过程使用样例预处理阶段编译阶段汇编阶段链接直接形成可执行文件gcc常用选项链接查看文件使用的库库的种类静态链接动态链接安装静态库动/静态链接区别正常而言一个程序翻译的过程分为如下几个阶段:预处理,编译,汇编,链接。gcc是以C语言的形式编译程序,而g++是以C++的形式去编译程序,但是他们都需要经过以上几个阶段完成翻译。这里将以gcc作为样例来介绍编译的过程。gcc使用方法使用方法: gcc [选项] 要编译的文件 [选项] [目标文件直接使用gcc原创 2022-03-28 09:14:23 · 289 阅读 · 0 评论 -
vim的初识
vim的初识vim的功能vim的使用多模式编辑器常用模式:命令模式:底行模式:插入模式注意事项:vim的简单配置操作方法:常用配置选项:注意事项vim的功能vim作为一个文本编辑器,从定位上类似于记事本。使用vim命令可以查看当前环境是否安装了vim,默认正常情况下是安装的。vim的使用使用vim+文件名,如果文件存在则打开文件如果文件不存在则会自动创建文件。多模式编辑器常用模式:命令模式:命令模式是vim打开时默认进入的模式,左下角会有如下表示表示当前所处模式。该模式下主要进行控原创 2022-03-26 09:39:20 · 245 阅读 · 0 评论 -
Linux下的权限
Linux下的权限用户分类文件类型具体文件类型基本权限root用户:修改权限使用方法:通过8进制数字更改权限对于文件,权限的意义读权限写权限运行权限对于目录权限的意义更改文件拥有者/所属组chownchgrp一次性同时修改拥有者和所属组粘滞位使用方法使用场景作用默认权限权限掩码自定义默认权限什么是权限?权限就是一件事情是否允许被特定的人做,权限约束的对象是人,而文件本身具有天然的权限属性(r(可读) w(可写) x(可运行))。用户分类Linux下分别有3类用户:1、 拥有者:owner,文件和文件原创 2022-03-24 09:44:27 · 210 阅读 · 1 评论 -
Linux常用基本命令 -2
Linux常用基本命令cal常用选项:find命令常用选项grep命令常用选项zip/unzip命令:常用选项:tar命令:常用选项:使用方法:bc命令uname命令常用选项:history命令file命令su命令sudo命令继上一节讲述了Linux系统下的基本操作命令,这次主要介绍一下Linux下对文件的一些基本操作命令以及一些实用命令calcal:命令是用来用于查看日历等时间信息。常用选项:-3:显示系统前一个月,当前月,下一个月的日历-j:显示在当年中的第几天(一年日期按天算,从1月1原创 2022-03-22 12:37:47 · 778 阅读 · 0 评论 -
Linux的基本指令-1
Linux的基本指令ls指令:对于目录列出该目录下的所以子目录与文件 对于文件,列出文件名以及其他信息pwd:用来显示用户当前所在目录cd:跳转工作目录touch:创建普通文件mkdir:在当前目录下创建一个新的空目录rmdir:删除空目录rm:删除,可以同时删除文件或者目录which:查看特定指令的系统路径alias :别名whoami :确认当前登录用户man:查询Linux手册cp:拷贝命令 拷贝普通文件或者目录mv:剪切/重命名cat:查看文件内容(不打开文件)more:显示文本内容 文件较大时候将原创 2022-03-20 10:11:30 · 1110 阅读 · 0 评论