自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(107)
  • 收藏
  • 关注

原创 牛牛的快递&&最小花费爬楼梯&&数组中两个字符串的最小距离

1.牛牛的快递2.最小花费爬楼梯3.两个字符串的最小距离。

2024-09-27 11:31:29 289

原创 两个数组的交集&&点击消除

需要注意[1,2,2] [2,2,2] 这两个数组的公共元素是[2],而不是[2,2]。思路:将nums1存入哈希表中,便利nums2,如果nums2的元素在nums1中,就将元素填入结果中,顺便将哈希表的位置设为false,这样就可去掉重复的元素这道题很明显需要使用哈希表,但是不建议直接使用容器。因为数据的取值范围,和数量都非常小,可以使用数组来进行模拟。

2024-09-25 21:16:17 159

原创 LINUX网络编程:Tcp(2)

1.Tcp流量控制2.滑动窗口2.1滑动窗口的更新2.2滑动窗口的丢包问题1.报文丢失的情况2.ACK丢失的情况3.拥塞控制3.1慢启动3.2拥塞窗口的增长。

2024-09-25 18:27:24 737

原创 LINUX网络编程:TCP(1)

1.认识Tcp的报头2.确认应答机制(ACK)序号与确认序号捎带应答3.超时重传机制4.Tcp连接管理三次握手为什是三次握手四次挥手理解TIMEWAIT。

2024-09-20 21:24:32 997

原创 LINUX网络编程:理解绑定和分装解包

1.理解绑定2.理解封装和解包封装(添加报头)

2024-09-19 11:30:12 203

原创 LINUX网络编程:传输层

1.端口号1.1知名端口号1.2注意2.UDP协议2.1UDP报头的格式2.2UDP的特点2.3UDP的缓冲区。

2024-09-18 22:25:42 372

原创 LINUX网络编程:http

1.认识http请求的字段2.HTTP请求类3.认识HTTP应答字段4.HTTP应答类5.源代码。

2024-09-13 21:52:19 1275

原创 Linux网络编程:守护进程

4.noclose吐过设置为0,会将标准输入,标准输出重定向到/dev/pst/null这个终端文件中,最5.终输入和输出的内容都会被丢弃,其他情况则不改动文件描述符。在Linux下一个会话就是 终端文件 + bash,会话就是人类和计算机沟通的窗口和解释器。使用daemon的进程一定不能是进程组的组长,进程组组长通常就是第一个被创建出来的进程。2.守护进程会去关联终端文件,也就是不会向终端输入输出,但是可以向文件中输出(日志)。1.守护进程不属于任何一个会话,所以不受用户登陆登出的影响。

2024-09-04 17:21:47 441

原创 LINUX网络编程:应用层和协议定制

全双工:双方可以同时发送数据半双工:同时只有一方可以发送数据因为在tcp有两个缓冲区,一个用来接收数据,一个用来发送数据。网络通信本质也就是数据的拷贝,将自己发送缓冲区的内容,拷贝到对方的接收缓冲区中。

2024-09-01 10:42:53 457

原创 LINUX网络编程:Tcpsocket封装

在使用Tcp套接字时,很多的流程都是固定的,将这些固定的流程封装,更方便后续的使用。

2024-08-30 18:51:16 454

原创 LINUX网络编程:UdpSocket echo服务器

echo服务器:将收到的消息回显到客户端。主要目的:学习网络系统调用接口的使用,和一些网络基础知识。

2024-07-26 10:56:34 305

原创 LINUX网络编程:网络基础

在计算机诞生最初是用来计算弹道的轨迹的,随着时间的发展,计算机越来越普及,这时候就需要计算机与计算机之间的协作,这个协作就产生了大问题,计算机A处理完的数据,必须拷贝到移动的存储介质像软盘,再交给计算机B处理,这个过程非常的麻烦不说,还非常的不安全,效率还非常低。在很多的教材中都提到了osi七层模型,但是在工程实践当中,应用层,表示层,会话层,这三层是难以区分的,所以通常用tcp/ip五层模型表示。网络通信发送数据,必须由应用层依次向下封装,封装到链路层,传输给对方,每经过一层都要加该层的协议报头。

