首页
关于
Search
1
Lua使用调试库hook函数调用
429 阅读
2
傻瓜式快速搭建l2tp
385 阅读
3
游戏邮件系统数据设计因素
328 阅读
4
Linux内核数据结构kfifo小结(TODO)
314 阅读
5
傻瓜式安装chatgpt-web工具
296 阅读
项目技术
项目思考
开发环境
数据库
编程语言
生活与阅读
哲学
登录
Search
标签搜索
nodejs
npm
Typecho
累计撰写
55
篇文章
累计收到
34
条评论
首页
栏目
项目技术
项目思考
开发环境
数据库
编程语言
生活与阅读
哲学
页面
关于
搜索到
55
篇与
的结果
Linux信号笔记
信号是什么 信号是一种软中断机制实现的进程异步通讯方式。信号常见几种产生方式:用户终端某些按键,比如CTRL+C,CTRL+D,CTRL+Z,CTRL+S,CTRL+Q硬件异常。除0,无效的内存引用等用户通过kill、tkill、tgkill、sigqueue、raise函数发送给另一个进程或者进程组或者自己进程一个信号通过kill命令发送信号当检测到某种软件条件已经发生,并应将其通知有关进程。如SIGALRM、SIGPIPE(对方已经关闭读,但本端想写)、SIGURG(有带外数据)什么是可靠信号,什么是不可靠信号 由于历史原因,小于32的信号是不可靠信号。反之则为可靠信号。不可靠信号有丢失的可能信号生命周期和进程处理信号的时机 在进程安装信号处理函数后,内核向进程发送信号,其实是向目标进程相关的bitmap结构(信号向量表)中加入记录,此时信号处于pending状态。对于小于32编号的不可靠信号,如果当前已经有这个信号处理pending中,则丢弃。对于可靠信号则进入一个pending队列中。当进程调用系统函数进入内核态返回用户态之前内核进行信号的投递(delivery),转而去执行信号处理函数。这就是一个信号的完整生命周期。如果设定为阻塞,则会一直阻塞。程序对信号的响应分类执行系统默认动作。如果是可靠信号,受到屏蔽字阻塞设定的影响。这些行为一般可以归类为:ignore、terminate、core、stop、continue设置为忽略此信号。SIGKILL和SIGTOP是不能被忽略的,其他信号都可以忽略。如果是可靠信号,并设置为忽略,则不受到屏蔽字阻塞设定的影响,直接丢弃。不可靠信号没有阻塞的概念。设置为指定的用户信号处理函数处理。比如捕捉到SIGCHLD信号则表示一个子进程已经终止,可以无阻塞的调用waitpid来取得子进程ID和终止状态。同理SIGKILL和SIGTOP也不能被用户捕捉。如果是可靠信号,受到屏蔽字阻塞设定的影响。进程有多线程时,信号是由哪个线程处理的,是什么时机处理的。多个线程来说,信号处理函数是共享的。每个线程都拥有独立的阻塞信号掩码。对于多线程的进程,kill和sigqueue发送的信号必须面对所有的线程,而不是某个线程。而系统调用tkill和tgkill发送的信号,又必须递送给进程下某个特定的线程。每个线程都有自己的私有挂起队列(pending),但是进程里的所有线程都会共享一个公有的挂起队列(shared_pending)。如果是发送了指定线程,则进行线程自己队列。那么多线程情况下发送给进程的信号,到底由哪个线程来负责处理?优先查询进程的主线程是否方便处理信号。如果主线程不方便,则会遍历线程组中的其他线程。如果某个线程A设定了对这个信号阻塞、或者正在退出则不由A线程处理。最后的效果就是在这些可以处理的线程中随机一个。信号处理函数有什么要注意的,malloc是否可用呢?根据上述信号处理函数的执行流程可以看出一位问题是,普通函数可能被中断,而后执行信号函数。这是就有异步安全问题。或者说重入问题。有重入问题的函数都是不用用于信号处理函数中。这和多线程重入的概念相似,但描述的事情不同的。线程安全的函数不一定是异步重入安全的。一般的不可重入函数(man 7 signal):使用了静态变量,典型的是strtok、localtime等函数使用了malloc或free函数标准I/O函数,如printf即使是可重入函数,在信号处理函数调用前要先备份errno变量,在离开前恢复errno变量。信号为什么会打断系统调用?如何处理? 系统调用在执行期间,很可能会收到信号,此时进程可能不得不从系统调用中返回,去执行信号处理函数。对于执行时间比较久的系统调用(如wait、read等)被信号中断的可能性会大大增加。系统调用被中断后,一般会返回失败,并置错误码为EINTR。 Linux操作系统提供了一个标志位SA_RESTART来告诉内核,被信号中断后是否要重启系统调用。如果该标志位为1,则表示如果系统调用被信号中断,那么内核会自动重启系统调用。有些信号即使设置了SA_RESTART也不会自动重启,常见的有epoll_wait, select, 和有超时设置的accept和有超时设置的recv. 这些不能自动重启的函数可以man 7 signal中查看。
2021年06月26日
9 阅读
0 评论
0 点赞
哈希冲突TODO
设计哈希表时,选择不同的哈希函数有不同性能表现。重点在于哪种散列函数可以有效避免冲突。如果出现了冲突,一般都有哪些冲突解决办法。线性探测二次探测开链法(GCC使用的SGI版本STL就是基于此方法) 虽然开链法并不要求表格大小必须为质数,但SGI STL 仍然以质数来设计表格大小,并且将28个质数(逐渐呈现大约两倍的关系)计算好,以备随时访问,同时提供一个函数,用来查询在这28个质数之中,“最接近某数并大于某数”的质数。在JDK8以前也是使用链表来处理冲突。JDK8以后在链表超过8时使用平衡树来存储。建议使用头插法而不是尾插法入链。因为最近增加的元素有很大概率被下次访问。常见的哈希算法:MD5SUM、SHA1、DJBX33A(Java HashCode)、CRC32(部分硬件原语加速)、CRC16、MurMurHash(速度比MD5快)、SipHash(Redis\Python使用)哈希算法从安全性又可以分两类加密哈希函数如SHA非加密哈希函数。服务器中使用哈希算法需要考虑:哈希攻击(hash flooding attack)。不要对不明数据进行哈希。而MurMurHash和SipHash使用了种子的概念实现随机化哈希,增加了攻击的难度。因此SipHash也被称为带密钥哈希算法(Keyed Hash Function),天生免疫哈希攻击。加盐哈希方案。通过增加一些随机的盐参数,把需要加密的账号密码更安全的存储。
2021年06月26日
13 阅读
0 评论
0 点赞
Groovy语法
Groovy运行于Java虚拟机上的,所以语法也自然支持Java语法。他也有对Java语法的扩展。注意Java是静态强类型语言, 而Groovy是一个动态强类型语言。前面也已经说了他是运行于Java虚拟机上的,自动是需要安装JVM环境的。更具体的安装可以参考官网方法。如果只是为了熟悉其语法,更便捷的办法是使用线上IDE学习。比如这个:https://groovyide.com/cpi变量定义关键字def:def str = "hello world";// 定义一个字符串 def str2 = "${str}!"; // 字符串支持插值 println(str2); // 一个跨行长字符串,不支持插值 def str3 = ''' 1)正式后台 2)测试后台 '''; print(str3.replaceAll('\\s+','').trim());查看动态类型信息和断言使用 // 查看动态类型信息和断言使用 def mixed = 1; assert mixed.class == java.lang.Integer; mixed = "str"; assert mixed.class == java.lang.String; //函数调用时,参数可以不使用括号 println mixed.class.name assert mixed.class == java.lang.Integer:"not a integer" assert mixed.getClass() == java.util.HashMap : "not valid select" assert backends instanceof java.lang.Integer : "not a Integer"支持Java写法, 注意数据和字典都是使用[]符号定义,只是后者还需要使用:指定valuedef dict = ['name':'john','age':14,'sex':'boy']; //println dict dict.each{ def kv = String.format("%s == %s", it.getKey(), it.getValue()); println kv; }支持闭包
2021年06月26日
12 阅读
0 评论
0 点赞
Redis在游戏的运用(二)
在读多写少的场景,有必要进行热点数据的缓存。缓存可以有效减少DB的读压力。这样的解决方案常见的DB也是具备的。不管是Redis还是MySQL或者是MongoDB, 都有复制集群的概念。只要使用从节点读数据,主节点写数据即可。MongoDB Atlas号称可以秒级别内同步新数据到从节点。这种方案也可以称为主写从读实现读写分离。说完减少主节点压力的优点,缺点也由此引入。这种方案只能实现数据的最终一致性,无法实现强一致性。DB数据的写入一般如下:应用层insert/update/delete返回时只是更新cache和Redo,Undo日志(在Mongodb中是更新oplog),并没有真正写入磁盘。主从binaryLog/Oplog同步延迟。比如机房间网络延迟问题、服务器负载问题等。即使忽略上面同步延迟问题,是不是就没有其他问题了?DB内部的缓存模块对热点数据的定义是死的,他缓存的数据可能不是我们我们认为的热点数据。因为他负责了多个维度数据的读写。比如我只访问了一次的数据,可能因为LRU原因,真正频繁热点数据被置换出缓存。有时我们想自己定义热点数据,比如近期1小时登录的玩家(这里不仅仅包含当前在线玩家)。这里补充扩展下有意思点,MySQL使用了自己改进后的LRU算法,使用了热数据插入队列前进5/8位置。这种优化可以屏蔽全表等大面积遍历引起热点数据的完全失效。于是引进了Redis这类内存DB。在进行写时,如果是需要强一致性。先删除Redis缓存(强迫读请求去DB加载)写入DB(写入会有锁,此时会阻塞读)再删除Redis缓存(即使有读请求在1和2的过程中取到旧数据,这里也会让旧缓存失效)如果需要最终一致性:设置缓存过期时间写入DB总是先尝试更新Redis数据再进行DB更新。如果Redis没有对应数据时可以考虑不进行写入的。因为可能不是热点数据>。另外如果宕机,连接不上也不需要进行更新Redis缓存。在进行读操作时,总是先尝试从Redis中取。如果没有再从DB取。这里要使用布隆过滤防止缓存穿透问题。从DB取数据返回时也写入Redis缓存。这里要注意两个问题:缓存击穿问题:对一个数据有并发多个请求加载。此时要排队加锁。真正进入DB加载时总是先尝试Redis取。更新Redis时缓存雪崩问题。数据过期时间最好进行一个随机,防止某个时间大量数据同时过期而缓存失效。
2021年06月26日
138 阅读
0 评论
0 点赞
2021-06-26
MongoDB内存分析实践
问题现象:外服120W数据DB>使用了12GB内存,但同样的数据导入一个开发实例,只占用了5GB
2021年06月26日
140 阅读
0 评论
0 点赞
1
...
9
10
11