自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

菜鸟康的博客

菜鸟成长日记

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

原创 Linux网络编程——http协议

我们所知道的应用层协议实际上就是对应用层传输数据时需要遵循的一系列标准的一个规定,这些协议都是程序员规定的,在TCP网络通信这篇文章中,我们实现了一个简单的网络计算器,通过客户端产生请求,服务端接收请求,并响应请求,我们为该网络计算器还制定了一个简单的协议。但是网络上需要传输的数据是非常复杂的,视频、图片、网页等等。况且如果这些都需要程序员自己制定自己的协议是非常麻烦的。所以就对于其他一些非常好的协议,就会形成一个应用层特定的协议的标准,如此就可以供大家使用。如等。

2025-04-02 11:19:51 723

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

在我们上一篇TCP网络通信文章中,我们使用了守护线程,但是当时没有做过多的了解,下面再本文中,我们再做详细介绍。

2025-03-14 20:59:13 1105

原创 Linux网络编程——应用层协议的初认识

在前面的文章中我们已经对UDP和TCP通信协议有了一定的了解,并且实现了不同版本的UDP和TCP网络通信代码。我们在之前实现通信网络中用到的各种接口:socket()bind()listen()等这些实际上都是Berkeley套接字接口( Berkeley sockets API),它们是标准库函数,提供了对底层网络通信协议的抽象,通过这些函数,应用程序能够方便的进行网络通信,而无需直接处理复杂的网络协议细节。然而网络发展至今天,已经出现了许许多多成熟的应用层协议,

2025-03-14 15:41:51 1035 1

原创 Linux网络编程——TCP网络通信多线程处理

上篇文章中我们实现了简单的TCP网络通信,有单进程版本的,多进程版本的。但是它们都存在着许多的不足之处。如单进程版本当给多个客户端提供服务时会出现问题,从而实现了多进程的两个版本,分别利用忽略子进程的退出信号使得子进程被自动回收和创建孙子进程的两种方法实现。但是对于多进程来说,这样的资源消耗会很大,所以接下来我们要考虑的是多线程版本。

2025-03-12 08:53:47 463

原创 Linux网络编程——简单的TCP网络通信

上篇文章中我们对udp网络通信有了初步的认识,我们在之前已经知道了UDP通信和TCP通信的不同UDP非连接,面向数据包。TCP连接,面向字节流。这篇文章我们来介绍和演示一下TCP套接字的接口。

2025-03-11 09:20:40 828 1

原创 Linux网络编程——UDP网络通信的简单实现

通过上述步骤,UDP服务端和客户端就可以进行基本的数据交换了。由于UDP是无连接的,每次数据传输都是独立的,因此每次调用sendto和recvfrom都不需要事先建立连接。这种方式非常适合那些对延迟敏感的应用程序,但也意味着数据包可能丢失或乱序到达。

2025-03-11 09:19:51 884

原创 Linux网络编程——网络编程初识、UDP套接字简单了解

上篇文章主要介绍的是网络通信方面的一些知识,也算是为以后的学习先做一下铺垫。从本章开始我们就要正式进入网络编程的学习了。但是在开始网络编程之前,我们还需要进行一些准备工作,需要先了解一些概念。

2025-03-10 08:44:03 1093 1

原创 Linux网络编程之——网络初认识

在前面的文章中,我们已经学习完了Linux系统编程方面的知识,接下来我们就要开始进入Linux网络编程部分了。在正式认识Linux网络编程前,我们先对网络做一个了解。

2025-03-10 08:42:38 759

原创 Linux系统编程——生产者消费者模型

生产者-消费者模型(Producer-Consumer Pattern)是一种经典的多线程同步问题,它描述了一组生产者线程和一组消费者线程共享一个有限缓冲区的情况。生产者负责创建数据并将其放入缓冲区中,而消费者从缓冲区中取出数据并处理它们。这个模型广泛应用于各种并发编程场景中,以确保线程之间高效、安全地交换数据。

2025-03-09 21:49:02 1049 3

原创 Linux系统编程--线程同步

