当前位置: 首页 > 编程日记 > 正文

Linux内核情景分析之异常访问,用户堆栈的扩展

情景假设:

在堆内存中申请了一块内存,然后释放掉该内存,然后再去访问这块内存。也就是所说的野指针访问。

当cpu产生页面错误时,会把失败的线性地址放在cr2寄存器.线性地址缺页异常的4种情况
1.如果cpu访问的行现地址在内核态,那么很可能访问的是非连续区,需要vmalloc_fault处理.
2.缺页异常发生在中断或者内核线程时,直接失败,因为不可修改页表
3.地址在一个区间内,那就可能是已经物理地址映射了但权限问题(错误处理)或者其物理地址没有分配(分配物理内存)
4.如果找到一个在线性地址其后面的vma(线性地址在空洞).那么可能是空洞上面的区间是
堆栈区,他表示动态分配而没有分配出去的空间,有一种特殊情况,可以缺页异常使得获取物理页框
5.如果找到一个线性地址气候的vma(线性地址在空洞),那么可能是空洞上面的区间不是堆栈区,说明
这个空洞是由于一个映射区被撤销而留下的,那样直接错误处理
20141120160315631.jpg
  1. ==================== arch/i386/mm/fault.c 106 152 ====================
  2. 106 asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
  3. 107 {
  4. 108 struct task_struct *tsk;
  5. 109 struct mm_struct *mm;
  6. 110 struct vm_area_struct * vma;
  7. 111 unsigned long address;
  8. 112 unsigned long page;
  9. 113 unsigned long fixup;
  10. 114 int write;
  11. 115 siginfo_t info;
  12. 116
  13. 117 /* get the address */
  14. 118 __asm__("movl %%cr2,%0":"=r" (address));//得到失败的线性地址
  15. 119
  16. 120 tsk = current;//获取当前描述符
  17. 121
  18. 122 /*
  19. 123 * We fault-in kernel-space virtual memory on-demand. The
  20. 124 * 'reference' page table is init_mm.pgd.
  21. 125 *
  22. 126 * NOTE! We MUST NOT take any locks for this case. We may
  23. 127 * be in an interrupt or a critical region, and should
  24. 128 * only copy the information from the master page table,
  25. 129 * nothing more.
  26. 130 */
  27. //如果大于3G,表示缺页异常时,访问的是内核空间,很有可能是访问了非连续的内核空间,转到vmalloc_fault处理
  28. 131 if (address >= TASK_SIZE)
  29. 132 goto vmalloc_fault;
  30. 133
  31. 134 mm = tsk->mm;
  32. 135 info.si_code = SEGV_MAPERR;
  33. 136
  34. 137 /*
  35. 138 缺页异常发生在中断时,是错误不可以的,表示是内核线程,不可以对其页表进行修改
  36. 140 */
  37. 141 if (in_interrupt() || !mm)
  38. 142 goto no_context;
  39. 143
  40. 144 down(&mm->mmap_sem);
  41. 145
  42. 146 vma = find_vma(mm, address);//查到end大于address的地址
  43. 147 if (!vma)//是否在行现地址内,不在转为错误处理
  44. 148 goto bad_area;
  45. //在线性区内,跳到正常处理部分,可能是由于权限问题,也有可能是对应的物理地址没有分配2种情况
  46. 149 if (vma->vm_start <= address)
  47. 150 goto good_area;
  48. 151 if (!(vma->vm_flags & VM_GROWSDOWN))//如果发生在一空洞上方的区间不是堆栈区,那么此地址是由于撤销映射留下的,进行错误处理
  49. 152 goto bad_area;

  1. 220 /*
  2. 221 * Something tried to access memory that isn't in our memory map..
  3. 222 * Fix it, but check if it's kernel or user first..
  4. 223 */
  5. 224 bad_area:
  6. 225 up(&mm->mmap_sem);
  7. 226 //用户态的错误处理
  8. 227 bad_area_nosemaphore:
  9. 228 /* User mode accesses just cause a SIGSEGV */
  10. 229 if (error_code & 4) {//判断错误发生在用户态
  11. 230 tsk->thread.cr2 = address;
  12. 231 tsk->thread.error_code = error_code;
  13. 232 tsk->thread.trap_no = 14;
  14. 233 info.si_signo = SIGSEGV;//强制发送SIGEGV信号
836125-20161027110921546-386581205.jpg
上面提到的第4种情况,因为越界访问而照成堆栈区间扩展的情况
836125-20161027110925593-1447682910.png
比如一进城要调用某个子程序,cpu需要把返回地址压栈,然而返回地址写入的是空洞地址,会引发一次页面异常错误
VM_GROWDOWN表示为1表示上面是堆栈区
  1. if (!(vma->vm_flags & VM_GROWSDOWN))
  2. 152 goto bad_area;
  3. 153 if (error_code & 4) {
  4. 154 /*
  5. 155 * 还要检查异常地址是否紧挨着esp指针,如果远超过32,那就是非法越界,错误处理
  6. 32是因为pusha(一次把32个字节压入栈中)
  7. 159 */
  8. 160 if (address + 32 < regs->esp)
  9. 161 goto bad_area;
  10. 162 }
  11. //扩展堆栈
  12. 163 if (expand_stack(vma, address))
  13. 164 goto bad_area;
有下面注释可知,expand_stack只是更改了堆栈区的vm_area_struct结构,没有建立物理内存映射
  1. static inline int expand_stack(struct vm_area_struct * vma, unsigned long address)
  2. 490 {
  3. 491 unsigned long grow;
  4. 492
  5. 493 address &= PAGE_MASK;//边界对齐
  6. 494 grow = (vma->vm_start - address) >> PAGE_SHIFT;//增长几个页框
  7. //判断是否超过了用户堆栈空间大小限制
  8. 495 if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur ||
  9. 496 ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->rlim[RLIMIT_AS].rlim_cur)
  10. 497 return -ENOMEM;
  11. 498 vma->vm_start = address;//重新设置虚拟地址
  12. 499 vma->vm_pgoff -= grow;//偏移减去grow
  13. 500 vma->vm_mm->total_vm += grow;//地址空间大小
  14. 501 if (vma->vm_flags & VM_LOCKED)
  15. 502 vma->vm_mm->locked_vm += grow;
  16. 503 return 0;
  17. 504 }

  1. [do_page_fault()]
  2. 165 /*
  3. 166 * Ok, we have a good vm_area for this memory access, so
  4. 167 * we can handle it..
  5. 168 */
  6. 169 good_area:
  7. 170 info.si_code = SEGV_ACCERR;
  8. 171 write = 0;
  9. 172 switch (error_code & 3) {
  10. 173 default: /* 3: write, present */
  11. 174 #ifdef TEST_VERIFY_AREA
  12. 175 if (regs->cs == KERNEL_CS)
  13. 176 printk("WP fault at %08lx\n", regs->eip);
  14. 177 #endif
  15. 178 /* fall through */
  16. 179 case 2: /* write, not present */
  17. 180 if (!(vma->vm_flags & VM_WRITE))//堆栈段可读可写,调到196行
  18. 181 goto bad_area;
  19. 182 write++;
  20. 183 break;
  21. 184 case 1: /* read, present */

  22. 185 goto bad_area;
  23. 186 case 0: /* read, not present */
  24. 187 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
  25. 188 goto bad_area;
  26. 189 }
  27. 190
  28. 191 /*
  29. 192 * If for any reason at all we couldn't handle the fault,
  30. 193 * make sure we exit gracefully rather than endlessly redo
  31. 194 * the fault.
  32. 195 */
  33. 196 switch (handle_mm_fault(mm, vma, address, write)) {
  34. 197 case 1:
  35. 198 tsk->min_flt++;
  36. 199 break;
  37. 200 case 2:
  38. 201 tsk->maj_flt++;
  39. 202 break;
  40. 203 case 0:
  41. 204 goto do_sigbus;
  42. 205 default:
  43. 206 goto out_of_memory;
  44. 207 }

  1. [do_page_fault()>handle_mm_fault()]
  2. 1189 /*
  3. 1190 * By the time we get here, we already hold the mm semaphore
  4. 1191 */
  5. 1192 int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma,
  6. 1193 unsigned long address, int write_access)
  7. 1194 {
  8. 1195 int ret = -1;
  9. 1196 pgd_t *pgd;
  10. 1197 pmd_t *pmd;
  11. 1198
  12. 1199 pgd = pgd_offset(mm, address);//获取该地址所在页面目录项的指针(页表的地址)
  13. 1200 pmd = pmd_alloc(pgd, address);//分配pmd目录
  14. 1201
  15. 1202 if (pmd) {
  16. 1203 pte_t * pte = pte_alloc(pmd, address);//分配pte表现
  17. 1204 if (pte)
  18. //分配物理地址
  19. 1205 ret = handle_pte_fault(mm, vma, address, write_access, pte);
  20. 1206 }
  21. 1207 return ret;
  22. 1208 }

  1. [do_page_fault()>handle_mm_fault()>pte_alloc()]
  2. 120 extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
  3. 121 {
  4. 122 address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);//给定地址转换为页表的下标,用于定位页表项
  5. 124 if (pmd_none(*pmd))//如果pmd所指向的页表为空,那就转到getnew分配
  6. 125 goto getnew;
  7. 126 if (pmd_bad(*pmd))
  8. 127 goto fix;
  9. 128 return (pte_t *)pmd_page(*pmd) + address;
  10. 129 getnew:
  11. 130 {
  12. 131 unsigned long page = (unsigned long) get_pte_fast();//从缓冲池获取(释放页表,并非一定会释放物理地址)
  13. 132
  14. 133 if (!page)
  15. 134 return get_pte_slow(pmd, address);
  16. 135 set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(page)));//写入中间pmd
  17. 136 return (pte_t *)page + address;
  18. 137 }
  19. 138 fix:
  20. 139 __handle_bad_pmd(pmd);
  21. 140 return NULL;
  22. 141 }

  1. [do_page_fault()>handle_mm_fault()>handle_pte_fault()]
  2. 1135 /*
  3. 1136 * These routines also need to handle stuff like marking pages dirty
  4. 1137 * and/or accessed for architectures that don't do it in hardware (most
  5. 1138 * RISC architectures). The early dirtying is also good on the i386.
  6. 1139 *
  7. 1140 * There is also a hook called "update_mmu_cache()" that architectures
  8. 1141 * with external mmu caches can use to update those (ie the Sparc or
  9. 1142 * PowerPC hashed page tables that act as extended TLBs).
  10. 1143 *
  11. 1144 * Note the "page_table_lock". It is to protect against kswapd removing
  12. 1147 * we can drop the lock early.
  13. 1148 *
  14. 1149 * The adding of pages is protected by the MM semaphore (which we hold),
  15. 1150 * so we don't need to worry about a page being suddenly been added into
  16. 1151 * our VM.
  17. 1152 */
  18. 1153 static inline int handle_pte_fault(struct mm_struct *mm,
  19. 1154 struct vm_area_struct * vma, unsigned long address,
  20. 1155 int write_access, pte_t * pte)
  21. 1156 {
  22. 1157 pte_t entry;
  23. 1158
  24. 1159 /*
  25. 1160 * We need the page table lock to synchronize with kswapd
  26. 1161 * and the SMP-safe atomic PTE updates.
  27. 1162 */
  28. 1163 spin_lock(&mm->page_table_lock);
  29. 1164 entry = *pte;//pte对应的物理地址当然没有,所以为null
  30. 1165 if (!pte_present(entry)) {//检查其对应的物理地址否为空
  31. 1166 /*
  32. 1167 * If it truly wasn't present, we know that kswapd
  33. 1168 * and the PTE updates will not touch it later. So
  34. 1169 * drop the lock.
  35. 1170 */
  36. 1171 spin_unlock(&mm->page_table_lock);
  37. 1172 if (pte_none(entry))//页表项内容为0,表明进程未访问过该页 
  38. 1173 return do_no_page(mm, vma, address, write_access, pte);//调用do_no_page分配
  39. //否则换出
  40. 1174 return do_swap_page(mm, vma, address, pte, pte_to_swp_entry(entry), write_access);
  41. 1175 }
  42. 1176
  43. 1177 if (write_access) {
  44. 1178 if (!pte_write(entry))
  45. 1179 return do_wp_page(mm, vma, address, pte, entry);
  46. 1180
  47. 1181 entry = pte_mkdirty(entry);
  48. 1182 }
  49. 1183 entry = pte_mkyoung(entry);
  50. 1184 establish_pte(vma, address, pte, entry);
  51. 1185 spin_unlock(&mm->page_table_lock);
  52. 1186 return 1;
  53. 1187 }
  54. 1145 * pages from under us. Note that kswapd only ever _removes_ pages, never
  55. 1146 * adds them. As such, once we have noticed that the page is not present

  1. [do_page_fault()>handle_mm_fault()>handle_pte_fault()>do_no_page()]
  2. 1080 /*
  3. 1081 * do_no_page() tries to create a new page mapping. It aggressively
  4. 1082 * tries to share with existing pages, but makes a separate copy if
  5. 1083 * the "write_access" parameter is true in order to avoid the next
  6. 1084 * page fault.
  7. 1085 *
  8. 1086 * As this is called only for pages that do not currently exist, we
  9. 1087 * do not need to flush old virtual caches or the TLB.
  10. 1088 *
  11. 1089 * This is called with the MM semaphore held.
  12. 1090 */
  13. 1091 static int do_no_page(struct mm_struct * mm, struct vm_area_struct * vma,
  14. 1092 unsigned long address, int write_access, pte_t *page_table)
  15. 1093 {
  16. 1094 struct page * new_page;
  17. 1095 pte_t entry;
  18. 1096
  19. 1097 if (!vma->vm_ops || !vma->vm_ops->nopage)
  20. 1098 return do_anonymous_page(mm, vma, page_table, write_access, address);//只是其封装而已
  21. ......
  22. ==================== mm/memory.c 1133 1133 ====================
  23. 1133 }

  1. [do_page_fault()>handle_mm_fault()>handle_pte_fault()>do_no_page()>do_anonymous_page()]
  2. 1058 /*
  3. 1059 * This only needs the MM semaphore
  4. 1060 */
  5. 1061 static int do_anonymous_page(struct mm_struct * mm, struct vm_area_struct * vma, pte_t *page_table,
  6. int write_access, unsigned long addr)
  7. 1062 {
  8. 1063 struct page *page = NULL;
  9. //如果引起页面异常是一次读操作,那么由mk_pte构建的映射表项要通过pte_wrprotect修正,只读属性
  10. //同时对于只读的页面,一律映射ZERO_PAGE同一个物理内存页面,也即是内容全部为0,只有可写才独立分配内存
  11. 1064 pte_t entry = pte_wrprotect(mk_pte(ZERO_PAGE(addr), vma->vm_page_prot));
  12. 1065 if (write_access) {
  13. 1066 page = alloc_page(GFP_HIGHUSER);//分配独立物理页面
  14. 1067 if (!page)
  15. 1068 return -1;
  16. 1069 clear_user_highpage(page, addr);
  17. //下面相同.只可写属性
  18. 1070 entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
  19. 1071 mm->rss++;
  20. 1072 flush_page_to_ram(page);
  21. 1073 }
  22. //虚拟页面到物理内存页面映射建立
  23. 1074 set_pte(page_table, entry);
  24. 1075 /* No need to invalidate - it was non-present before */
  25. 1076 update_mmu_cache(vma, addr, entry);
  26. 1077 return 1; /* Minor fault */
  27. 1078 }








