自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

大学生一枚

好好学习 天天向上

  • 博客(92)
  • 收藏
  • 关注

原创 I/O多路转接之select、poll、epoll详解

select是一个系统调用,用来进行I/O多路转接select可以让程序同时监视多个文件描述符上的事件是否就绪当监视的多个文件描述符中有一个或多个事件就绪时,select才会成功返回并将对应的文件描述符就绪的事件告知调用者。

2025-04-19 20:30:09 842

原创 [leetcode]第445场周赛

找到最近的人,z是不动的,我们需要知道,x 到 z 的距离和 y 到 z 的距离,又因为 x 和 y 的移动速度相同,所以,谁离 z 越近,越先到达 z 位置,排列前半部分字符串,也就是[0,mid),这样前半部分字符串就有序了,如果是奇数,则加上中间的字符s[mid],如果是偶数,则不用加。//m-i-1表示,从下标m位置,到下标i位置,之间的长度,都是左开右开(i,m);找到 s 的中点mid,如果 s 是奇数序列,mid是中点,如果是偶数序列,mid是偏右的中点。//统计前半部分字符出现的频率。

2025-04-13 18:04:40 1493

原创 八大排序——c++版

/算法原理: 一共排序n-1次,每一次排序,相邻元素两两比较,一共比较n-1-i次,最后排出一个元素放在数组末尾,n-1次后,排序完成。//算法原理: 需要选择n-1次基准元素,从下标为0开始选取,然后与未排序的元素比较,找到元素最小的下标,交换基准元素和最小元素,一次排序。//算法原理: 任取待排序元素中的某元素作为基准元素,使左边元素都小于基准元素,右边元素都大于基准元素,然后重复该过程,直到所有元素都。//算法原理: 从下标为1开始,令其为key,然后插入到已排序的元素中,找到应该插入的位置。

2025-04-07 21:27:43 812

原创 仿tcmalloc高并发内存池的实现

池化技术(Pooling Technique)是一种资源管理策略,通过预先分配和复用资源(如内存、线程、对象、连接等),减少资源创建和销毁的开销,从而提高系统性能和资源利用率。常见的池化技术有:内存池,线程池,连接池,对象池,缓存池等。

2025-03-15 14:43:04 738

原创 网络层IP协议

有IP地址,但是不进行路由控制的设备。:有IP地址,又能进行路由控制。:主机和路由器的统称。

2025-03-01 18:04:52 883

原创 传输层协议TCP

TCP全称为传输控制协议(Transmission Control Protocol),就是要对数据的传输进行一个详细的控制。

2025-03-01 09:54:32 900

原创 HTTPS协议原理

加密就是把明文(要传输的信息)进行一系列变换, 生成密文。解密就是把密文再进行一系列变换, 还原成明文。在这个加密和解密的过程中, 往往需要一个或者多个中间的数据, 辅助进行这个过程, 这样的数据称为密钥数字摘要(数据指纹),其基本原理是利用单向散列函数(Hash 函数)对信息进行运算, 生成一串固定⻓度的数字摘要。数字指纹并不是一种加密机制,但可以用来判断数据有没有被篡改。

2025-01-02 23:21:17 794

原创 HTTP cookie与session

HTTP Cookie是服务器发送到用户浏览器并保存在浏览器上的一小块数据,它会在浏览器之后向同一服务器再次发送请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态、记录用户偏好等.HTTP Cookie 和Session 都是用于在Web应用中跟踪用户状态的机制。Cookie是存储在客户端的,Session是储存在服务器端的。

2025-01-01 22:20:07 799

原创 传输层协议UDP

用的是二进制流的序列化和反序列化,因为传输层是属于操作系统的,而操作系统都是用C语言写的,在代码上具有统一性,所以结构体转成二进制,不会有语言上的差别,而在应用层,可能是两种不同语言的应用层传输,所以不建议转为二进制进行传输。0-1023:知名端口号,HTTP,FTP,SSH等这些广为使用的应用层协议,他们的端口号都是固定的,如果我们自己写的客户端要设置知名端口号,需要root权限,不过这一般是不允许的。根据报头的16位目的端口号,找到对应的服务进程,然后进行数据的处理。

2025-01-01 09:20:33 1032

原创 Typora基础使用教程

