C语言
文章平均质量分 59
古德jiò
这个作者很懒,什么都没留下…
展开
-
手写死锁检测组件
死锁概念 多个进程或线程互相等待对方的资源,在得到新的资源之前不会释放自己的资源,这样就形成了循环等待,这种现象被称为死锁。四个产生原因(都需要满足): 1、资源互斥:资源只有两种状态,只有可用和不可用两状态,不能同时使用,同一时刻只能被一个进程或线程使用。 2、占有且请求:已经得到资源的进程或线程,继续请求新的资源,并持续占有旧的资源。 3、资源不可剥夺:资源已经分配进程或线程后,不能被其它进程或线程强制性获取,除非资源的占有者主动释放。 4、环路等待:死锁发生时,系统中必定有两个或两个以上.原创 2022-01-24 20:21:54 · 255 阅读 · 1 评论 -
cpu绑定进程
#include <stdio.h>#include <string.h>#include <stdlib.h>#define __USE_GNU#include <sched.h>#include <unistd.h>#include <pthread.h>#include <sys/syscall.h>void process_affinity(int num) { //gettid...原创 2022-01-19 20:02:36 · 435 阅读 · 0 评论 -
池式组件之异步请求池
请求池 用于请求第三方服务,如mysql/redis,下图中第三列是第三方服务。当大批量数据去请求第三方服务时(单线程),阻塞等待返回是十分耗时的操作(及时单次阻塞等待时间很短),因此可以引入异步请求池。 基本原理就是业务服务器请求第三方服务后,不阻塞等待,用另外一个线程去等待结果要点1、发送请求是多个io,即业务服务器与第三方服务器之间有多个fd连接,因为单fd的话,一次只能申请一次服务2、在发送请求之后,将fd利用epoll_ctl加入到epoll中,接受结果的线程去判断epoll中数据原创 2022-01-17 21:05:05 · 747 阅读 · 0 评论 -
池式组件之线程池(c语言实现)
目录线程池的作用线程池的工作原理线程池代码技术参考线程池的作用1、减少线程创建与销毁的开销2、异步解耦的作用,如日志,主线程要求高性能,写日志写多了就耗时,那么将日志任务交给线程池来处理,就能保证主线程高效线程池的工作原理线程池是当做组件在使用的。线程池需要提供的API:1、创建 create2、插入任务 push_task3、销毁 destroy4、获取任务数量 task_count(可选)5、空闲线程数量 free_thread(可选) 可以把线程池理解为银行大堂,处理业务的柜原创 2022-01-16 19:28:22 · 291 阅读 · 0 评论 -
用户态协议栈之TCP/IP设计
协议栈数据组成格式用户层:用户数据传输层:8个字节udp头+用户层网络层:20个字节的ip头 + 传输层链路层:14个字节的以太网头 + 网络层网卡(在链路层和物理层之间):将链路层数据经过DA转换,变成电信号/光信号以太网头#pragma pack(1)#define ETH_ADDR_LENGTH 6// 以太网的头struct ethhdr{ unsigned char h_dst[ETH_ADDR_LENGTH]; unsigned char h_src[E原创 2022-01-12 21:17:22 · 998 阅读 · 1 评论 -
协程设计原理(理论)
网络编程与协程原理为什么有协程,协程用来干什么?原语操作大致思路实现方法协程适用场景技术参考为什么有协程,协程用来干什么?协程有着同步的编程方式,异步的性能。即写代码是同步的方式写的,运行起来是异步的异步:检测io(调度器)与io操作不在一个流程中。如检测io(epoll_wait()判断fd读写状态)与io操作(send(),recv())同步:检测io与io操作在一个流程中//以网络io为例 同步的写法(单线程)有着多线程的性能while(1){ epoll_wait() for(;;原创 2022-01-10 20:58:42 · 443 阅读 · 0 评论 -
UDP可靠传输(KCP))
在阅读本文之前,可以先阅读一下之前的文章,了解tcp是如何保证可靠传输的本文主要以KCP协议展开讲解,KCP是UDP可靠传输协议分片 链路层具有最大传输单元MTU这个特性,它限制了数据帧的最大长度,不同的网络类型都有一个上限值。以太网的MTU是1500,你可以用 netstat -i 命令查看这个值。如果IP层有数据包要传,而且数据包的长度超过了MTU,那么IP层就要对数据包进行分片(fragmentation)操作,使每一片的长度都小于或等于MTU。我们假设要传输一个UDP数据包,以太网的MTU为原创 2022-01-09 20:56:29 · 2458 阅读 · 0 评论 -
posix api(TCP)与网络协议栈的联系
linux 下 posix api有哪些服务端1、socket2、bind3、listen4、accept5、recv6、send7、close客户端1、socket2、bind(可有可无)3、connect4、send5、recv6、close设置socket参数setsocketoptgetsocketoptsocket是什么 直译过来是插座,fd(文件描述符)是我们可以操作的,与之对应的有tcb(tcp control block),fd与tcb的生命周期相同原创 2022-01-06 22:43:03 · 1152 阅读 · 3 评论 -
c语言#include *.c
最近再看redis源码,发现了这样一行代码在这几个*.c文件中定义了相同的方法,因此在调用方法的时候会根据宏定义来选择.c文件。#include .c 实际上就是将.c中的代码复制粘贴到这里原创 2022-01-06 09:08:53 · 1297 阅读 · 0 评论 -
socket编程需要关注的点
网络编程关注的问题连接的建立通过三次握手,分两种情况:1、客户端连接服务器2、服务器连接第三方服务器int client = accept(listenfd, addr, sz);int connectfd = socket(AF_INET, SOCK_STREAM, 0);int ret = connect(connectfd, (struct sockaddr*)&addr, sizeof(addr));// 每一次调用socket相关函数,erron都会有相应的变化errn原创 2022-01-05 21:42:04 · 988 阅读 · 0 评论 -
redis,memcached
网络io职责检测ioio函数本身可以检测io的状态(通过errno),但是只能检测一个fd对应的状态,io多路复用(select)可以同时检测多个io的状态;这两者的区别是:io函数可以检测具体状态(errno),但io多路复用只能检测出可读,可写,错误,断开等(fd_set)笼统的事件;select返回的错误fd_set可以通过getsockopt()了解具体错误是什么。操作io只能使用io函数来进行操作,操作方式分为阻塞io与非阻塞io阻塞io:如调用read(),就一直在等read()返回原创 2022-01-05 21:41:55 · 550 阅读 · 0 评论 -
http小记
http粘包现象如:客户端连续3次send 1k数据,并且每次发送间隔没有很明确(可以理解为每次发送间隔很短很短),会让服务器误以为客户端一次发送了3k的数据。因此服务器只会recv一次并且send一次返回给客户端,导致客户端只recv一次,与其send的次数不匹配。解决办法1、解析http数据,用\r\n\r\n进行区分(head中每一行都有/r/n,而head与body之间有一个空行,因此会有两个/r/n)2、在http的head中定义包的长度(content-length)sendfile原创 2022-01-05 20:25:01 · 223 阅读 · 0 评论 -
websocket
websocket是什么是一个应用层协议,主要用于服务器主动推送数据给浏览器(不仅仅局限于浏览器)。如:浏览器请求登录csdn,csdn的服务器产生一个二维码信息给浏览器,浏览器显示二维码,通过微信扫描二维码,微信的服务器处理信息,然后去告知csdn的服务器哪个二维码被哪个微信扫描了,csdn服务器再主动发送用户相关数据给浏览器(csdn给浏览器发送消息是websocket在起作用),浏览器登录成功。自定义协议由tcp包本身的信息(如包的长度)和协议本身的信息(如版本号)组成协议格式1.建立连接原创 2022-01-04 21:05:21 · 710 阅读 · 0 评论 -
百万并发服务器by c
epoll本身就能支持百万并发,本文是基于recator实现百万并发服务器(关于recator可以参考之前发布的博客)接下来解释一下结构体的作用: ntyevent结构体是用于存储单个fd(clientfd与listenfd)的相关内容,每一个clientfd对应一个客户端的连接,listenfd是监听一个端口的fd ntyreactor是recator结构体,其中包含epollfd与eventblock,epollfd是用于管理单个epoll的文件描述符(即epoll_create()出来的原创 2021-12-29 21:31:14 · 612 阅读 · 0 评论 -
epoll&reactor by C
udp的服务器,如何做多个客户端并发1、在数据上加一层协议来区分客户端。但这个前提是要数据先发先到?,但是udp并不支持。2、模拟tcp,在第一次recvfrom时,创建一个fd与相应的客户端对应。信号在进程中如何工作的:1、进程的信号集合如何保存:进程中专门有一块地方保存信号2、调用signal信号如何保存到进程里面3、信号如何发送,如何捕获...原创 2021-08-09 20:45:58 · 145 阅读 · 0 评论 -
C语言,select函数的使用方法以及为何使用
I/O复用本文旨在简单介绍select与epoll的优缺点多进程服务器端的缺点和解决方法为了构建并发服务器,只要有客户端连接请求就会创建进程。这的确是实际操作中采用的一种方案,但并非十全十美,因为创建进程时需要付出极大代价,这需要大量的运算和内存空间,由于每个进程都具有独立的内存空间,所以相互间的数据交换也要求采用相对复杂的方法(IPC属于相对复杂的通信方法)。那有何解决方案呢?能否在不创建进程的同时向多个客户端提供服务? 答案是肯定能,I/O复用就是解决方法之一(还可以通过线程池解决,之后会讲解线原创 2020-09-24 17:52:07 · 3130 阅读 · 3 评论 -
线程基础知识 C语言 Linux
竞争与同步同一个进程中的线程能共享进程中的绝大多数资源,当它们随意竞争时可以导致资源会破坏、脏数据、不完整、不一致等问题。通过一些方法让进程在竞争资源时相互协调,避免出现数据不完全、不一致等问题,这就叫线程同步。临界区与临界资源被多个线程同时访问的代码叫临界区,被同时访问的资源叫临界资源。原子操作中间不会打断的操作叫原子操作。互斥量(互斥锁)pthread_mutex_t 是一种数据类型,可以定义变量int pthread_mutex_init(pthread_mutex_t *mute原创 2020-09-09 20:41:14 · 133 阅读 · 0 评论 -
C语言基础-------指针篇
什么是指针指针是一种数据类型,使用它可以用来定义指针变量,指针变量中存储的其实是整数,这种整数代表了内存的编号。为什么要使用指针:1、函数之间相独立,但有些时候需要共享变量。传参是值传递全局变量容易命名冲突使用数组还需要传递长度命名空间是独立的,但地址空间是同一个,所有指针可以解决这个问题。2、由于函数之间传参是值传递(内存拷贝),对于字节数比较多的变量,值传递效率较低,如果传递变量的地址只需要传递4|8字节。3、堆内存无法取名字,它不能像data、bss、stack让变量名与内存建立联系原创 2020-07-18 14:52:18 · 338 阅读 · 0 评论