来自为知笔记(Wiz)


转载于:https://www.cnblogs.com/zengyiwen/p/a36f15f18826cb4ef269a23e561b6c16.html

相关文章:

系统性能测试方案

转载&#xff1a;http://www.cnblogs.com/yunman/articles/5482134.html 1引言 1.1编写目的 编写本方案的目的是用于指导XXXX系统的性能测试,主要从测试环境、测试工具、测试策略、测试具体执行方法、任务与进度表等事先计划和设计。 1.2适用范围 XXXX系统性能测试组 XXXX系统开…

python跨行字符串 变量_在Python中有没有在多行字符串中使用变量的方法?

所以我把这个作为邮件发送脚本的一部分&#xff1a;try:content ("""From: Fromname To: Toname MIME-Version: 1.0Content-type: text/htmlSubject: testThis is an e-mail message to be sent in HTML formatThis is HTML message.This is headline."&q…

Python中的pickle模块

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 Pickle模块的作用 Pickle模块用于将python对象序列化为字节流&#xff0c;可存储在文件或数据库中&#xff0c;也可同通过网络进行传输。使用反序列…

pytorch python区别_pytorch源码解析:Python层 pytorchmodule源码

尝试使用了pytorch&#xff0c;相比其他深度学习框架&#xff0c;pytorch显得简洁易懂。花时间读了部分源码&#xff0c;主要结合简单例子带着问题阅读&#xff0c;不涉及源码中C拓展库的实现。一个简单例子实现单层softmax二分类&#xff0c;输入特征维度为4&#xff0c;输出为…