在图片设置中,选择指定文件路径,然后指定一个文件夹用来存放图片,${filename}表示当前文件名,指定的文件夹是存放所有图片的文件夹,然后这个文件夹下面有 以每个笔记命名的文件夹存放该笔记的图片,避免混淆。每次退出时,Typora都要询问是否要保存笔记,比较麻烦,可以在偏好设置里把自动保存打开,但是第一次需要保存笔记,最后系统就会自动保存了。有序列表是 1.+空格 然后输入内容,回车可以进入 2. 列表 ,连续连续两次回车,可以退出有序列表。英文的冒号+一些英文单词,会有一些特殊的符号,比如。

2025-01-01 09:19:52 451

原创 *(int**)是什么意思

(int**)arr 取到的就是前4 或 8 个字节的空间,arr 是指向这段空间开头的指针,(int**)arr 是把 arr 转化成 int**类型,但是 arr 的值还是不变呀,然后*(int**)arr 得到的空间还是 arr 所指向的空间,只不过类型变成了 int*类型,这样一来,就可以解决指针在不同平台下大小不一致的问题了,然后得到的这个空间可以用来存放下一段内存的地址,就可以把几个不连续的空间连接起来了。那么我们只有指向这段空间开头的指针 arr,怎么获取 前 4 或 8 个字节的空间呢?

2024-12-25 17:50:02 375

原创 应用层协议HTTP

所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。服务器无法根据客户端的请求找到资源(网页)。由于超载或系统维护,服务器暂时的无法处理客户端的请求。Header:请求的属性,冒号分割的键值对,每组属性之间用 \r\n 分隔,遇到空行表示 header 结束。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择。只能切换到更高级的协议,例如,切换到HTTP的新版本协议。

2024-12-12 22:50:00 1147

原创 进程间关系与守护进程

会话可以看作是一个或多个进程组的集合,一个会话可以包含多个进程组,每个会话也有一个会话 ID(SID)创建一个会话,一般会形成一个终端文件,然后关联一个 bash 进程,bash 进程单独一个进程组,会话 ID 一般是会话中第一个进程 的 ID,一般是 bash 进程 ID同一个会话中,可以同时存在多个进程组,但是,任何时刻只允许一个前台进程(组)运行,可以允许多个进程(组)后台运行后台运行进程。

2024-12-07 12:09:49 1011

原创 Socket编程

例如,如果服务器有多个网卡(每个网卡上有不同的 IP 地址),使用 INADDR_ANY 可以省去确定数据是从服务器上具体哪个网卡/IP 地址上面获取的。bind: 用于将一个套接字(socket)与一个特定的端口号(port)和IP地址(IP address)绑定起来。这个函数通常在服务器端使用,它从监听队列中取出第一个连接请求,并为这个新的连接创建一个新的套接字。这个函数将客户端的套接字与服务器的套接字关联起来,以便两者之间可以进行通信。设置每个请求包之间的时间间隔(单位:秒)。

2024-12-07 12:09:00 973

原创 网络基础概念

进程 ID 属于系统概念,技术上也具有唯一性,可以用来表示一个唯一的进程,但是这样做,会让系统进程管理和网络强耦合,不太好,所以不建议这样做。在网络角度,OSI七层模型其实非常完善,但是在实际操作过程中,会话层和表示层是不可能写入操作系统中的,所以在实践中,实际是四层协议。sockaddr 是一个通用的地址结构体,可以用来表示多种类型的地址,例如 IPv4 地址,IPv6 地址,Unix 域套接字地址。因为协议栈是分层的,所以,每层双方都会有协议,同层之间,互相认识对方的协议。

2024-11-26 20:56:03 688

原创 C++11——智能指针

在 C++中,智能指针如 unique_ptr 和 shared_ptr 默认使用 delete 或 delete[] 来释放内存,在一些场景下,delete 可能不适用,所以要定制删除器,lambda 表达式很适合作为删除器。这段代码出现了循环引用,会造成内存泄漏的问题,_next 指向 node2,_prev 指向 node1,谁也不先释放,引用计数也不为 0, 造成循环引用的现象,出现内存泄漏。是的,引用计数的加减是加锁保护的,但是指向的资源不是线程安全的。shared_ptr 的循环引用问题。

2024-11-20 16:39:25 773

原创 C++11——异常

一般情况下,抛出的异常都是派生类对象,异常捕获的是基类对象,派生类继承了基类,这样 catch 捕获的时候,只需要捕获基类对象就可以了public:, _id(id){}protected:int _id;return str;

2024-11-19 20:46:35 1082

原创 C++11————线程库