2024-07-26 10:01:04 760

原创 c++11:智能指针

智能指针是c++11中很好用的一个东西,很好的解决的资源泄露的问题。

2024-07-20 10:12:46 642

原创 c++11:异常

在实际开发中,都会有一个异常的体系,因为如果异常是随便抛出的,那可就坏事了,程序员A抛出了一个int,程序员B抛出了一个char*。异常是不能随便抛的,是要有严格规范的。通常都会使用多态,catch基类可以捕捉抛出的派生类的异常。使用基类调用,what这个虚函数。

2024-07-19 23:09:28 343

原创 LINUX:懒汉单例模式线程池

创建一个线程,就是要这个线程去完成某种任务的。池化技术就是,提前创建一批线程,有任务这一批线程就会执行。而不是有任务的时候在去创建线程。池化技术有着更高的效率,因为线程都是提前创建好的,直接执行任务。

2024-07-16 12:57:18 547

原创 LINUX系统编程:基于环形队列和信号量的生产者消费者模型

当下标遍历到vector末尾的时候, 下标 %=判断环形队列为空还是为满 vector容量,下标就回到数组的开始。所以生产者在生产之前要对空间的信号量进行p操作,生产完成之后要对数据的信号量进行v操作。所以消费者在生产之前要对数据的信号量进行p操作,消费完成之后要对空间的信号量进行v操作。队列一定不为空&&不为满,这个时候生产者可以生产,消费者可以消费。环形队列可以实现并发生产和消费,就是在消费的同时也可以生产。为空的时,只能让生产者先生产,消费者后消费,为满时,消费者先消费,生产者后生产。

2024-07-12 22:55:39 594

原创 LINUX系统编程:基于阻塞队列的生产者消费者模型

它是时一个经典的多线程并发的协作模型,也就是生产者(线程)向一个公共区域(阻塞队列)生产,生产出的“商品”被消费者(线程)消费。其中生产者可以拥有多个,消费者可以拥有多个,但是公共区域只有一个。

2024-07-12 10:17:54 798

原创 LINUX系统编程:多线程互斥

这也就解释了,为什票会抢到负数,究其原因就是我们抢票+判断的操作不是原子的,所以我们要通过互斥锁把这两个操作编程"原子"的,这个原子是在线程看来是原子的,不是真正意义上的原子。thread1开始执行,thread1进行判断,thread1发现票数也是大于0的,进入循环,这个时候hread1的时间片到了,thread1进入等待队列。thread0进行判断,thread0发现票数是大于0的,他就会进入循环,但是这个时候thread0的时间片到了,thread0进入等待队列。3.销毁的互斥量,就不要在加锁了。

2024-06-30 19:55:47 785

原创 LINUX系统编程:原生线程库的封装

在c++11之后,c++也支持了多线程,也就是thread库,thread库一定是对pthread库的一个封装,因为在Linux下不存在线程的概念,只有轻量级进程,pthread库就是对轻量级进程的系统调用接口封装成线程接口。那么对线程的管理一定不是操作系统做的,因为操作系统不认识线程,这个工作是由pthread原生线程库做的。pthread动态链接到共享区,使用struct pthread描述线程,struct pthread在共享区的起始地址就是该线程的 tid。可以打印看看sleep(1);

2024-06-30 14:54:28 712

原创 C++11

这个也不知道是哪个神人想出来的,大概思路就是,[1,3,4,5,6],第一次调用show将[1]传给t,[3,4,5,6]传给arg,第二次递归将[3]传给t,[4,5,6]传给arg,依次类推就将所有参数解包。bind是一个函数模板,它就像一个函数包装器(适配器),接受一个可调用对象(callable object),生成一个新的可调用对象来“适应”原对象的参数列表。在c++98中,我们使用sort这类的接口,想要比叫大于或者是小于,必须自己写一个仿函数,非常的不人性,非常的麻烦。