在vue中使用babel-polyfill

在 Vue.js项目中使用Vuex&#xff0c;Vuex 依赖 Promise&#xff0c;所以如果你的浏览器没有实现 Promise (比如 IE)&#xff0c;那么就需要使用一个 polyfill 的库 我们可以通过babel-profill转译 1、安装 npm install --save-dev babel-polyfill 2、在main.js中引入 import b…

CoinMarketCap计划于11月发布新的流动性排名系统

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 去中心化金融&#xff08;DeFi&#xff09;引领未来金融发展趋势&#xff0c;InvestDigital联合传统金融机构&#xff0c;依托现有数字货币金融业务…

cookie和session的代码实现

cookie和session的代码实现 1、设置cookie 今天笔试题考的是cookie的设置&#xff0c;我竟然选了request也可以设置cookie&#xff0c;我的天呀。 我们来看如何在response设置吧 public void service(HttpServletRequest req,HttpServletResponse resp) throws ServletExceptio…

idea 批量修改同一列_学会这个,1秒就可以批量处理文件

【问题1】根据公司名称&#xff0c;批量创建文件夹拿到老板给到的这个任务后&#xff0c;没关系我很有耐心&#xff0c;不就是右击新建文件夹重命名保存吗&#xff0c;然后加班点鼠标到天荒地老&#xff0c;终于完成了。结果老板说有些公司名有误要改正过来&#xff0c;还有几百…