在 c++11 之前,涉及到多线程问题,都是和平台相关的,比如 windows 和 linux 下各自有自己的接口,这使得代码的可移植性比较差。在 c++11 中引入了线程库,使得 c++在编程时不需要依赖第三方库了函数名功能thread()构造一个线程对象,没有关联任何线程函数,即没有启动任何线程构造一个线程对象,并关联线程函数 fn,args1,args2, ... 为线程函数的参数get_id()获取线程 idjoinable()

2024-11-17 21:39:39 1708

原创 信号量和线程池

但对于长时间的任务,比如一个Telnet连接请求,线程池的优点就不明显了。况下,将产生大量线程,虽然理论上大部分操作系统线程数目最大值不是问题,短时间内产生大量线程可能使内存到达极限,出现错误.死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所占有的不会释放的资源而处于永久等待的一种状态。1. 需要大量的线程来完成任务,且完成任务的时间比较短。POSIX信号量,用与同步操作,达到无冲突的访问共享资源目的,POSIX信号量可以用于线程间同步。等待信号量,会将信号量的值-1。

2024-11-11 11:54:44 1416

原创 线程ID和线程库

在linux中,线程的运行可以用lwp来标识,只是操作系统的标识方法,lwp表示轻量级进程,在Linux中,进程和线程都可以用lwp来标识,而对于用户来说,也有对应的线程ID,

2024-11-04 23:22:29 337

原创 linux线程的认识

线程是一个进程内部的控制序列每个进程都至少有一个线程线程在进程内部运行,本质上是在进程地址空间运行通过进程虚拟地址空间可以看到进程的大部分资源,将进程资源合理的分配给每个执行流,就形成了线程执行流。

2024-11-02 23:11:29 670

原创 信号的保存和处理

我们先看看进程的虚拟地址空间,每个进程都会有一份pcb结构体,在linux在叫做task_struct,然后task_struct中储存着一个数组,叫做虚拟地址空间,虚拟地址空间中有用户空间和内核空间,用户空间通过页表与物理地址进行映射,而内核空间通过内核级页表与物理地址映射,内核级页表一般只需要维护一份就够了,其他进程的内核空间也可以通过这一份内核级页表进行映射,可以说,OS本身就在进程的地址空间中,但是我们访问内核空间需要受到一定限制,就是使用系统调用访问内核,进程从内核态返回到用户态的时候处理信号。

2024-10-30 22:15:19 924

原创 信号的理解

信号处理有三种:默认动作,忽略动作,自定义处理 大多数进程的默认动作是终止进程,但也有一些信号的处理是忽略,忽略动作就是对该信号忽略,自定义处理就是对于该信号,用户自己定义一个处理方式。这段代码,但我们执行ctrl+c时,相当于向进程发送了2号信号,然后通过signal函数,执行函数,get a sig: 2。自定义处理,就是利用signal函数,捕捉到信号发出,然后执行该信号所对应的动作,这个动作是用户自己设定的。从1号到31号是普通信号,剩下的都是实时信号,我们只考虑普通信号,剩下的不考虑,

2024-10-28 11:39:16 329

原创 命名管道和共享内存

system V 共享内存是一种进程间通信(IPC)机制,他允许多个进程共享一个给定的内存区域,这种通信方式非常高效,因为数据直接在进程间传递,无需数据复制,从而提高了数据传输的效率。管道应用的一个限制就是只能在具有共同祖先的进程间通信,如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它被称为命名管道,命名管道是一种特殊类型的文件。mkfifo函数可以创建明明管道,第一个参数是指定路径的文件名,第二个参数是创建管道文件的权限。命名函数由mkfifo函数创建,打开用open。

2024-10-27 10:44:04 333

原创 进程间通信——管道

我们可以使用pipe()系统来调用管道,一旦管道被创建,一个进程就可以在fd[1]上写数据,另一个进程在fd[0]上读数据,当我们打开一个文件时,会获得这个文件的fd,当我们以不同的方式打开同一个文件,我们会获得两个fd,但是都指向同一个文件。对于父进程,我们要关闭他的写进程,因为父进程只能读取数据,对于子进程,我们要关闭读进程,因为子进程只能写入数据。进程之间需要摸某种协同,协同的条件是通信,而通信也是有类别的,有通知就绪的,传递数据的,控制相关信息等等,这是一个简单的子进程写数据,父进程读数据,

2024-10-20 16:14:06 334

原创 软硬连接和动静态库