上篇文章我们讲解了线程互斥的概念,为了防止多个线程同时访问一份临界资源而出问题,我们引入了线程互斥,线程互斥其实就是多个线程同时争抢一份资源,谁抢到了就是谁的,抢不到的只能等待着下一次抢。虽然解决了有多个线程同时访问同一资源所产生的问题,但是我们思考一下这样子合理吗?不合理,这会产生另一种问题——线程饥饿。二、线程饥饿那么线程饥饿是什么呢?

2025-03-09 21:48:41 1025 1

原创 Linux操作系统——多线程互斥

我们已经学习了什么是多线程,以及多线程的控制和其优点,多线程可以提高程序的并发性和运行效率,可以充分利用计算机的多核资源。但是我们在前面学习的过程中,看到了有些多线程的程序的运行结果是有一些问题的,如出现了输出混乱、访问共享资源混乱等特点。所以我们下面提出的这个概念是关于这方面的——线程互斥。

2025-01-03 11:11:20 696 1

原创 Linux系统编程——线程控制

在上一篇文章中我们已经学习了线程的概念,线程的创建和等待,并且已经从根本上了解了线程和进程的相同点及不同点。在学习进程时,我们也学习了进程的相关控制接口,而线程作为更轻量级的进程,其自然也有着控制接口。

2024-12-29 21:36:12 794 2

原创 Linux系统编程——线程

之前的文章中我们已经对进程相关的概念做了认识,从创建进程、子进程,进程回收、进程替换等,由于我们之前对于知识框架的不熟悉,为了方便我们的理解学习,我们在之前的学习中没有做到深挖细节和深入理解,对之前的进程内容的有些部分做了简单的抽象,接下来我们学习的是比进程粒度更细的一个概念——线程。在这部分内容中,我们除了学习主线的内容外,还会对之前的內容稍作补充和修改,这都是会在文章中提到的。资源共享:同一个进程中的所有线程共享该进程的资源,包括全局变量、堆栈和文件描述符。这使得线程之间的通信和数据交换更加高效。

2024-12-28 22:13:34 1006

原创 Linux系统编程——详解页表

页表是我们之前在讲到程序地址空间的时候说到的,它是物理内存到进程程序地址空间的一个桥梁,通过它物理内存的数据和代码才能映射到进程的程序地址空间中,在信号这一节我们又提到了内核空间的页表,讲到了该内核级页表不同于前面说的用户级页表是每个进程都有的,内核级页表整个系统只有一份。但是之前我们对页表的理解还都处于一个比较简单的层面,事实上页表的实现还是比较复杂的,这次我们深入理解一下页表的构成及其功能。1、进程虚拟地址和物理内存的解耦在二级页表中,每个页表条目记录的是页面(page)的位置,未加载的页面会存储为。

2024-12-27 21:39:05 1004 3

原创 Linux系统编程——理解系统内核中的信号捕获

如果 用户的自定义处理信号方法内部, 还会发送其他信号, 并且用户还对其进行了捕捉. 那么 信号的处理就无止尽了. 这种情况是不允许发生的.所以 可以通过使用。

2024-12-23 22:27:37 982 3

原创 Linux系统编程——系统内核中的信号

在信号之前讲到的所有进程信号的产生都需要OS来执行,为什么?我们提到进程在接收到信号之后通常有着三种处理方式,那么针对这三种处理方式,进程是立即处理的吗?如果不是立即处理,那么信号是否需要暂时被进程记录下来?记录下来放在哪里呢?一个进程在没有收到信号的时候,怎么知道自己应该对合法信号作何处理呢?怎么理解OS向进程发送信号?是怎么发送的?具体情况是什么?接下来我们将从系统内核层面着重讨论和理解进程信号产生之后进程处理信号的详细操作以及进程信号的产生到进程接收之间内核做了哪些事情。

2024-12-22 21:39:43 1121

原创 Linux系统编程——信号