2024-06-28 20:11:46 965

原创 LINUX系统编程:线程控制

但是别忘了还有缓存命中这种东西,cpu在加载代码的时候,会把该代码附近几行也加载到cpu的高速缓存中,一旦进程切换了,这些高速缓存的数据,对于下个进程就没有用了,都是失效的数据,但是对线程不是这样的,线程代码和全局数据是共享的。在LINUX内核中是不存在线程的概念的,只有轻量级进程的概念,但是在用户的角度来看,用户就是要把轻量级进程当做线程的使用,所以将轻量级进程的控制接口,封装成了一个线程库,用户直接使用库,也就屏蔽了底层的实现。2.操作系统切换线程的工作,要比进程小的很多。

2024-06-21 16:58:17 872

原创 LINUX系统编程:线程的概念

本文主要介绍,在LIUNX下的线程。

2024-06-20 09:54:39 341

原创 LIUNX系统编程:可重入函数&&volatile

在执行流执行到mian函数,insert函数中的1号位置的时候,突然就陷入内核,处理信号,执行信号自定义方法,这个方法调用的也是insert,执行完之后,导致了n2的节点丢失,那么这个函数就叫不可重入函数,如果在执行流重复进入的情况下不会出问题的就叫,可重入函数。我们发现已经终止不了,这是因为编译器看我们的main函数中没有对flag的修改,直接就把flag放到寄存器中了,省着还要和内存交互,但是我们对内存的flag修改,并不会影响寄存器。这个关键字主要就是防止编译器的优化,保持内存的可见性。

2024-06-12 22:07:11 238

原创 LIUNX系统编程:信号(3)

内核级的页表只有一份,因为操作系统只有一个,操作系统的内核数据也只有一份,只需要一个内核级的页表,建立不同进程的虚拟地址到操作系统所处物理内存的映射,就可以让多个进程看到一个操作系统。硬件中断:键盘直接连接到cpu的针脚上,当键盘输入的时候,会给对应的针脚一个高电频,cpu会拿着这个针脚的编号,去操作系统的中断向量表(函数指针数组),执行对应的函数。由一个硬件,向操作系统发送一个频率非常高,时间非常短的周期时钟中断,操作系统会拿着中断号去操作系统的中断向量表中,执行进程调度,内存管理,更新系统时间。

2024-06-07 21:22:23 732

原创 LINUX系统编程:信号(2)

当进程收到2信号,首先会将pending位图第二比特位变为1,等到机会合适时处理pending中的信号,处理时会看2号信号的位置在block中是否为1,如果为1就阻塞住,不递达,为0就递达,调用handler中对应的函数。它们也是不可阻塞的,因为它们是用来控制进程执行状态的信号,不受进程阻塞的影响。3.向进程发送2号信号,因为2号信号被阻塞了,所以2号信号会一直在pending位图中。处理信号的动作叫做递达(Delivery),处理信号有三种方式,默认,忽略,自定义。

2024-06-06 11:26:12 592

原创 LINUX系统编程:核心转储

Core终止,在终止之后会生成,一个core文件,将进程在内存中的内核数据(与调试有关)转储到磁盘当中形成core文件,然后将进程干掉。在使用信号的时候,我们发现大多数的信号都是终止进程,虽然都是终止进程,但是终止进程是有两种方式的。我们发现core文件默认的最大大小是0,我们只需要将core文件最大大小修改一下,确保能够捕获足够的信息用于调试即可。如果每次启动就挂掉,会一直重启,一直挂掉,会生成很多的core文件,最后磁盘被打满,整个系统就挂了。当一个服务挂了,第一肯定是先恢复服务,然后在去解决问题。

2024-06-05 20:38:58 380

原创 LINUX系统编程:信号(1)