动态规划和分治法的区别

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 动态规划也是一种分治思想&#xff08;比如其状态转移方程就是一种分治&#xff09;&#xff0c;但与分治算法不同的是&#xff0c;分治算法是把原问…

关于链式前向星。

一些代码 理解 #include<bits/stdc.h> using namespace std; //优先队列优化的链式前向星 const int maxn1000; const int INF0x3fffffff; struct Edge{int from, to, dist;Edge(int u, int v, int d):from(u),to(v),dist(d){} }; struct HeapNode{int u, d;HeapNode(int…

Ceph分层存储分析

最近弄Ceph集群考虑要不要加入分层存储 因此花了点时间研究了下 1&#xff0c;首先肯定要弄清Ceph分层存储的结构 &#xff0c;结构图大概就是下图所示 缓存层(A cache tier)为Ceph客户端提供更好的I/O性能&#xff0c;而数据存储在存储层(a backing storage tier)。用相对快速…

jemeter多场景混合案例_Redis 混合存储最佳实践指南

Redis 混合存储实例是阿里云自主研发的兼容Redis协议和特性的云数据库产品&#xff0c;混合存储实例突破 Redis 数据必须全部存储到内存的限制&#xff0c;使用磁盘存储全量数据&#xff0c;并将热数据缓存到内存&#xff0c;实现访问性能与存储成本的完美平衡。架构及特性命令…