软连接和硬链接是两种不同的文件链接方式,他们提供了不同的方式来引用文件系统中的文件软连接:ln -s 要连接的文件路径+名称 链接文件名,类似于windows中的快捷方式link_mytest.txt就是一个链接文件,他存放的是指向文件的路径,如果我们把指向的文件删除,那么链接文件也就会失效了,硬链接:硬链接不是一个单独的文件,他本质是文件名和inode的一个映射,因为他的inode号和链接文件是一样的,当我们删除链接文件时,硬链接文件还可以使用,因为我们文件的inode号还在,还可以用。

2024-10-17 17:48:00 570

原创 文件系统理解

inode table:每个文件都有一个inode号,Linux中文件的属性是大小固定一个集合体,struct inode结构体用来储存文件属性,要找到一个文件,就要找到文件的inode号,inode号是以分区为单位的,也就是说,在一个分区中,inode号是唯一的,而inode table存放的就是文件的inode号,目录文件=属性+内容,我们知道,一个目录下不能有同名文件,查找文件的顺序是先有文件名,再找到inode号,所以是通过文件名来映射inode号,那么,我们inode编号是怎么来的呢?

2024-10-13 17:36:11 469

原创 stderr和磁盘理解

发现stdout打印到log.txt了,但是stderr还是打印到显示器上,因为我们重定向的是把文件标识符1给log.txt,而stderr的文件标识符是2,所以不影响,还是打印到显示器上,有了扇区对应的下标,我们就可以在磁盘中找到对应的文件了,对于操作系统来说,和磁盘交互时的基本单位是4KB,也就是8个连续的扇区,这8个连续的扇区称为块,磁盘,放在磁盘的文件就叫做磁盘文件,那么如何在磁盘中存储文件呢?磁盘读写的基本单位是扇区,大小一般是512字节,如何找到一个指定位置的扇区呢?

2024-10-13 17:35:35 562

原创 重定向的本质

会发现,本来应该打印到显示器上的内容,打印到文件"myfile"里面了,这是因为我们关闭了文件描述符1,然后打开一个文件,myfile的文件描述符就是1,所以,printf默认是向stdout输出的,但是stdout指向的文件描述符是1,所以就打印到myfile文件中了,这种现象叫做重定向输出。会发现fd是0或者2 ,可见文件描述符的分配规则是找到当前没有被使用的最小的一个下标,作为新的文件描述符,当我们打开一个文件,他的fd是3,因为0 1 2 已经被占用了,当我们关闭0 和 1 ,再看这段代码。

2024-09-29 13:01:24 357 1

原创 文件标识符fd

..:如果我们第二个参数使用了O_CREAT,那么第三个参数表示创建文件的权限,它通常与umask相结合来确定文件的最终权限,比如umask为0,第三个参数设置成0666,表示文件权限是rw-rw-rw-,我们用“w"的方式打开log.txt文件,如果这个文件不存在,就创建这个文件,如果文件存在,就把这个文件内容清空然后打开。我们理解了,每一个文件标识符标识一个文件,那么fd 0 1 2 的文件默认被打开了,是什么文件呢?打开文件的本质是进程打开文件,文件没有被打开时,在磁盘中。1:标准输出 显示器。

2024-09-17 18:08:52 1105 3

原创 编写myshell

shell的解释器本质就是一段代码,用来解释不同的指令,然后做做出相同的操作,下面我们自己编写一个简易的shell。

2024-09-16 19:18:52 203 1

原创 进程程序替换

可以看到,进程在运行到一半,最后一句的printf没有执行,这是为什么呢?因为程序被替换了exec*系列的函数,可以替换当前的程序,进程的程序替换,本质上还是那一个进程,进程不变,但是进程里的程序变了,要是把代码改成多进程版本,让子进程替换,那么父子共享的代码和数据,都要进行写时拷贝。

2024-09-16 19:17:47 641 1

原创 进程控制管理

进程出异常,本质上是操作系统给进程发出信号,一旦异常退出,退出码就没有意义了,要看操作系统给进程发出的退出信号,退出信号可以表示进程为什么异常退出,比如一个死循环的进程,我们可以用kill -9 进程pid 来向进程发出终止信号,那么进程就会异常退出,退出信号就是9,任何子进程,在退出时都要等待被父进程回收,子进程的代码和数据先释放,task_struct保留退出信息,等父进程回收,在这个过程中子进程处于Z状态,参数:输出型参数,获取子进程退出状态,如果不关心,可以设置成NULL,

2024-09-15 15:48:38 733

原创 程序地址空间