Linux让系统提供让用户给其他进程异步发送消息的一种方式。站在进程的角度看待信号1.信号在没被发送之前,进程是认识这个信号。2.在接受到信号之后,进程是被设定好去怎么处理这个信号的。3.信号到来的时候,如果进程有更重要的事情要做,这个信号会被临时保存。4.收到信号之后可以不立即处理,等到机会合适在处理信号。5.信号产生是不定时,随时都可能接受到信号,所以信号是异步发送的,是别的用户和进程。

2024-06-03 22:18:41 1220

原创 LINUX系统编程:信号量

信号量可以在多执行流下对,共享资源进行保护(例:共享内存本身是是一种共享资源,但是本身是不带协同机制的,这样就会出现数据不一致的问题,写端想写"hello world",但是在写端写到hello时,读端就把数据读走了,造成了数据不一致)。每个小区域都有自己的编号,当一个执行流想使用小块资源时必须,申请对应的编号,然后才能让问对应的小区域,使用完之后还要将编号还回去,这样保证每一块的小资源都是互斥访问的,大块的资源就是多个进程同步访问的。信号量是一种资源预定机制,只要预定了,资源在未来一定是该进程的。

2024-06-03 11:12:13 649

原创 LINUX系统编程:进程间通信之共享内存

ftok使用参数pathname和最少8个有效位的参数proj_id(必须不为0)生成一个key_t类型的System V IPC密钥,适用于msgget,semget,shmget这三个函数。size:就是开辟多大的共享内存,共享内存的开辟是以4kb为单位的,size的大小建议设置4*n,因为即使size为7,还是会开辟8个字节的内存,剩下的一个字节就浪费了。进程间通信的本质就是让进程看到同一块系统提供的资源,共享内存就是让不同进程看到同一块内存,用内存作为媒介,让两个不同进程通信。

2024-05-30 19:31:06 513

原创 LINUX系统编程:命名管道

匿名管道的通信只能在,有血缘关系的进程中,本质就是,子进程会拷贝一份父进程的文件描述符表,父子进程就可以看到操作系统的同一块资源(文件),以这块资源为媒介进行通信。命名管道,就是以路径为标识符,让两个不相干的进程,看到同一块资源(文件),以这个文件进行通信。

2024-05-24 20:48:47 575

原创 C++11:万能引用,完美转发,成员函数新功能。

在模版中,&&既可以接收左值,又可以接收右值。运行结果如果把模板去掉,prefectForward(a);会报错的确是两个都调用成功了,但是有一个问题,为什么prefectForward(10)参数明明是右值,为什么模板实例化的确实左值的版本?这是因为,右值引用右值,会把右值的属性变为左值,所以在调用fun的时候会调用左值版本。使用完美转发可以解决上面的情况。

2024-05-23 16:39:26 373

原创 LIUNX系统编程:进程池的实现

每一个可执行程序,在被执行前都要转化为进程,操作系统都要为其创建PCB,地址空间,页表,构建映射关系,进程池就是创建进程时,创建很多个进程,如果要执行程序,就直接使用创建好的进程。就像一次性创建5个进程,肯定是比一次创建一个创建5次的效率更好的,将任务均匀的分配给进程执行。

2024-05-06 20:23:47 470

原创 C++11:右值引用和左值引用

左值是一个具有长久生命周期,可以被赋值,可以被修改,取地址的表达式。以下都是左值int a = 0;右值是一个将亡值,快要死了生命周期很短,不能被修改,不能被取地址,一般都是临时对象,表达式的结果,函数返回值,字面常量。5;//5字面常量就是右值x + y;//结果就是右值fun1();//返回值是右值3.右值引用的意义对右值的引用,就是给右值取别名。1.左值引用解决了,传参的时候拷贝的问题。2.左值引用解决了,函数返回非局部对象拷贝的问题。

2024-05-04 16:21:59 654

原创 LIUNX系统编程:进程间通信-管道(2)