在Linux操作系统中,进程信号是一个非常重要的概念。我们在前面的文章中已经见识过了进程信号了,比如我们在进程的一章中,尝试过向进程发送9号信号来终止进程(所以对于用户来说,我们可以通过向进程发送特定的信号使得进程完成某些指定的动作。signal()捕捉信号:其是一个系统调用接口,作用是捕捉进程信号,并由用户处理。可以看到该函数的函数声明:signal(intsignum。

2024-12-22 09:56:56 771

原创 Linux系统编程——System V 共享内存

System V 消息duilieSystem V 共享内存System V 信号量我们下面主要研究的是物理内存。

2024-12-17 11:46:22 771 1

原创 Linux系统编程——进程间通信

在我们学习进程的时候,我们知道正是因为程序地址空间的存在,所以进程之间具有独立性,他们互不影响,但是在我们的实际应用中,进程之间总会有需要通信的时候,那么这个时候的程序地址空间就是进程间通信的一个阻碍了,那么此时该怎么办呢?匿名管道 的生命周期 取决于什么时候彻底关闭管道文件(即pipe文件的打开计数为0)匿名管道 是面向字节流的匿名管道 自带同步机制(pipe满, 则writer阻塞;pipe空, 则reader阻塞), 即自带访问控制机制。

2024-12-13 10:15:18 1200 1

原创 Linux系统编程——超级详细讲解静态库、动态库的创建、打包和使用

在Linux环境下,我们使用gcc编译连接代码时,可以分为静态链接和动态链接。静态链接即在编译链接时,将代码所使用到的静态库文件代码全部加入到可执行文件中(拷贝实质上是将库文件的代码展开拷贝至我们的可执行程序的代码段。,这样做的缺点是可执行文件会生成的比较大,优点是此时再运行可执行文件就不需要再查找库了。静态库文件一般以.a结尾。动态库链接不会在编译时将动态库文件的代码加入到可执行文件中,而是在可执行文件运行时,去查找所需的动态库,并将其加载到相应的进程中,并且不同的进程可以共享这些动态库。

2024-12-08 21:12:45 2121

原创 Linux操作系统——Linux的磁盘管理系统、文件inode及软硬链接

在上一篇文章中我们了解到了操作系统对打开的文件即加载到内存中的文件的一系列操作,但是整个计算机中还存在着许许多多的没有被打开的文件,这些文件又是存在在哪里呢?操作系统对这些文件都是怎么管理的呢?

2024-12-06 21:06:12 958 1

原创 Linux操作系统--文件的重定向以及文件缓冲区

上一篇讲到了文件描述符,我们知道每次自己新创建的文件描述符都是默认从3开始的,因为stdin、stdout和stderr分别对应的0、1、2是默认打开的。所以后面是从3开始的。接下来我们分别关闭0、1、2的文件再创建新的文件看看有什么影响上面我们已经知道了通过关闭文件来实现重定向,但是这个未免也太过于麻烦,系统中已经给出了重定向的接口,我们先来介绍一个:dup2()可以看到,dup2()接口的两个参数分别是两个文件描述符,并且newfd是oldfd的一份拷贝(

2024-12-05 21:25:53 920

原创 Linux系统编程——文件

操作系统下一切皆文件!我们知道open()接口的返回值是文件描述符,先打印出来几个看看这里出现了问题,为什么这个文件描述符是从3开始打印的,0、1、2去哪里了。实际上0、1、2是被默认打开的,0代表的是标准输入,对应的是键盘。1代表的是标准输出,对应的是显示器,2代表的是标准错误,对应的是显示器。在Linux进程运行的时候就会先打开这三个文件验证:打印出来他们的文件描述符看看。

2024-12-03 09:58:47 971

原创 Liunx系统编程——shell的简单实现

现在我们实现的这个简易的shell是系统的bash的子进程,所以它会继承bash的全部环境变量,因此,我们在自己的shell中仍然可以访问和使用bash中的环境变量。从上面的分析来看,显然我们需要改变的是父进程的路径,也就是我们自己实现的shell的路径而不是子进程的路径,改变子进程的路径没有任何意义,这个时候就需要使用我们的内建命令了。我们可以看到用系统的bash执行命令之后,他会自动带上颜色,我们自己实现的却没有,那是因为我们执行的命令都是裸的命令没有经过任何的配置,我们先看看系统的命令。

2024-12-01 17:16:20 1193

原创 Linux系统编程——进程替换

一般情况下,对应的语言写的程序只能调用对应的语言的接口,对于其它类型的语言的接口,如C++就不能 调用java或者python的接口,那如果我们想要调用别人的接口怎么办?所以进程程序替换就能很好的解决这个问题,这样我们就可以使用现成其他语言接口的程序而不用费力地去再实现一个,很大程度上能减少我们的编程成本。

2024-11-30 18:45:54 1236

原创 Linux系统编程————进程控制

我们在这一篇首先认识了如何利用fork()函数来创建一个子进程,介绍了创建子进程的过程。在这一篇详细介绍了父子进程的代码和数据共享的问题(写时拷贝)。但是我们之前的实验都是为了演示子进程创建成功的现象,并没有说明子进程创建失败是什么结果,且在这一篇我们还介绍了许多进程的状态,其中提到了僵尸进程,这是一种在子进程退出时没有被父进程读取所产生的一种状态。所以在这篇文章中,我们再深入认识一下进程的终止和进程的等待。

2024-11-28 20:41:52 1050

原创 Linux系统编程——程序地址空间

接下来,我们看这么一个现象:我们实现一个代码让父子进程打印同一代码段里的同一数据可以看到父子进程打印的该数据的地址都是相同的, 这无可厚非,因为我们之前在进程那一节说到过,子进程和父进程的代码和数据(只要任意一方不修改数据)是共享的。现在对这个代码稍稍做一个改动,在子进程片段中对数据进行修改如下。

2024-11-25 16:14:49 815 1

原创 LINUX系统编程之——环境变量

试想我们在Linux命令行中输入指令的时候,如我们在不同的目录或者文件夹下输入ls、pwd、cd等等命令的时候,我们并没有带路径的名称,但是系统仍然给出了我们正确的反馈,那么系统是怎么知道我们这个时候是在哪个路径下呢?上面我们知道了凡是在PATH的路径下的命令在运行的时候都不需要添加路径,那么我们能否将自己写的程序添加进这个路径下呢?子进程的环境变量来源于父进程,就我们从命令行运行的进程来说,这些环境变量的来源都是shell,而shell进程的环境变量也来源于它的父进程,这样一直向上推,可以推到1号进程。

2024-11-22 21:27:21 1268

原创 Linux系统操作——进程状态

在前面的文章中,我们已经介绍了进程的概念,和如何取获取进程相关的属性及进程相关性的信息,以及如何去创建一个子进程。可是我们知道,系统中的内存资源是非常宝贵的,且系统中存在着大量的进程,对于这些进程,系统需要给其分配所需要的资源,对于如今的单核或者多核的计算机,想象一下,如果大量的进程同时需要进行处理,那么会产生什么样子的后果呢?所以为了整个操作系统的稳定和效率,操作系统会对进程进行调度、管理,于是就需要对进程状态进行分类,操作系统需要知道哪些进程是可运行的,以便将它们分配给可用的CPU核心;

2024-11-20 11:36:59 1247

原创 Linux:进程的初见面

在操作系统中,进程是一个很关键的概念,进程程序的一个执行实例吗?还是正在执行的程序?还是说进程是担当分配系统资源(CPU时间、内存)的实体?想象一个这样的场景,当你写完一个程序的时候,在没运行的时候,代码存在于哪里呢?存在于磁盘中,当程序运行的时候,程序就会被加载到内存之中,此时该程序就是进程吗?显然还不是。在一个操作系统中,除了运行你的程序之外,还运行着其他的程序,那么系统中这些程序都是杂乱无章的吗?当CPU处理这些任务的时候考不考虑优先级呢?运行中程序的描述组织过程。

2024-11-18 20:55:00 958

原创 Linux项目自动化构建工具—make与makefile

例如,下面的Makefile文件,目标文件test的形成依赖于test.o文件,但是test.o文件不存在,所以寻找test.o文件的依赖关系,找到test.s文件,而test.s文件也不存在,再找test.s的依赖关系,就这么一层层找下去,直到找到最后一个文件的依赖关系,生成test.i文件,再一层层往上生成,所以看起来有点像一个堆栈的过程。Makefile带来的好处是“自动化编译”,一旦写好的话,只需要一个make命令,整个工程的完全自动编译,极大的提高了软件开发的效率。Makefile是一个文件。

2024-11-14 18:02:44 830 1

原创 Unordered_map和Unordered_set的底层实现(C++)

应用链地址法处理溢出的情况时需要增设链接指针,看起来似乎增加了存储开销,但是事实上由于开地址法必须保持大量的空闲空间以确保搜索的效率,而表项所占的空间又比指针大很多,所以使用链地址法比开放空间法更节省存储空间。

2024-07-27 10:33:39 1277 1

原创 红黑树的简单实现(C++)

红黑树是一种二叉搜索树,但是在每个结点上增加一个表示该点颜色的存储位,可以是Red或者Black,通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,相对于AVL树来说,红黑树是平衡。

2024-07-16 16:42:55 965

原创 AVL树的C++实现

首先我们要实现的是关联式容器,与序列式容器不同,其里面存储的是<key,value>的结构的键值对,这种存储在数据检索时比序列式容器的效率更高。其次,我们构造一个三叉链,除了定义两个孩子结点,还需要一个指向父亲的结点。接着,我们还需要一个平衡因子,方便我们监视和调整结点的子树的高度以满足平衡。所以我们给出下列类模板//三叉链int _bf;//balance factor平衡因子//存储的键值对, _bf(0), _kv(kv){}

2024-07-15 15:21:04 790

原创 STL—vector类的简单实现

上次介绍了STL的string类,这次介绍一下STL中的vector,vector类似于数据结构中的顺序表,那么string也是一个数组,它与vector的区别是什么呢?首先对于string类,因为其是字符数组,里面存有'\0',其次其可以实现字符的比较或者'+='之类的操作符重载。而vector里没有’\0‘,'+=',因为’+=‘对于其毫无意义。1、vector是一个表示可变大小数组的序列容器。

2024-07-04 21:52:35 1106

原创 STL-string类的实现

string就是字符串的意思,是用来表示字符序列的类,是C++用来代替char 数组的数据结构,里面封装了一些关于操作字符串的方法,该string类的接口与常规容器的接口基本相同,同时再添加了一些专门用来操作string的常规操作。但是不能操作多字节或者变长字符的序列。所以综上所述,我们就可以将string类理解为一个数组,只不过存储在该数组中的元素类型为char类型,且其大小可以实现动态增长,而且在数组末尾隐藏了'\0'

2024-06-27 16:22:40 763

原创 常见的排序算法

1)如果元素集合越接近有序的话,则直接插入排序算法的时间效率越高2)时间复杂度为考虑最坏的情况,对于一个有着n个元素的集合,则第二个元素需要一次排序,第三个需要两次...第n个元素需要n-1次,利用等差数列求和公式可以得出其时间复杂度。3)空间复杂度为4)稳定性:稳定1)希尔排序是对直接插入排序的优化2)当gap>1时进行的排序都是预排序,其目的是让数组更加接近有序。当gap=1时,数组已经接近有序了,这样就很快。对于整体而言,可以达到优化的效果。

2024-05-31 17:07:37 737 1

原创 堆的C语言实现

如果有一个元素的集合,,将其所有的元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足且且)i=0,1,2...,则称为小堆(大堆)。将根结点最大的堆叫做最大堆或者大根堆,反之,根结点最小的堆叫做最小堆或者小根堆。

2024-05-29 20:51:36 681

原创 二叉树C语言简单实现

非线性结构、有一个根结点(无前驱结点)、除根结点外其余节点被分为互不相交的集合、子树不能有交集。

2024-05-28 09:31:07 789

原创 队列的C语言实现

队列是只允许在一端进行插入数据操作,在另一端进行删除数据的操作的特殊线性表,队列具有先进先出(FIFO)。进行插入操作的一端称为队尾,进行删除操作的一端称为队头。

2024-05-27 15:55:21 174

空空如也

空空如也

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

TA关注的人

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