交易所频频被盗,你该如何保护自己的数字资产?

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 5月8日凌晨&#xff0c;数字货币交易所币安发生被盗事件&#xff0c;黑客从币安热钱包盗走大约 7000 个比特币。币安官方公告称&#xff0c;这是一次…

gitlab搭建

一、安装源和依赖包 #增epel源,如果你是i686系统&#xff0c;请把x86_64修改下。cd /usr/local/src wget -O /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6 https://www.fedoraproject.org/static/0608B895.txt rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6 rpm -Uvh http://dl.f…

kafka源码分析(二)Metadata的数据结构与读取、更新策略

一、基本思路 异步发送的基本思路就是&#xff1a;send的时候&#xff0c;KafkaProducer把消息放到本地的消息队列RecordAccumulator&#xff0c;然后一个后台线程Sender不断循环&#xff0c;把消息发给Kafka集群。 要实现这个&#xff0c;还得有一个前提条件&#xff1a;就是K…

python实现简单的http服务器_Python实现简单HTTP服务器(二)

#coding:utf-8importsocketimportreimportsysfrom multiprocessing importProcessclassHTTPServer(object):def __init__(self, application):"""application&#xff1a;指的是框架的app"""self.server_socketsocket.socket(socket.AF_INET, so…

机器学习中的模型评价、模型选择及算法选择

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 正确使用模型评估、模型选择和算法选择技术无论是对机器学习学术研究还是工业场景应用都至关重要。本文将对这三个任务的相关技术进行回顾&#xff…

Apache 流框架 Flink,Spark Streaming,Storm对比分析(一)