在操作系统内部,会有虚拟地址空间,通过页表的映射,访问物理内存空间,由于子进程拷贝的是父进程的数据,所以同一份代码,父子进程是共享的,当子进程要修改g_val的值时,又为了不影响父进程对g_val的使用,就有了写时拷贝,子进程会把父进程的很多数据结构都拷贝一份,包括虚拟地址空间,本质上虚拟地址空间也是一个结构体,当操作系统发现子进程的要更改的数据和父进程指向的数据冲突了,才会进行写时拷贝,在物理内存上开辟g_val的空间,子进程通过页表映射的物理内存地址也就和父进程页表映射的g_val的地址不一样了,

2024-09-15 15:47:37 948

原创 进程优先级和环境变量

命令行中启动的程序,都会变成进程,其实都是bash的子进程,父进程的数据,默认对于子进程是能看到并访问的,但是子进程的后续修改,对于父进程是看不到的,系统中的很多配置,在我们登录linux系统的时候,就已经被加载到bash进程中(内存),最开始的环境变量在配置文件中,然后被加载到bash中,nice的调整是有限制的,修改范围位[-20,19],而且每次调整优先级,PRI的值都是从80开始的,避免修改叠加。cpu资源分配的先后顺序,就是指进程的优先级,linux中进程的优先级数字越小,优先级越高;

2024-09-14 23:05:59 1437

原创 进程的基本概念

数据要在计算机结构进行传输,从一个设备到另一个设备,本质上是数据的拷贝,设备之间的拷贝效率决定了计算机的整体效率,当我们运算数据时,CPU直接从储存器读取数据,减少了数据从输入设备到CPU的传输时间,如果没有了储存器,直接从输入设备直接把数据传给CPU,那么CPU的运算效率远远大于输入设备的传输效率,这样计算机的整体效率就取决与数据传输的效率,就很慢了,所以这就是冯诺依曼的优秀之处。我们直接在命令行里启动的进程,他的父进程是bash,bash会自动回收结束的进程, 所以不会产生僵尸进程,

2024-09-14 23:04:44 1066

原创 git的使用和gdb工具

程序的发布模式有两种,debug和release,我们一般调试代码是用debug模式,由于gcc/g++编译出来的二进制文件默认是release模式,所以我们需要在后面加上-g选项,使其变成debug模式。gdb具有记忆功能,可以自动记忆上一个命令,点击回车可以执行下一个命令。disable/enable 断点编号:可以打开/关闭断点。list/l 行号/文件名:可以打印出代码在屏幕上。display 变量编号:可以把变量长显示在屏幕上。b 文件名/行号:在第几行打印断点。gdb 文件名:打开gdb工具。

2024-09-07 22:39:11 528 1

原创 linux编译器——gcc/g++

g++ -o mytest test.cpp 被执行,当我们再次make时,由于test.cpp是最新版本,所以他不会再执行了,因为有些函数是别人已经写好了,我们用的时候不用再重新写了,直接拿过来用就好了,这个写好的函数家就在库中放着,所以我们要链接库。make是一个命令,makefile是一个文件,make会根据makefile的内容,完成编译和清理工作,gcc --version 可以查看当前的版本 ,我们默认安装的是4.8.5的版本,比较低,-o指明生成文件的名字,可以自己命名,比如:my.exe。

2024-09-07 22:38:27 1126 1

原创 C++11——包装器和绑定

也就是说placeholders::_1永远表示传的第一个参数,placeholders::_2表示传的第二个参数,而对于fx函数来说,按照传参顺序,placeholders::_2表示a,placeholders::_1表示b,这样就实现了参数顺序的调换;std::bind定义在头文件里,是一个函数模板,他可以接受一个可调用对象,然后生成一个新的可调用对象,新的可调用对象的参数顺序或者参数个数可以发生改变,以此来适应原对象的参数列表,如果包装成员函数指针,需要注意哪些?

2024-08-09 20:54:41 461 1

原创 C++11新特性

如果你没有实现移动赋值重载函数,且没有实现拷贝构造,赋值重载和析构函数,那么编译器会默认生成移动赋值,默认生成的移动赋值函数,对对内置类型,会按字节拷贝,对自定义类型成员,要看这个成员是否实现移动赋值,如果实现了移动赋值就调用移动赋值,如果没有实现就调用拷贝赋值。返回值类型,函数可以自动推导,如果没有返回值,可以省略,如果有返回值,返回值明确的情况下,也可以省略,所以我们常见的写法都是省略了;左值是一个表示数据的表达式,通俗来说,可以被取地址的叫做左值,左值引用就是给左值取别名,

2024-08-09 20:53:51 988

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除