- 博客(43)
- 收藏
- 关注
原创 MySQL数据类型
最大存储65535个字节,而不是字符个数,当表的编码是utf8时,utf中一个字符占用3个字节,所以varchar(n)的参数n最大值是65532/3=21844。char是固定长度字符串,即使数据的字符串长度没有超过L,存储的时候也是L长度的存储空间,varchar是可变长度字符串,数据字符串长度是多少存储时也是按这个长度来存储的,是根据实际情况来定的。在插入数据时hobby插入的是0,是空串,如果插入不能存在的值是会插入失败的。由于online设的是1个bit,所以只能插入0和1,插入3时就存不下了。
2025-05-29 14:00:00
455
原创 MySQL表的约束
假设有一个学生信息表,这个表中除了又该学生的学号、性别、电话等,还应该要有该学生是在哪个班的字段,以及这个班的一些信息字段,每次插入一条信息,班级字段要插入“计科4班”,这样数据会出现冗余,而且插入的班级没有这个班级呢如,插入“计科10”,但是没有这个班级,但向表中插入,MySQl数据库是不会报错的是能够插入成功,这样就需要程序员在向表中插入数据时先判断有没有这个班级。auto_increment:当对应的字段,不给值,会自动的被系统触发,系统会从当前字段中已经有的最大值 +1操作,得到一个新的不同的值。
2025-05-21 14:40:23
849
原创 【项目】—高并发内存池
当前项⽬是实现一个高并发的内存池,原型是google的一个开源项目tcmalloc,tcmalloc全称 Thread-Caching-Malloc,即线程缓存的malloc,实现了高效的多线程内存管理,我们这个项目是把tcmalloc最核心的框架简化后拿出来,模拟实现出⼀个自己的高并发内存池。以服务器上的线程池为例,它的主要思想是:先启动若⼲数量的线程,让它们处于睡眠状态,当接收到客户端的请求时,唤醒池中某个睡眠的线程,让它来处理客⼾端的请求,当处理完这个请求,线程⼜进⼊睡眠状态。
2025-05-20 14:00:00
843
原创 MySQL数据类型
最大存储65535个字节,而不是字符个数,当表的编码是utf8时,utf中一个字符占用3个字节,所以varchar(n)的参数n最大值是65532/3=21844。char是固定长度字符串,即使数据的字符串长度没有超过L,存储的时候也是L长度的存储空间,varchar是可变长度字符串,数据字符串长度是多少存储时也是按这个长度来存储的,是根据实际情况来定的。在插入数据时hobby插入的是0,是空串,如果插入不能存在的值是会插入失败的。由于online设的是1个bit,所以只能插入0和1,插入3时就存不下了。
2025-05-16 13:30:00
555
原创 【表的操作】
在数据目中有三个不同的文件,分别是: users.frm:表结构 users.MYD:表数据 users.MYI:表索引。更改某一列属性后,再次查表信息,没有了描述,这是因为更改时没有加描述,将数据库中记录用新的属性信息覆盖掉。向user表中再新增image_path列,属性,描述,新增的这一列放在birthday这一列的后面。将名为name列修改成为名为xingming,但是修改时需要完整的定义还要有属性。不同的存储引擎,创建表的文件不一样。查看当时在建表时的详细信息。修改表中某一列的属性。
2025-05-15 13:30:00
112
原创 数据库的操作
字符集是向数据库中写入数据时的编码格式,我们对数据库会进行查找、提取这样的操作,查找和提取就需要对比,要对比就需要先读取出来,以哪种编码格式写入,就需要以对应的校验格式读出,创建数据库时如果不指定编码格式和校验格式,默认使用配置文件指定的编码规则。同时备份多个数据库如果备份一个数据库时,没有带上-B参数,在恢复数据库时,需要先创建空数据库,然后使用数据库,再使用source来还原。如果该名称的数据库不存在则创建数据库,存在则不创建数据库。备份的不是整个数据库,而是数据库中的一些表。查看数据库支持的字符集。
2025-05-14 13:30:00
286
原创 MySQL数据库基础
它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。mysql能够跨网络访问,-h数据库服务所在主机的IP地址-P数据库服务的端口号-u以什么身份登录-p密码,去掉-h选项mysql -u root -p默认连接本地服务器上的mysql数据库。主要用在电商,SNS,论坛。对简单的SQL处理效果好。PostgreSQL :加州大学伯克利分校计算机系开发的关系型数据库,不管是私用,商用,还是学术研究使用,可以免费使用,修改和分发。
2025-05-13 13:30:00
145
原创 CentOS下安装MySQL数据库
在CentOS上通过yum源获取的安装包都是以.rpm为后缀的格式,通过rpm命令查看mysql的安装包。看到没有与我们操作系统相对应的版本,直接下载el7.rmpCentOS7的yum源。登录方法一:当我们安装MySQL时会给我们生成一个临时的密码,查看临时密码然后登录。登录方法二:如果你安装的最新的mysql,就没有所谓的临时密码,直接登录。这里是登陆上了,但是对于新版本的MySQL是没有临时密码的。查看mysql进程的相关信息,mysql程序是否正在运行。可以看到并没有MySQL相关的yum源。
2025-05-12 13:48:43
639
原创 传输层UDP协议
我们注意到, UDP 协议首部中有一个16 位的最大长度,也就是说一个UDP 能传输的数据最大长度是64K(包含UDP 首部),然而64K 在当今的互联网环境下是一个非常小的数字,如果我们需要传输的数据超过64K, 就需要在应用层手动的分包, 多次发送, 并在接收端手动拼装。UDP协议是向套接字一次写多少的数据,一次就传多少的数据,接收端也只能一次recvfrom,不能分多次recvfrom。UDP 具有接收缓冲区. 但是这个接收缓冲区不能保证收到的UDP 报的顺序和发送UDP 报的顺序一致;
2025-05-06 14:00:00
260
原创 应用层协议HTTP
Host字段:就是IP地址+端口,客户端告知服务端,所要找的资源是在哪个服务器的端口上的,这里就有人好奇了,资源难道没有在浏览器给发起请求的IP地址+端口主机上的服务端吗?这里可以在该IP地址+端口主机上的服务端,也可以不在,请求的资源在另一个IP地址+端口服务器的服务端上,该服务器相当于充当另一台服务器的客户端,将浏览器发来的请求,提取出Host字段,将浏览器发出的请求发送给Host字段中的服务器上的服务端,做出响应后,发送给充当客户端的服务器,充当客户端的服务器再把响应发送给客户端。
2025-05-05 14:30:00
1675
原创 TCP网络编程
sockfd是用来获取连接的,将_sockfd传给accept(),accept()返回一个sockfd,未来和远端主机进行通信的是返回的sockfd,_sockfd我们一般称listen sockfd监听套接字,sockfd,_sockfd获取的链接越多,返回的sockfd越多。先创建一个管道文件,然后创建一个子进程,子进程中做命令字符串解析,然后执行命令,命令执行后的结果写到管道文件中,为了上层能够拿到命令执行后的结果,返回这个管道文件的指针。第四个参数 size:自己定义的缓冲区的大小。
2025-05-04 14:30:00
611
原创 应用层自定义协议序列与反序列化
第二种约定方案:定义结构体来表示我们需要交互的信息, 发送数据时将这个结构体按照一个规则转换成字符串, 接收到数据的时候再按照相同的规则把字符串转化回结构体。操作系统内核能够以这种方式进行通信的原因:操作系统都是用C语言写的,操作系统一旦写好,基本不会做改变,使用这种协议进行本地通信实现起来简单。这个报错是链接报错,gcc、g++默认是认识C/C++库,但不认识第三方提供的库,在makefile文件中添加。序列化和反序列化的工具:Jsoncpp用于将数据序列化为字符串的C++库。Log.hpp(日志)
2025-05-03 13:39:22
755
原创 UDP网络编程
建议服务器端绑定IP地址时绑定INADDR_ANY(就是0),因为该服务器上可能存在多个IP地址,如果只绑定了IP1地址,那么只能收到来自IP1地址的信息,绑定INADDR_ANY(就是0)表示信息无论来自IP1还是IP2都能收到。第一个参数sockfd,socket文件的文件描述符,表示从那个socket文件中读取;半双工通信:可以实现双向的通信,但不能在两个方向上同时进行,必须轮流交替地进行。单工通信:发送端只能发送信息,不能接受信息,接收端只能接收信息,不能发送信息。
2025-05-03 13:28:57
824
原创 Linux多线程
所有的线程要能够加锁要保证所有的线程能够看到锁,所以锁必须是共享资源,加锁的过程必须是原子性(原子性:只有两种状态,要么没有执行,要么执行完成,不会出现中间状态,一条指令就能够完成的具有原子性,两条以上指令才能执行成功就不具有原子性,因为执行完第一条指令可能会被切走,此时是执行了但还没有完成,处于一种等待的状态),也就是一个线程正在加锁的过程中,其他线程不能进行加锁。如果计算密集型线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的同步和调度开销,而可用的资源不变;
2025-04-01 15:00:00
601
原创 【线程池】
如果其他线程进入不会出现问题该函数称为可重入,如果多线程并发执行该函数造成问题那么该函数不可重入,带来的结果是该线程不安全,所以一个函数是可重入的那么访问的线程一定是安全的,线程安全不一定函数是可重入的,可能是不重入但加了锁。两个线程在持有自己的锁的情况下申请对方的锁,这就造成了两个线程拿着自己的锁进入到对方锁的阻塞队列中,形成了一个死扣,这样两个线程会永远处于一种等待的状态。提高线程的可管理性:线程池可以统一管理线程,包括线程的创建、调度、执行、销毁等,简化了并发编程的复杂性。
2025-03-26 15:33:16
695
原创 【进程信号】
对9号信号设置屏蔽是不会起作用的,原因如果对所有的信号设置屏蔽且起作用,并且该信号的执行动作时一个死循环,那该进程就无法被终止。函数sigfillset初始化set所指向的信号集,使其中所有信号的对应bit置位,表示该信号集的有效信号包括系 统支持的所有信号。随时都可以向进程发送信号,进程收到后能够识别该信号的含义,如果进程正在作重要的事情,所以可能需要保存信号,并不会立即执行该信号。信号捕捉有一特点:在执行信号的处理方法时,再发同一信号会将该信号自动屏蔽,信号方法执行完之后自动解除对该信号的屏蔽。
2025-03-21 14:04:04
834
原创 【进程间通信】
双向通信,父子进程都可以进行读写,子进程需要读取父进程写的,父进程需要读取子进程写的,哪那些是父进程写的,进程间通信设计成通道是为了简单,但如果设计成双向通信就变复杂了。共享内存的大小是自由设置的,但是操作系统申请的实际空间只能是4096的整数倍,。如上父子进程都能够读写一个内核级文件缓冲区,该文件称为管道文件,管道在设计时只允许单向通信,例如:父进程给子进程发数据,最开始父进程是以读和写两种方式打开管道文件的,父进程需要关闭以’r’方式打开的文件,子进程需要关闭以’w’方式打开的文件。
2025-03-14 13:32:44
958
原创 【文件系统】
"代表上级目录,进入到dir下的a目录中,cd…要想找到myshell文件就得知道"myshell"与inode编号映射关系,所以要先找到linux文件,要想找到linux文件先要找到qian文件,要想找到qian文件先要找到home文件,想要找到home文件就要先找到根目录,根目录的inode编号是操作系统设计是制定好的。Linux中的软链接和Windows中的快捷方式一样,将软链接文件删除,目标文件不会受影响,因为软连接文件是独立的文件,有自己的inode编号,软链接文件内容是目标文件的路径字符串。
2025-03-11 22:43:35
660
原创 【基础io】
向文件写入是先写入到C语言层的缓冲区,通过C语言层的fflush()将内容从C语言层的缓冲区刷新内核缓冲区中,或者程序结束后自动刷新到内核缓冲区,内核缓冲区是由内核来操作管理的。这里FILE是C语言提供的结构体类型,操作系统是通过fd来确定哪个文件,所以FILE结构体中肯定封装了fd,C语言库中对文件操作相关函数内部实现肯定调用了系统接口。系统中同时有很多的进程在运行,一个进程可以打开多个文件,被打开的文件是只读、只写还是追加,那个文件等等都需要知道,所以要对被打开的文件进行管理。第三个参数传起始权限。
2025-03-08 15:42:11
1001
原创 编写Shell
fgets()函数也会提取’\n’,所以要将userCommand[]数组中最后一个字符设为’\0’,userCommand[strlen(userCommand)-1]并不会越界,因为用户至少要按下Enter键,至少有’\n’字符。命令行是由父进程来打印的,所以cd命令应该由父进程来执行。}while(0)可以形成一个代码块,写宏函数的技巧,一般要写宏函数需要代码块时就用do{ …返回userCommand[]数组元素个数为后续分情况做处理,元素个数>0所相关操作,元素个数==0说明用户没有输入指令。
2025-03-06 15:00:00
879
原创 【进程控制】
通过以上信息推理可知缓冲区不在操作系统中,因为如果在操作系统中,由于用户是无法直接对操作系统进行访问,需要操作系统提供的接口才能进行访问,exit内部调用的是_exit,exit能刷新缓冲区肯定是因为_exit能够刷新缓冲区。有了wait()后,子进程没有退出,父进程一直阻塞等待。操作系统将父进程的状态设置为S,然后将父进程的PCB链接到子进程的等待队列中,当子进程退出,操作系统将父进程唤醒,也就是从子进程的等待队列中出来,然后链接到CPU的调度队列中继续执行后面的代码。0,提取子进程退出码。
2025-01-26 11:47:35
880
原创 Linux进程
父进程没有读取退出信息的这一段时间该进程处于僵尸状态(Z),此时的进程称为僵尸进程。设计方案:当创建一个进程时必须有自己的虚拟地址空间和对应的页表,操作系统会给子进程创建和父进程一模一样的虚拟地址空间和页表,当子进程对变量做修改时,会开辟新空间将旧空间中的数据拷贝给新空间,更改页表中的物理地址,然后对新空间中的内容做修改。子进程创建成功时,这时就有两个进程,父进程和子进程会执行相同的代码,他们都会执行fork()函数的return,父进程返回的是子进程的pid,子进程返回的是0。拷贝到内存上的什么地方?
2025-01-19 07:51:06
1242
原创 Linux调试器-gdb
场景:假设你的程序出bug了,你现在排查该bug是否出现在该函数内部,进入到函数内部后有一个1000的循环,执行几次循环后通过分析该循环没有问题,但是不能保证该函数没有问题,因为循环后面还有语句,这时nutil直接跳转到该函数内部后面的语句。debug模式下编译器生成的可执行程序要比release模式下生成的可执行程序要大,原因debug模式下编译器会添加调试信息,release模式下编译器会做一些优化。debug模式下编译生成的可执行程序可以调试,release模式下编译生成的可执行程序不可调试。
2025-01-02 14:30:00
519
原创 Linux平台下实现的小程序-进度条
因为程序对大多数用户来说是用来做计算的,用户由键盘输入,经过程序计算,再由显示器给用户显示出来,显示器和键盘被用户经常使用,那C语言设计者就想既然显示器和键盘被多次用,那在程序开始执行之前默认将其打开。sleep与usleep的区别是sleep休眠时间单位是秒,usleep休眠时间单位是微秒。如下图在vim编辑器中的命令模式下输入命令,在3号手册中查看sleep。usleep是由Linux提供的接口,用于程序在执行时停下来休眠数微秒。sleep是由Linux提供的接口,用于程序在执行时停下来休眠数秒。
2024-12-30 16:11:33
1347
原创 Linux编译器-gcc/g++使用、Linux项目自动化构建工具-make/makefile
想象一下一个很大的项目,有上千个源文件,编译一次就需要半个小时,当只修改了一小部分程序时,每次调试都将所有的源文件再次编译这样效率太低,对于没有做改动的源文件不需要再次编译,只需将修改了的源文件编译就可以了。2、浪费资源(每用到标准库中的方法时,就需要将标准库中的方法拷贝到自己的程序中,这样造成可执行程序变大,程序加载到内存中时会占用更多的内存)对test.i文件来说进行编译。标准库中是函数的实现,而对应的头文件中包含了相应的声明,通过头文件就知道标准库中有那些方法、方法的参数列表、方法的返回值。
2024-12-29 08:30:00
1031
原创 Linux软件包管理器-yum、Linux编辑器-vim
我们看到这里无法通过sudo对指令提权,并不是所有的普通用户都能够指令提权,如果任意一个普通用户都能通过sudo对指令提权,那就和root一样了,root也就没有存在必要了,只有被信任的用户才能sudo对指令提权。在Linux中vim并不是简单的直接执行可执行程序,还会读取配置文件.vimrc,没有该文件的自己新建一个.vimrc的配置文件。对于维护该系统的一群人说想让该系统被更多人来选择,就需要将自己的社区维护好,开发更多的项目。这些Linux系统的底层内核是差不多的,哪怎么选择一款Linux系统?
2024-12-26 08:30:00
718
原创 Linux中权限的理解
在Linux中有3种角色,同一文件对于不同的角色有不同的权限,剩余9个字符3个为一组依次为,拥有者具有的权限、所属组具有的权限、other具有的权限。qian这个普通用户删除了root在/home/qian/lesson6下创建的文件的根本原因是:qian是lesson6这个目录的拥有者,对于拥有者有r、w、x权限。在能在系统非用户目录下创建,但有这里有一个问题:这个目录对所有的other都有r、w、x权限,其他人都可以对该文件进行删除。目录w权限:决定用户能否在目录中新建、修改、删除文件;
2024-12-23 09:00:00
752
原创 C++11
以上Plus类中静态成员函数只有两个参数,没有隐含的this指针,而非静态成员函数有隐含的this指针,参数为3个,如上代码中对非静态成员函数指针包装有两种,第一个传的是对象地址,第二个传的是对象,传的是对象地址operaator()函数内部通过对象来调用Plus类中该非静态成员函数,传的是对象operaator()函数内部通过对象来调用Plus类中该非静态成员函数。实现思路:构造函数私有化,不让其在类外实例化对象,但是可以在类内部调用构造函数,那就在类内部实现一个公有的函数,new该对象并返回该地址。
2024-11-29 13:04:45
918
原创 二叉搜索树、AVL树
树为空,新增的节点就为树的根;树不为空,用cur指针找合适的空位插入,如果比当前节点的key值大,就往当前节点的右子树走,如果比当前节点的的key值小,就往当前节点的左子树走,不断循环当cur为空时,合适的空位就找到了,新增节点与父节点链接。为什么要叫二叉搜索树:根据名字可以看到二叉搜索树查找的速度很快,插入40亿个数据,假设形成的树是平衡树(AVL树和红黑树就是对二叉搜索树的优化,AVL树是严格平衡,红黑树是相对平衡),那该树的高度也就三十多,查找一个数最多也就查找三十多次,可见查找的速度是非常的快。
2024-11-12 14:40:15
878
原创 C++多态
调用A类中的虚函数test(),执行test()函数体内部this->func(),this是A*类型的,调用A类中的func(),但A类中的func()函数被子类func()函数重写,重写只重写函数体部分,对于接口部分不重写。在我们日常生活中买火车票,不同的人买票价格是不一样的,普通人是全价,学生是半价,军人可能有其他的优惠政策,对于不同的对象买票的价格不同这样的买票程序如何设计,这样的场景就用多态,多态的概念就是不同的对象完成某种行为时会产生不同的状态。final修饰的类,叫最终类,这个类不能被继承。
2024-10-30 16:46:19
619
原创 C++继承
C++继承1、继承的概念和定义概念:在保持原有类特性的基础上进行扩展,增加功能,写出新的类称为派生类(也叫子类)。继承体现出了面向对象程序设计的层次结构,体现了有简单到复杂的认知过程。#include<iostream>using namespace std;class Person{public: void Print() { cout << "name:" << _name << endl; cout << "age
2024-10-25 12:39:10
573
原创 C++queue和priority_queue的实现
适配器模式是一种设计模式,该种模式是将一个类的接口转换成客户希望的另外一个接口。在STL中stack和queue并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为栈和队列只是对其他容器的接口进行了包装。双端队列支持迭代器、任意位置随机访问、任意位置的插入和删除底层原理图(deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组)1、vector容器的优点和缺陷2、list容器的优点和缺陷3、deque容器的优点和缺陷。
2024-10-13 23:00:12
888
原创 C++ vector的实现
这里的拷贝不应该这样写,对于容器中存储的内容是内置类型的可以这样写,但当容器中存储的是自定义类型,这里进行的是浅拷贝,例如:vector<string> v;_size指向了新的空间,而_finish还指向原空间,size()的实现是_finish-_start;size()就不是原空间的size了。出现这种结果的原因:最初有4个空间,再插入一个,就要扩容,扩容要开新的空间,而这里传的是旧空间指定的位置,这里传的迭代器也就失效了。第二个函数:多了一个参数,传的是greater类型的对象,排的是降序。
2024-05-28 09:39:59
792
原创 Linux基本指令
tab键快速按两次,列出所有相关指令和上一级路径按一次,自动补齐指令或上一级路径补齐什么都不输按tab键一次:列出所有的指令Alt+回车(全屏、去全屏)Ctrl+c 终止当前正在运行的操作复制: ctrl + insert (有些insert 需要配合 fn 来按)粘贴: shift + insertwhoami指令:查询当前用户名;adduser指令:设置用户名;passwd指令:设置密码;userdel指令:删除账户【选项】-i 输出文件的 i 节点的索引信息。
2024-05-19 16:08:25
620
原创 C++模版初阶
比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<> 中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。2. 代码的可维护性比较低,一个出错可能所有的重载均出错,那能否告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码呢?函数模板代表了一个函数家族,该函数模板与类型无关,
2024-05-19 15:35:26
272
原创 C++内存管理
【说明】2 C++中动态内存管理C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。2.1new和delete操作内置类型、自定义类型对于自定义类型,new出来的空间都没有初始化,则都是随机值。如果部分初始化,剩余部分编译器会初始化为0。【注意】:通过以上汇编代码我们可以发现==对于自定义类型,在堆中开辟空间编译器会自动调用构造函数(还调用了operator newde
2024-05-19 15:04:58
884
原创 C++类和对象【下】
为什么会有初始化列表,下面代码用两个栈类实现队列类,思考一下如果栈类构造函数不是默认构造,那在初始化Stack类型的成员变量时就必须传参,这时就有大聪明想到在Queue类中的构造函数体内对自定义类型的成员变量定义,答案是肯定不行的,函数体内会使用this指针,this指针指向的是对象的地址,所以先要定义成员变量,再执行函数体,这时就有了初始化列表。友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。内部类是一个独立的类,
2024-04-23 14:29:53
725
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人