- 博客(120)
- 收藏
- 关注
原创 【网络】数据链路层
数据链路层是软件层的最底层协议,它的下面就是物理层,那么下面我们就来介绍一下它负责在网络通信中完成什么工作我们前面说的IP协议是解决如何进行跨网络转发的,也就是转发时的路径选择问题。比如一个主机A要跨公网转发到主机B,先不要说A如何到B,我们先说A如何到距离A最近的路由器(与A处于同一个子网,负责转发A的消息的路由器)的,这就需要用到数据链路层并且跨网络转发到目标主机本质就是一个报文经历了无数个子网所以数据链路层是解决同一个网段之间的主机的如何通信的问题的,即局域网通信。
2024-11-06 19:56:52 598
原创 【网络】网络层协议IP
IP是用来主机定位和路由选择的,它提供了一种能力,就是将数据从A点跨网络送到B点。并且这种能力并不是一定能完成,而是有较大概率能完成。我们在网络世界中追求的就是将数据可靠送达可靠用的策略是TCP,而送达用的就是IP的能力就是因为TCP和IP只是负责把数据送到,跟什么业务无关,所以可以做进操作系统我们平时也见过很多IP,IP都是由目标子网+目标主机构成的。
2024-11-03 20:10:03 1183
原创 【网络】传输层协议TCP(下)
那如果B一直没空间,A就会给B发的报头中把PSH标记位 置一(当然PSH标记位的应用场景不只是会这么极端),就是让B尽快向上交付,当然取走缓冲区中的数据取决于应用层,这里的意思是应用层调用read的时候不要阻塞,即使要读走的内容很少,也要尽量读走。的状态,对这个就是等待一段时间,这个状态实际上是先调用close的一方收到对方的close并给应答后处于的一种状态,这个状态通常持续的时间是分钟级别的,所以我们也可以较容易的看到。A会向B发送窗口探测,B会向A发送窗口更新通知,这两种机制是会同时存在的。
2024-10-31 20:15:13 2144 6
原创 【网络】传输层协议TCP
TCP的全称是传输控制协议(Transmission Control Protocol),也就是说,对于放到TCP发送缓冲区中的数据,如何发,什么时候发,出错了怎么办,这些都是有TCP协议控制的下面是TCP报文的基本格式标准报头是20个字节,并且在传输层,并不会像我们在应用层一样还需要序列化,传输层直接发送的就是结构化的数据,因为这样发送成本是最低的,发送带宽最小。那它不是会有跨平台,大小端的问题吗?
2024-10-29 20:34:25 1146
原创 【网络】传输层协议UDP
之前我们已经把应用层http协议说完了,我们知道一些优秀的应用层协议会绑定知名端口号,就是说它们的端口号默认是固定的,比如http是80,https是443,ssh是22等,我们也可以通过查看下面的文件来查看知名端口号。指的是报头+正文的总长度(字节),16位表示的最大的数是2^16-1,也就是说UDP一次发送的报文长度是64kb-1,如果一次发送的数据超过这么多,sendto就会调用失败。这也就是为什么UDP是不可靠的,当然我们不能把它看成一种缺点,而是一种特点,因为不可靠也就决定了它是比较简单的;
2024-10-27 10:39:24 642
原创 【网络】HTTP协议(下)
上篇博客讲了http请求和响应的基本格式,那么其中请求是浏览器发给我们服务器的,也就是说,里面的字段都是浏览器填充的;而我们需要做的是分析请求内容,然后把目标文件发给客户端。
2024-10-23 19:39:48 980
原创 【网络】HTTP协议
url全称Uniform Resource Locator(统一资源定位符)我们可以给它大致分为三部分,那么如何理解呢?我们知道访问一个网站,实际上就是去服务器上获取资源,资源其实就是文件,那么如何找到这个文件(互联网中唯一的一个文件)呢?我们需要服务器的ip和文件在服务器上的路径即可所以上面的三部分就是http协议,ip,文件路径其实这个文件路径并不是说在根目录下的某个路径,而是跟进程有关的,我们叫做web路径,那其实就需要端口号,那为什么不体现在url中呢?
2024-10-20 18:54:17 914
原创 【网络】序列化和反序列化
在之前的博客中,我们已经是成功的利用UDP和TCP进行网络通信,但是不知道你发现没有,我们在用TCP时,发送数据和接收数据用的是write/read、send/recv这类接口,这类接口处理的数据都是字符串,那如果我们要传输一些“结构化的数据”怎么办呢?我们一般想到的就是把结构化的数据变成一个字符串,这样可以方便网络的发送这其实就是序列化和反序列化:发送数据时将这个结构体按照一个规则转换成字符串,收到数据时再按相同的规则转化回结构体。
2024-10-12 20:32:19 1006
原创 【开源项目】Jsoncpp的简单使用
下面就是给我们json格式的字符串,我们如何转化为结构化的数据,我们无法得到json格式的字符串可以用上面的代码把生成的字符串写入到文件中。并且我们可以发现,打印格式是按名称首字母排序后打印的(a,n,s,w),而不是我代码中的赋值顺序(n,a,w,s)当然除了上面的格式,我们在定义输出格式对象的时候还可以定义下面的类的对象,这样字符串的格式就会发生变化。下面我们就来简单使用一下这个库:下面的就是简单的样例代码,我们只需要照猫画虎的套模板够用即可。安装完成之后我们就可以在如下的目录中查询到头文件。
2024-10-10 19:49:13 406
原创 【网络】TCP协议的简单使用
还有一种方法就是子进程马上创建孙进程,让孙进程去执行任务,之后子进程立马退出,父进程就可以直接wait到子进程,并且孙进程成为了孤儿进程,会由系统领养,我们就不用关心孙进程的回收问题了。此时我们就可以创建子进程让子进程去和客户端进行交互,父进程重新去获取连接,这样就是可以的,但是父进程是要回收子进程的,父进程也不可能去一直等待,那应该如何做呢?网络中read的返回值有不同的含义,大于0就是读到的字节的个数,小于0是读取出错,等于0是客户端退出并且关闭连接,我们就可以用返回值去判断客户端的状态。
2024-09-22 20:28:11 1281
原创 vscode连Linux虚拟机(超简单)
首先我们需要设置好Linux虚拟机,我们需要下载vmware,我这里也有阿里云盘的下载链接,阿里云盘是非常快的,比百度云盘好使。其实vscode连虚拟机和云服务器是一样的,我在这里就讲述我的亲身经历(因为云服务器要到期了,所以打算向虚拟机过渡一下)之后我们需要下载Linux镜像文件,可以参考这篇博客。之后我们安装vscode,去官网即可。等到我们打开虚拟机,首先安装ssh。之后就配置虚拟机就可以了。找到虚拟机的IP地址,用。ssh 用户名@IP。
2024-09-22 15:12:59 428
原创 【网络】UDP协议的简单使用
UDP是基于socket进行网络通信的,那我们这篇博客就来介绍一下基于UDP通信的基本流程,先让服务端和客户端进行简单的跨网络通信。
2024-09-08 11:54:37 1996 5
原创 【Linux】线程结束
自旋其实就是一个不断询问的过程,我们是否用自旋锁就跟线程在临界区中执行时间的长短有关了,如果执行时间长的话,比如有IO操作或者网络请求,我们就用之前学的普通的锁,线程会挂起等待;举一个更加普遍的例子,线程1需要先申请锁1再申请锁2才可以访问资源,线程2需要先申请锁2再申请锁1才可以访问资源,当线程1申请完锁1,线程2申请完锁2后由于它们再也申请不到另一把锁了,所以就会一直阻塞,就会出现死锁问题。:同一个函数被不同的执行流调用,当前一个执行流还没有执行完,就有其他的执行流再次进入,我们就称之为重入。
2024-09-01 20:06:36 745
原创 【Linux】线程池
这篇博客我们主要基于前面的知识实现一个,我们想要的效果就是说提前把线程都创建好,等到有任务的时候直接往任务队列里放任务,线程直接去任务队列中取任务并完成即可,其中我们要引入日志的概念,就是把进程运行的信息以打印到屏幕或打印到文件的形式让我们看见。其中有很多的语法细节等我们遇到了再说。
2024-08-31 20:47:09 903
原创 【Linux】POSIX版本 信号量
之前我们在System V版本的进程间通信说过信号量,这里我们说的是POSIX()版本的并且会说的更加详细我们之前对于信号量也有一定的理解,我们说它就是要给计数器,用来记录所需资源的数量,因为这个计数器是被多个线程所共享的,所以它本身就是共享资源,为了保证共享资源的安全,所以我们说PV(对计数器--和++)操作是原子的今天我们还是想用信号量实现生产消费模型。
2024-08-28 21:11:37 552
原创 【Linux】线程同步和生产消费模型
超市内的资源就是共享资源,由于生产者们之间,消费者们之间,生产者和消费者之间不能同时访问超市这种资源,也就是说它们之间是互斥的(为了方便起见这么理解,实际情况复杂更多,并且实际的生产消费模型也就是较为简单的这种情况),所以我们需要对超市进行保护,让超市中的资源变成临界资源。,这个主要是通过引入缓冲区(超市)来实现的,如果没有缓冲区,生产者一会忙,一会闲,消费者就要被迫的这样,有了缓冲区消费者就可以平稳的执行任务,其实就是平衡二者之间处理能力的差异,减小等待时间,提高整体的效率。所以记录一下等待的人数,
2024-08-08 10:41:51 772
原创 【Linux】线程互斥
同一进程内的各个线程都能访问的资源叫共享资源:把共享资源保护起来后就叫做临界资源(保护就是说一个只允许一个线程访问该资源):访问临界资源的代码就叫做临界区,除了这临界区,就是非临界区:任何时刻,只有一个线程进入临界区访问临界资源这个就叫线程间互斥:一个操作要么没干,要么干完,此时就称该操作是原子的。
2024-08-02 12:44:56 664
原创 【Linux】线程的控制
我们说Linux是用进程模拟的线程,所以Linux中只有轻量级进程的概念,但是,用户是只认线程的,所以我们有一个叫原生线程库的东西,它就负责把轻量级进程的系统调用进行封装,转成线程相关的接口提供给用户。为什么叫原生呢?就是说只要你装Linux系统,就必须装这个库,就是默认装好的库。有关线程的接口在3号手册,就证明它们不是系统调用,因为系统调用在2号手册。当然也有创建轻量级进程的系统调用,它是在二号手册我们可以说,其实pthread_create其实就是封装了这个系统调用。
2024-07-30 15:46:25 739
原创 【Linux】线程的理解
线程可谓是大名鼎鼎了,它的重要性不亚于我们之前学的进程,之所以说进程重要,那是因为进程就代表着用户,用户所作的操作都是以进程为载体的,而今天要说的线程甚至比进程还要重要。那么什么是线程呢?线程是进程内部的一个执行分支,线程是CPU调度的基本单位,当然这对于支持线程的操作系统来说是正确的,我们后面会说到,Linux操作系统并不直接支持线程,而是利用轻量级进程封装出的线程加载到内存中的程序叫做进程,当然这个解释抽象不具体。所以我们一般说进程=内核数据结构+程序的代码和数据。
2024-07-28 20:13:47 712
原创 【C++】类型转换
我们其实在C语言就用过类型转换,不管是隐式类型转换还是强制类型转换。那我们就先来总结一下C语言中有哪些类型转换1.整形之间可以进行隐式类型转换,比如char和int,可能会有截断问题,但还是能转换的2.整形和浮点数可以进行隐式类型转换,它们都是表示一个大小,可能会有丢失数据的问题3.bool和整形 bool和指针之间可以进行隐式类型转换,是0或者空指针就为假,否则就为真4.指针和整形之间可以进行强制类型转换5.不同类型的指针之间可以进行强制类型转换C++其实。
2024-07-26 11:42:19 1035
原创 【C++】特殊类的设计
本篇博客就是说给一个需求,然后根据需求和类的一些语法规则设计出符合要求的类,比如说我们之前的不能拷贝的类:C++98的做法就是将拷贝构造仅声明且声明在私有,这样编译器不仅不会自动生成,外部也无法调用私有;C++11有关键字delete就可以直接解决,我们再来看一些其他的需求。
2024-07-25 18:29:54 708
原创 【C++11】智能指针
就像我们上篇博客说的一样,如果new和delete之间抛异常,那么就容易导致内存泄漏,所以我们为了避免这种情况,使用智能指针,那么这篇博客我们就来详细的介绍一下各种智能指针。
2024-07-24 21:57:25 783
原创 【C++】异常
C语言处理错误的方式有哪些呢?assert断言;返回错误码errno,然后我们可以通过这个错误码查到错误信息(strerror(errno));我们可以自定义函数的返回值,如果有错误返回什么等等。同样抛异常就是C++处理错误的一种方式。
2024-07-23 13:09:52 645
原创 【C++11】lambda表达式
这是我们之前的写法,如果只是单纯的排序一种数据还是比较容易的,但是实际生活中,一个商品往往有很多的属性需要排序,比如一款手机的价格,销量,用户评价等,不仅需要升序还需要降序,所以就导致我们需要写很多的仿函数,这样无疑是非常不方便的,还有可能因为命名问题导致矛盾的产生,所以,为了避免这种情况,我们可以使用lambda表达式。mutable一般不写;,可以将可调用对象(函数指针,仿函数,lambda表达式)进行再封装,就是说,将上面的一系列可调用对象在封装一层,这样它们的类型就统一了,这样调用就更好调用了。
2024-07-21 15:33:33 1290
原创 【C++11】模板的可变参数
默认生成的拷贝构造的话对于内置类型是浅拷贝,对于自定义类型是调用它的拷贝构造,这里的默认生成的移动构造也是这样的(对于内置类型是浅拷贝,对于自定义类型是调用它的移动构造),但如果自定义类型没有移动构造,就会调用拷贝构造。这里的拷贝构造和析构都是必要的,它不会默认生成移动构造和移动赋值,但是我想让它生成,为了证明它生成的是错的,先把拷贝构造和析构屏蔽掉,来执行下面的代码。,就是对于自定义类型调用它的移动赋值,对于内置类型就是浅拷贝,我们看结果。了,此时也没有拷贝赋值,但是会默认生成拷贝赋值,此时结果是。
2024-07-20 13:18:55 647
原创 【C++11】右值引用
下面就到了右值引用的部分,之所以发明右值引用,肯定是因为之前的左值引用有一些问题不能解决,那下面我们就来具体的看一下首先我们要明白什么是左值,什么是右值,其实左值和右值之间最根本的区别是能否取地址。有人可能说左值可以改变,右值无法改变,其实这是不对的,const修饰的左值也无法改变,而右值确实都无法改变。那我们下面先来举几个例子之前我们说的都是左值引用,我们已经会写了,右值引用的话就是两个&符号在这里我们需要记住右值被右值引用后,右值引用的属性是左值。
2024-07-19 10:04:33 760
原创 【Linux】信号的处理
我们之前说信号产生后OS向进程的PCB中写入信号,那么什么时候对信号进行处理呢?就是。信号的处理这里就不得不提什么是内核态,什么是用户态,其实我们平常在调用系统调用的时候就会去执行OS的代码,这时我们就说进程陷入了内核,目前处于内核态。那有可能我们的代码不调用系统调用,那它怎么会进入内核态呢?不要忘记,进程是基于时间片进行调度的,当时间到了进程会从CPU中剥离下来,这时就是OS在执行操作,就是处于内核态。
2024-07-17 15:02:06 927
原创 【Linux】信号的保存
上篇博客我们介绍了信号的产生,进程可能目前无法处理信号,所以要将信号进行临时保存。我们说:OS向进程发送信号本质上就是向PCB中写入信号,这个过程就是信号的保存过程,这篇博客我们就来详细介绍一下信号的保存。
2024-07-16 10:30:31 739
原创 【Linux】进程间通信——消息队列和信号量
system V版本的进程间通信方式有三种:共享内存,消息队列和信号量。之前我们已经说了共享内存,那么我们来看一下消息队列和信号量以及它们之间都属于一个版本,所以不管是接口还是底层实现都有很多的相似性,我们也一同来探讨一下。
2024-07-13 14:09:29 665
原创 【Linux】进程间通信——命名管道和共享内存
我们不得不说,共享内存是最快的进程间通信的方式,因为一个进程只需要把数据写入到它的地址空间中(其实就是写到了物理内存中),另一个进程就可以看到,这是它的优点,但是共享内存是不提供进程间协同的机制的,就是你写你的我读我的,这就会导致你可能还没写完我就读了,这就导致信息丢失。这个函数有两个参数,其实我们可以随便给一个路径,一个proj_id,只要它们是唯一的即可,这样就可以生成唯一的key值,不同的进程间只要传入相同的路径和proj_id,它们就能获得相同的key值,找到同一块共享内存。
2024-07-11 15:54:48 976
原创 【Linux】System V版本 进程间通信(IPC)——匿名管道
1.:一个进程需要将它的数据发送给另一个进程,比如我们有两个进程,一个负责获取数据,另一个负责处理数据,这时第一个进程就要将获取到的数据交给第二个进程2.:多个进程间共享同样的资源3.:一个进程需要给其他进程发送消息,通知他们发生了某种事件4.:有些事件需要完全控制另一个进程,比如我们在使用gdb调试时,gdb就是一个进程,它控制了我们要调试的进程进程之前是有互相传递信息的需求,但是,一个进程不可能去另一个进程的地址空间中取信息,所以这就要求操作系统去提供一块交换数据的空间来供进程之间使用。
2024-07-08 22:09:55 1225
原创 【Linux】动静态库
有了这个库文件,我们就可以使用了,比如我在这个目录下创建一个使用这个库的用户,用户创建一个main.c使用add和sub函数,我如果只把头文件拷贝到这个用户的目录下它还是无法编译的,因为它。因为静态库只有在链接的时候使用,而动态库在链接和运行的时候都需要使用,所以对于静态库的制作和制作中出现的一些问题是动态库制作过程中问题的子集,所以我们先简单的来制作一下静态库。现在我就可以对于目标文件进行打包了,用下面的创建静态库的命令,在这个命令中,r表示插入新的成员,c表示创建新的库文件。
2024-06-08 20:05:33 1678 3
原创 【Linux】磁盘文件和软硬链接
上篇博客我们说了,就是文件加载到内存中它的一些操作。那么不可能所有文件文件都要加载到内存中,大部分文件都要存在与一种可以的硬件中,就是我们要说的。现在的笔记本电脑用的都是硬盘,你可以理解为硬盘比磁盘更先进。但是目前企业级的磁盘仍在被使用,因为更加便宜。下面我们从磁盘的物理结构成谈起,逐步抽象到逻辑上的存储。
2024-06-06 21:17:20 750
原创 【Linux】内存级文件
所以我们说fopen底层就是封装了open,并且不同的选项底层就对应了不同的宏,我们上面说stdin、stdout、stderr每个程序都会默认打开,并且它们的类型是FILE*,这是C语言层面的类型,本质就是一个结构体,既然Linux要通过文件描述符来确定一个文件,C语言要通过FILE*的对象,所以FILE*结构体中肯定有文件描述符。我们可以关闭stdout试一试,还不能关这个,因为一旦关了就打印不出东西来了,我们卡伊关掉stdin,新打开的文件的文件描述符就会从最小的没用到的0开始。
2024-05-31 21:08:51 796
原创 【Linux】自己实现一个bash进程
还有一个问题,就是当我们什么都不输入,直接回车时,我们其实就没必要在执行下边了,直接回到循环最开始就可以,于是我们可以做一个判断就是如果输入的命令的长度为0,那么就直接回到循环最开始处,这里的长度可以让Interactive的返回值来给。为例,如果判断出来了用户就是要输入cd命令,如果后边什么都没有,那么默认是回到家目录,如果有,那就chdir到那个目录,并且不要忘记命令行提示符可是一直通过环境变量PWD来打印我们当前所在目录的,所以我们还要通过putenv把PWD。了,就是让子进程执行,父进程等待。
2024-05-28 20:40:15 1119
原创 【Linux】进程程序替换
因为进程地址空间中是有环境变量的,而子进程就是与父进程共享的环境变量,这个道理和父子进程共享代码和数据是一样的,只有一方修改时才会发生写时拷贝。,它就是通过创建子进程来执行我们输入的命令的并且拿到执行结果,我们后面也会自己写一个bash来更好的理解bash的工作原理。到现在,我们已经把所有的字母的意义都讲完了,其他没讲到的函数无非就是各个字母的组合,就只剩。,它的第一个参数表示路径,就是我们要执行的程序在哪个路径下,后面的叫做。这样我们就比较容易理解了,arg我们知道,命令行参数,所以。
2024-05-26 19:51:30 901
原创 【Linux】进程地址空间
其实每个进程都有一个进程地址空间,这其实是操作系统给进程画的一张“大饼”,就像上面的图一样,说是有4G,每个进程也认为它们有4G空间,但实际上怎么可能每个进程都有4G呢,进程实际上是用不了这么多内存的,所以这就是假的,这是操作系统想让进程看到的,等进程真的需要空间时,,就是它们之间的关系并没有那么强了,进程看来就是去申请空间,操作系统看来就是去开辟一块空间,它根本不需要考虑进程的问题,比如进程要求空间连续,操作系统也可以申请不连续的空间,只需要映射到连续的空间即可,它们之间的工作就相对独立了。
2024-05-19 21:07:23 886
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人