说明代码会把管道的数据读完,然后读到文件末尾,结束读取。说明读端关闭,os会终止写进程,使用信号13杀死写进程。同上,什么也读不出来,管道写满,写端阻塞等待。什么也没读出来,说明读端一直在阻塞等待。子进程的退出信号是13,

2024-05-03 21:59:55 235

原创 LINUX系统编程:进程通信-管道

pipe创建一个管道,这个单向数据管道被用于进程间通信,这个pipefd的数组(输出型参数)返回两个管道读端和写端的文件描述符,pipefd[0]是管道的读端,pipefd[1]是管道的写端。打开一个文件,操作系统都会给该文件分配一个文件描述fd,用读打开会分配一个fd,用写打开文件也会分配一个fd,但是这两个fd指向的是同一个文件。进程通信,肯定是不能直接是,进程和进程之间直接通信的,因为进程具有独立性,代码数据独立之间互不影响。管道的本质就是文件,一个进程向文件写入,一个进程读取文件。

2024-05-03 15:48:26 374

原创 腾讯云ubuntu新建用户后,命令行只显示$

这是因为,新建用户命令行解释器默认是sh,需要手动切换为bash,bash可以认为是sh的加强版本。所以我们只需要将,shell切换为bash就好了。将sh修改为bash。

2024-05-03 12:31:22 515

原创 LIUNX系统编程:动态库加载(2)

虚拟地址空间并不是有操作系统一个完成的,而是需要cpu,编译器,操作系统,三者共同联动,互相配合,编译器在编译的时候就已经生成虚拟地址了,CPU的MMU + 操作系统的页表才能讲虚拟的地址转化为物理地址。使用绝对编址的方式,对每个指令,进行编址,然后将链接了哪些动态库,main函数的地址(虚拟地址),代码区,数据区,已初始化的数据.....各个区域的大小划分,存储到到表头中。当指令寄存器,执行指令的时候,需要访问物理地址,这是时候cpu会给MMU一个请求,MMU区页表中查询,将虚拟的地址转化为物理地址。

2024-04-29 11:52:34 375

原创 LIUNX:系统编程动态库加载(1)

首先main想要运行,首先要为main创建task_struct和mm_struct,然后将main的代码和数据加载到内存,将main的代码通过页表映射到mm_struct的正文代码段,看这个程序运行是需要哪些动态库,将这些动态库加载到内存中,建立映射到共享区。我们发现一个文件的代码,数据,已初始化的数据,未初始化的数据的大小已经规定好了,这说明即使程序未被加载到内存,可执行程序已经存储好初始进程地址空间的数据了!对库的管理依旧采用面相对象,现描述再组织,抽离出库的主要信息,用链表连接起来。

2024-04-28 10:50:23 273

原创 LIUNX系统编程:动态库的制作

因为#include""的搜索规则是,在当前目录下寻找,找不到再去/usr/include中寻找头文件,但是我们的头文件在/mylib/inclue中,所以在编译的时候要指明我们的路径。但是我们并没有告诉操作系统,这个库的位置,所以在运行的时候,操作系统找不到这个共享库的位置。这个时候因为因为只在main编译的时候我们告诉编译器,这个库的位置,才得以编译通过。这样动态库就制作完了,还是需要对这个库进行一些包装,让库更规范一下。这种方式只建议比较成熟的库我们可以这么做,自己写的就不要瞎搞了。

2024-04-27 10:59:01 364

原创 LINUX系统编程:动静态库的制作

gcc -o main mian.c -L./ -lmymath //库的名字是去掉前缀和后缀的libmymath.a mymath。例:我写了一个函数,我想让别人使用,但是并不像让使用者看到我写的代码,就可以把我的代码制作成一个库,提供给使用者。ar -rc libmymath.a add.o sub.o//-rc(crate和replace)将add.c sub.c add.h sub.h 制作成静态库。1.首先要将add.c sub.c编译生成.o文件。使用-L选项制定库的路径,-l指定库的名称。

2024-04-26 20:42:24 210

空空如也

空空如也

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

TA关注的人

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