Linux
文章平均质量分 76
Linux
码农也是农...
哈哈哈哈哈哈哈哈
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
27.epoll(三)
我们这里使用的是用户空间用于我们文件描述符的传递,事件通知用我们对应的eventfd。我们使用管道,既可以唤醒对应的Reactor,也可以唤醒对应的条件变量。每次发送消息和接收消息,都进行更新时间(这样我们就能做连接管理了)有任何一个请求到了,Master进程不做任何的处理,直接通知子进程。由一个Master创建多个子进程,然后用管道进行通信。我可以用以前的客户端来向我们的服务器进行发起请求。我们要将给文件描述符的关心事件全部都进行更改。epoll啥都能进行关心(包括管道)原创 2025-11-21 17:03:55 · 299 阅读 · 0 评论 -
27.epoll(二)
IOService只是进行连接的获取,而我们对应的Listener只是进行连接的建立,处理信息式交给我们对应的上层的。我们虽然将一轮全部都读取完了,但是我们还不能确定报文是否读取完整了(所以我们要引入对应的协议)上面的整体我们已经完成了,所以现在我们对应的矛盾就转移到了对应的IOService了。这个是关于我们对应的epoll模型的,不进行改变。上一篇博客的代码我们将会进行一些微调。那么我们如何发送数据呢?这里我们将方法抽离出来。原创 2025-11-21 11:28:31 · 532 阅读 · 0 评论 -
27.epoll(一)
(LT模式)水平触发模式: 只要底层有数据,就一直告知上层,条件是就绪的(ET模式)边缘触发模式: 当收到新的数据是就会通知对方一次!(从无到有,从有到多,变化(增多)的时候,才进行通知对方)所谓的张三就是我们对应的 (epoll && LT),快递就是我们对应的数据,小车就是我们的输入缓冲区打电话就是我们的通知机制所以ET单位时间内,IO吞吐量更多但是ET这样做是有代价的!!!原创 2025-11-20 22:34:33 · 738 阅读 · 0 评论 -
26.poll
poll就和select是一样的poll将我们的事件全部都定义出来了(本质上就是宏)我们主要就是看对应的POLLIN(读事件) 和 POLLOUT(写事件)而那个short就是我们对应的位图。原创 2025-11-19 16:50:43 · 314 阅读 · 0 评论 -
25.多路转接select
输出型参数,表示几秒内进行阻塞如果一个fd只关心读,就将fd添加到读fd_set里面,以此类推用结构体进行包装,就能避免我们因为传参,导致的数组降级之类的情况发生我们来大概看一下我们对应的fd_set的大小。原创 2025-11-19 15:00:57 · 562 阅读 · 0 评论 -
24.五种IO模型与非阻塞IO
IO = 拷贝 -> 充分的利用我们的硬件资源。原创 2025-11-18 22:04:36 · 182 阅读 · 0 评论 -
23.NAT,代理,内网穿透
网络层,是提供了对应的路径选择的能力真正干事的就是对应的各个主机的数据链路层RARP是mac转IP,所以这个非常容易,直接向该主机发送对应的请求,将其IP进行获取即可1.应用层进行序列化成为对应的字符串,向下交付到TCP发送缓冲区2.到了TCP缓冲区,根据一系列的流量控制等操作,将其划分成几个数据段3.向下添加TCP报头,再向下添加IP报头,再封装mac帧,然后进行发送4.到底目标主机,然后进行解包和分用,一直向上进行交付5.以流式将我们对应的有效载荷拷贝到接收缓冲区中。原创 2025-11-18 15:35:29 · 288 阅读 · 0 评论 -
22.数据链路层
网卡有一种混杂模式,可以将所有的数据直接全部都进行上传(后续再讲)进行碰撞检测,然后再进行碰撞避免(主机进行休眠一段时间)这个局域网就相当于是临界资源,然后碰撞检测和碰撞避免就是保护临界资源的一种方式(类似于锁的功能)原创 2025-11-18 09:22:59 · 206 阅读 · 0 评论 -
21.网络层
局域网进行通信,本质是数据链路层来进行的IP就是将数据进行转发,但是伴随着丢包的风险,但是TCP会进行超时重传,一次丢包没关系,那就再进行传递TCP解决的是通信策略的问题,IP解决的是具体的转发的问题,两个共同合作,可以进行主机之间的数据转发。原创 2025-11-17 17:29:31 · 469 阅读 · 0 评论 -
20.传输层协议TCP
TCP和UDP不同,TCP既有发送缓冲区,又有接收缓冲区,UDP只有接收缓冲区。原创 2025-11-16 20:20:49 · 336 阅读 · 0 评论 -
19.传输层协议UDP
16为UDP长度 = (UDP首部(8字节) + UDP数据(报文))如果,打游戏的时候,需要快速传递信息,就算网络波动导致丢包也没事。UDP不可靠不是缺点,而是特点(有时候,我们就需要简单通信)原创 2025-11-16 11:36:27 · 250 阅读 · 0 评论 -
18.HTTP协议(三)
如果有公司层面进行保证我们的通信安全,我们可以省去对应的加密过程,通过http,以便于我们更快的进行通信。后续的操作,就是在我们的Login里面进行Request和Response之间的操作了。请求ip的变化,用户行为等变化,可以将我们的session进行失效,进行重新登录。这样上传传入的/login的时候,就自动到我们对应的Login()中了。这样我们每一次进行请求的时候,都会自动携带我们的Cookie。如果我们不带我们的Cookie的话,我们就要一直进行身份验证。原创 2025-11-15 22:13:17 · 1138 阅读 · 0 评论 -
18.HTTP协议(二)
我们现在是任何的访问内容都是给其返回一个字符串,浏览器自己可以进行解析(图片还是文本),但是我们的返回字段中,要加上对应的内容信息。对于浏览器和服务器的http版本来说,一般是不同的,我们传递消息时,一定要将该版本进行交换。当用户只请求我们对应的首页或者/,那么就直接变成默认的index.html。对于我们的返回信息,要包含状态码和对应的状态状态码对应的string值。我们通过图标来去向浏览器发送新的请求,是通过前端的<a>标签进行的。所以,我们在收到对应的信息的时候,我们应该加上我们的默认页面路径。原创 2025-11-15 16:16:38 · 1147 阅读 · 0 评论 -
18.HTTP协议(一)
应用层协议往往和端口号是强关联的,比如说http(80),mysql(3306),所以我们不需要体现这个端口号浏览器会自动添加端口号当服务器端得到了对应的URL的时候,要将字符重新进行decode(解码)原创 2025-11-14 21:08:40 · 311 阅读 · 0 评论 -
17.TCP编程(二)和序列化
要使用的时候,我们直接查就行了private:int _x;int _y;char _oper;private://结果int _code;//出错码,0,1,2,3,4。原创 2025-11-14 11:54:50 · 1057 阅读 · 0 评论 -
17.TCP编程
目前我们的TCP代码和UDP代码,只有创建sockfd时,是不一样的(SOCK_STREAM和SOCK_DGRAM)但是我们来一个用户,创建一个进程,但是进程创建的成本太高了,我们可不可以替换成多线程呢?对于我们的线程池,比较适合处理短任务,或者是用户量较少的情况(因为线程池的个数是固定的)我们如果创建多线程进行通信的话,我们不需要关闭文件描述符表。我们目前写的是一个单进程的程序,所以只能由一个人来发消息。read来读取,write来写(和文件一样)TCP是面上字节流的,所以我们可以直接使用。原创 2025-11-13 16:23:35 · 671 阅读 · 0 评论 -
16.udp_socket(三)
public:nocopy(){}当我们的服务器不想被拷贝,我们可以进行继承上面的nocopy的类即可//表示本地主机public:nocopy(){}public:// 1.创建套接字// 2.1 bind :: 设置进入内核中if(n < 0)if(n > 0)//1.消息内容 && 2.谁给我发的") == 0)//移除观测者message = cli.Addr() + "# " + "我走了,你们聊!原创 2025-11-12 21:02:19 · 413 阅读 · 0 评论 -
16.udp_socket(二)
if(n > 0)//1.消息内容 && 2.谁给我发的//2.新增用户。原创 2025-11-12 16:24:25 · 1040 阅读 · 0 评论 -
16.udp_socket
对于我们的client,我们就不进行封装了,我们就直接进行对应的实现即可(有时间的可以尝试实现封装)所以这里的客户端由我们对应的OS自动进行随机bind(不用被别人知道)所以,我们的服务器根本就不需要ip,只要一个port来标识唯一性就行了。bind的本质就是将我们对应的_sockfd设置进入内核中。打印对应的发送消息的客户端的IP + 端口。后续我们的网络转主机,就使用这个。返回值为一个文件描述符。原创 2025-11-11 22:39:45 · 588 阅读 · 0 评论 -
15.网络基础概念
所以,我们的TCP/IP协议就是解决主机之间变远了。原创 2025-11-11 18:33:53 · 252 阅读 · 0 评论 -
14.封装线程池 和 线程结束
当线程在条件变量下等待的时候,是不能进行Join的。加了锁,忘记释放,又加了锁(这时一直在锁上等待)我们要有一个新的static的锁来保护这个单例。但是单例会不会被多个线程调用呢?但是每一次都要进行加锁的话,效率就比较低了。这样就将大部分线程拦住在第一个if下面了。单线程可能产生死锁吗?上面的构造不用返回值。原创 2025-11-10 19:03:38 · 405 阅读 · 0 评论 -
14.日志封装和线程池封装
这里定义宏的好处:在该文件进行调用时,会将代码进行宏替换到对应的文件,然后__FILE__和__LINE__就能识别是哪个代码的哪一行int main()return 0;NEW,RUN,STOPprivate://这个地方不能写成成员方法// {// }t->_func();if(n!= 0)if(n!= 0)if(n!原创 2025-11-10 16:41:38 · 924 阅读 · 0 评论 -
13.POSIX信号量
可以看往期博客(了解即可,怎么使用的根据兴趣)太麻烦了,我们直接使用POSIX信号量。原创 2025-11-09 21:21:17 · 917 阅读 · 0 评论 -
12.线程同步和生产消费模型
这里如果是单生成单消费,那么就没有问题,但是如果是我们对应的多生产和多消费,那么这样就行不通了,因为我们唤醒,是要将所有的代码进行唤醒,而不是只进行唤醒一个线程。答案是生产者,所以当我们进行生产的时候,就将等待的消费者进行唤醒(前提是要有消费者),生产者等待时也同理。这里我们创建了2个生产者,3个消费者(我们刚刚改了while,所以支持多生产多消费了)所以的线程互斥,线程同步的机制,都在我们对应的Equeue和Pop里面进行完成。所有,我们可以加上两个成员函数,来统计我们的生产者和消费者等待的个数。原创 2025-11-09 19:16:17 · 980 阅读 · 0 评论 -
12.线程同步与互斥
/临界资源//锁本身是全局的,那么锁也是共享资源//加锁//1.抢票//解锁elsebreak;int main()//1.构建线程对象i < NUM;i++)//2.启动线程//3.等待线程return 0;但是锁本身就是临界资源,那么谁保证锁的安全呢?加锁和解锁被设计成为原子的(本身就是原子的)如何看待锁呢?二元信号量就是锁!加锁的本质就是对资源展开预定!整体使用资源!如果申请锁的时候,锁被别人已经拿走了,怎么办?其他线程要进行阻塞等待。原创 2025-11-09 14:42:17 · 857 阅读 · 0 评论 -
12.线程库和线程池封装
/默认不分离#endif。原创 2025-11-08 18:11:23 · 551 阅读 · 0 评论 -
12.线程控制
线程是进程的一个执行分支,线程在做任何事情,就是进程在做,野指针本质就是查询页表失败,然后MMU报错,CPU内部触发软中断,根据软中断的中断号处理中断向量方法,给目标进程发送信号。我们拿到的只是FILE*(前面博客里有我们自己实现的简单stdio的库,那个里面的FILE,就是我们自己进行维护的)所有的线程都能看到我们任意的一个方法(函数),全部的线程数据共享,代码也是共享的。多线程中,所有的资源都是共享的(独立的栈,但是想访问也是有方法的)答案是不行的,因为程序替换,会将代码进行替换,导致其他的线程奔溃。原创 2025-11-08 14:47:48 · 886 阅读 · 0 评论 -
12.线程(二)
TLB缓冲的是虚拟到物理地址的映射,cache缓存的是代码和数据块(进程间切换,前面都会失效,但是线程间切换不会失效)也就是说,我们有一个创建一个轻量级线程,只要给这个线程一个函数的入口地址就可以了。pthread库属于第三方库,我们要加对应的-l选项。直接执行中断逻辑(默认处理方法),然后将其处理即可。重复的访问,就可以进行优化,减少时间消耗。然后从MMU里面出来的就是物理地址。硬件快,所以要硬件自动完成。线程创建的个数一般都等于。原创 2025-11-07 17:29:29 · 271 阅读 · 0 评论 -
12.线程(一)
应该子进程退出的时候,系统默认对其的信号是Ign的,所以我们看不到对应的反应所以,现在我们对应的子进程退出时,确实会给父进程发送信号,我们就能基于信号,来进行回收子进程。原创 2025-11-07 11:38:59 · 333 阅读 · 0 评论 -
11.Linux进程信号(三)
将系统调用号,放到寄存器中,然后触发系统调用(int $0x80),然后自动查表,执行对应方法本质上系统调用就是为了提供安全的访问环境。原创 2025-11-06 21:06:27 · 1163 阅读 · 0 评论 -
11.Linux进程信号(二)
我们不需要对pending表进行修改,因为,pending表不需要被修改(上篇博客(ctrl + c,ctrl + \等)全部都是修改我们的pending表的)同理,我们的handler表,也不需要进行修改,因为我们的signal()函数就是进行修改handler表的。我们看到这里的1成功显示出来了,但是因为,我们的2号信号被屏蔽了,虽然到达了,但是进程还是在跑的。信号屏蔽解除了,所以,我们的pending表的位置还是1,执行默认的操作,然后就退出了。所有的内核区的数据,全部都是用的一块页表进行映射。原创 2025-11-06 17:25:28 · 644 阅读 · 0 评论 -
11.Linux进程信号(一)
这里默认将core进行关闭的,但是如果进程出错了,那么就会重启(这样就一直出错,一直重启),那么哦我们的磁盘上很容易被打满core.xxx。OS不会处理Eflags,只会处理信号,所以Eflags里面的标志位一直都是1,所以就是死循环。所以,我们就知道了,对于我们的信号有默认的处理方式,并且我们还可以设置相关的信号处理方式。我们的新一点的服务器,只会生成core(避免一直生成core.xxx,一直只有一个)如果我们将所以的信号全部都进行捕捉,那是不是我们对应的进程就永远都杀不死了?原创 2025-11-06 13:01:11 · 1068 阅读 · 0 评论 -
10.进程间通信(五)
删除的cmd也和共享内存是一样的查询消息队列:删除操作消息队列和共享内存的接口大部分都是一样的进程间通信这里,我们只需要见过命名管道,匿名管道,共享内存(信号量,消息队列不考虑)原创 2025-11-05 21:07:45 · 430 阅读 · 0 评论 -
10.进程间通信(四)
共享内存,就是操作系统在物理内存开辟的一块空间,根据页表的映射,到我们对应的进程地址空间的共享区,所以操作系统提供的资源,能被所有的进程看到。操作系统给你分配的是4096*2,但是你要的是4097,就给你显示4097(用户要啥就给你啥)(建议使用4096的整数倍)这里我们用管道传输数据时的拷贝是非常小的,主要还是通过我们的共享内存来进行我们对应的数据交互。目前,我们还只是进行我们对应的创建共享内存,并进行挂接,还没有进行通信操作。管道有自己的保护机制,而共享内存是没有对应的保护机制的。原创 2025-11-05 16:12:57 · 842 阅读 · 0 评论 -
10.进程间通信(三)
我们的key为了避免冲突,所以系统提供了生产的函数所以共享内存和named pipe原理是一样的,提供给用户一个不会修改的东西标识唯一性。原创 2025-11-05 10:59:39 · 812 阅读 · 0 评论 -
10.进程间通信(二)
std::cout << "我是下载任务..., pid: " << getpid() << std::endl;void Log()std::cout << "我是日志任务..., pid: " << getpid() << std::endl;void Sql()std::cout << "我是数据库同步任务..., pid: " << getpid() << std::endl;public:private:然后我们还应该,增加一个选择任务的接口返回我们的随机数。原创 2025-11-04 20:35:28 · 1294 阅读 · 0 评论 -
10.进程间通信(一)
管道,是比较古老,经典的通信方式!原创 2025-11-04 14:39:08 · 1029 阅读 · 0 评论 -
9.磁盘文件系统(三)
静态库没有上面这些,静态库就是将我们的.o文件中的Section进行合并,所以体积会变大。原创 2025-11-03 20:55:02 · 908 阅读 · 0 评论 -
9.磁盘文件系统(二)
通过start_inode确定在那一个组里面,inode - start_inode 得到我们的inode Bitmap对应的位号,找到我们的inode Table,然后对应到我们的Data blocks。所以,在文件系统中,我们只要找到一个inode编号就行,通过inode编号确定,然后再看inode Bitmap是否是合法的,如果是合法的,就再找inode Table里面索引Data blocks。先进行查找,将Block Bitmap和inode Bitmap里面的内容由1置0,然后GDT进行修改。原创 2025-11-03 11:12:09 · 772 阅读 · 0 评论 -
9.磁盘文件系统(一)
这两个问题,我们要先理解磁盘的结构才能进行回答。原创 2025-11-02 21:02:11 · 156 阅读 · 0 评论
分享