https://bigdata.163.com/product/article/5 Apache 流框架 Flink&#xff0c;Spark Streaming&#xff0c;Storm对比分析&#xff08;一&#xff09;转载于:https://www.cnblogs.com/WCFGROUP/p/9075745.html

梯度下降算法_神经网络梯度下降算法

神经网络梯度下降算法2018, SEPT 13梯度下降&#xff08;Gradient Descent) 是神经网络比较重要的部分&#xff0c;因为我们通常利用梯度来利用Cost function&#xff08;成本函数&#xff09; 进行backpropagation&#xff08;反向传播&#xff09; 不断地iteration&#xff0…

微擎删除分类无法删除解决-select in效率低解决办法

今天朋友微擎后台微网站里的分类要删除&#xff0c;可是怎么删除也不能删除&#xff0c;同样的系统另一套却可以迅速删除。 后来查询到是查询语句的问题&#xff0c;朋友的平台用户量太大&#xff0c;数据太大&#xff0c;用了以下语句&#xff0c;造成效率太低&#xff1a; SE…

EOS技术及生态系统介绍

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 嘉宾介绍 哈胜&#xff0c;现任梦起文化传播有限公司技术总监&#xff0c;西北地区区块链技术发起第一人&#xff1b;一直在致力于将区块链技术推广…

svn 提交信息模板

版本&#xff1a;1.0作者&#xff1a;张三描述&#xff1a;修改了xxx转载于:https://www.cnblogs.com/ithfm/p/9075748.html

pta函数统计素数并求和_黎曼的zeta函数

9月24日阿提亚爵士&#xff08;Sir Atiyah&#xff09;直播“证明”黎曼猜想&#xff08;Riemann hypothesis&#xff09;在普通人中引发了一轮数学热潮&#xff0c;网络上一时间涌现了很多数学八卦文章。许多人在论及该命题重要性时都指出&#xff0c;ζ函数的非平凡零点与素数…

EasyRTMP手机直播推送rtmp流flash无法正常播放问题

本文转自EasyDarwin团队Kim的博客&#xff1a;http://blog.csdn.net/jinlong0603/article/details/52960750 问题简介 EasyRTMP是EasyDarwin团队开发的一套简单易用的RTMP推送SDK。本文想讲述下开发过程中遇到的一个问题。问题的现象是使用EasyRTMP推送音视频流到自己搭建的ngi…

对称加密和非对称加密

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 对称加密 对称密钥是双方使用相同的密钥 。 对称加密的要求 &#xff08;1&#xff09;需要强大的加密算法。算法至少应该满足&#xff1a;即使…

防火墙iptables介绍

防火墙&#xff1a; netfilter/iptables是集成在Linux2.4.X版本内核中的包过滤防火墙系统。该架构可以实现数据包过滤&#xff0c;网络地址转换以及数据包管理功能。linux中防火墙分为两部分&#xff1a;netfilter和iptables。netfilter位于内核空间&#xff0c;目前是Linux内核…

企业局域网的组建

写在前面的话 随着计算机技术发展啊&#xff0c;办公无纸化、网络化已经成为一种趋势。 企业局域网的概述 企业中可能有多台计算机&#xff0c;同时还可能有其他的硬件设备&#xff0c;比如打印机、扫描仪和数码相机等。通过组建小型网络&#xff0c;可以共享企业内部各种软、硬…

python3 线程池源码解析_5分钟看懂系列:Python 线程池原理及实现

概述传统多线程方案会使用“即时创建&#xff0c; 即时销毁”的策略。尽管与创建进程相比&#xff0c;创建线程的时间已经大大的缩短&#xff0c;但是如果提交给线程的任务是执行时间较短&#xff0c;而且执行次数极其频繁&#xff0c;那么服务器将处于不停的创建线程&#xff…

区块链+能源,能擦出什么样的火花?

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 区块链从闯入能源行业的那一天起&#xff0c;就引起了行业内外人群的高度关注&#xff0c;关于能源区块链的争论与质疑不断搅动人们的神经。区块链能…

JS学习梳理(三)类型和语法

类型 JavaScript 有七种内置类型&#xff1a;null、undefined、boolean、number、string、object 和symbol&#xff0c;可以使用typeof 运算符来查看typeof返回的都是字符串很多开发人员将undefined 和undeclared 混为一谈&#xff0c; 但在JavaScript 中它们是两码事。undefin…