daily reading

2024-03-23 04:32
文章标签 daily reading

本文主要是介绍daily reading,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

操作系统: 让CPU满载,设备驱动,内存管理,线程调度

内存直接存取,不足点:(地址空间不隔离,内存效率低--内存不够要经常换入换出, 程序运行地址不确定), 解决,用虚拟内存方式 ,CPU->虚拟地址->mmu->物理地址 ,(段页式内存模型)

线程: 程序执行流最小单元,cpu调度的最小单元.  运行-》就绪-》等待 (调度算法,轮转法为基础,加上优先级调度)

线程私有:线程局部存储(容量有限,__thread xxxx  在tls段,复制多个副本到堆里面保证独立),寄存器,栈(栈可以被同进程其他线程访问,但逻辑意义上讲是私有的)

fork:写时复制,仅要修改的时候复制一份给修改方。

mutex-binary semaphore: mutex 仅单个线程获取和释放 ,semaphor 时系统级别,可以一个线程获取,另一个线程释放。

原子操作:单指令的操作.


程序编译预处理:删除所有#define #if #eif ,删除所有注释,展开宏,展开包含头文件,添加行号,保留#pragma  gcc -E  

编译: 词法分析(产生tokern),语法分析(生产语法树),语义分析(程序语言的语法检查),生产汇编代码文件

汇编:产生机器码,生成ELF文件。(file命令可以查看格式)如:file a.o 
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped

链接: 链接机器码,负责地址和空间分配,符号决议,和重定位(重新计算目标操作地址的过程)。

链接过程的接口是依赖于各个源文件的符号,仅关心全局符号,将各个文件依赖的全局符号相互粘连。过程依赖 重定位表。

c符号 全局函数或者变量 _xxx  c++ _命名空间类名变量名 如:_ZN1C4funEi  c++filter 命令可以逆查看

函数和初始化的全局变量为强符号,未初始化的全局变量为弱符号。 1,强符号不能多次定义,否则ld报错, 2,强弱符号共存,用强符号,3,多个文件中有相同弱符号,选择空间最大那个。

函数级别链接: gcc -ffunction-sections -fdata-sections 链接某些库中的某些函数(链接过程消耗大)

链接过程:1,空间分配,扫描所有目标文件,收集所有段信息,合并相同的段,计算合并后的长度和位置信息,分配虚拟地址空间。2,。符号解析与重定位,利用收集到的信息,读取数据段和重定位信息,进行符号解析与重定位,调整代码中的地址。


编译后的ELF没有运行时主要由代码段(.text)和数据段(.data)组成rodata只读,bss段(.bss)  objdump -h xx.o 可以查看

ELF运行时主要由代码段(.text)和数据段(.data)组成,bss段(.bss) ,堆,栈,共享库(0x400000新0xbfxxxxx, .interp .dynamic ldd命令查看动态库依赖)等

 
图8-1  ELF文件结构
ELF头:包含文件版本,目标机器型号,程序入口地址, 段表信息等。 readelf -h xx.o 可以查看文件头

ELF linux运行时进程空间布局:

0xffffffff kernelspace#stack# (unused space) #dynamic libraries# (unused space)#heap#read/wirte sections(.data.bss)#readonly sections(.init.rodata.text) reserved 0x00000


在采用段式内存管理的架构中(比如intel的80x86系统),一个程序本质上都是由 bss段、data段、text段三个组成的

BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。

一般在初始化时bss 段部分将会清零(bss段属于静态内存分配,即程序一开始就将其清零了) BSS段属于静态内存分配。

数据段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。

代码段:代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)

栈(stack):栈又称堆栈, 是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

比如,在C语言程序编译完成之后,已初始化的全局变量保存在.data 段中,未初始化的全局变量保存在.bss 段中。   
l          text和data段都在可执行文件中(在嵌入式系统里一般是固化在镜像文件中),由系统从可执行文件中加载;
l          而bss段不在可执行文件中,由系统初始化。
编译两个小程序如下:
程序1:
int ar[30000];
void main()
{
......
}
程序2:
int ar[300000] =  {1, 2, 3, 4, 5, 6 };
void main()
{
......
}
发现程序2编译之后所得的.exe文件比程序1的要大得多。 为什么?
区别很明显,一个位于.bss段,而另一个位于.data段,两者的区别在于:
l          全局的未初始化变量存在于.bss段中,具体体现为一个占位符;全局的已初始化变量存于.data段中;
l          而函数内的自动变量都在栈上分配空间。
l          .bss是不占用.exe文件空间的,其内容由操作系统初始化(清零);
l          而.data却需要占用,其内容由程序初始化,因此造成了上述情况。
注意:
l          bss段(未手动初始化的数据)并不给该段的数据分配空间,只是记录数据所需空间的大小。
l          data(已手动初始化的数据)段则为数据分配空间,数据保存在目标文件中。
l          DATA段包含经过初始化的全局变量以及它们的值。
l          BSS段的大小从可执行文件中得到,然后链接器得到这个大小的内存块,紧跟在数据段后面。当这个内存区进入程序的地址空间后全部清零。包含DATA和BSS段的整个区段此时通常称为数据区。

一些典型ELF段的名和内容解释如下表所示:

名称

内容

.text

机器指令, 常值数据和常值串.

.data

初始化数据.

.sdata

小初始化数据.

.bss

未初始化变量.

.sbss

小未初始化变量.

.comment

Comments from #ident directives in C.

.init

Main()函数之前执行的代码.

.fini

程序执行完成后执行的代码.

.eini

.fini代码的最后指令;.init,.fini和eini section应以序放入内存.

.debug

DWARF格式的符号调试信息.

.line

符号调试的行号信息.

.relaname

Section name的重定位信息.

.shstrtab

Section名.

.strtab

串表for符号表中的符号.

.symtab

包含符号表.


分段目的为了管理,如代码段只读, 数据段可读写,全局放一起,静态放一起,未初始化的一起,初始化的一起。(多个程序副本运行,系统可以只加载一份代码副本,多个数据副本,节约了内存)

段页内存管理:用于内存寻址,页面,程序运行过程的存储管理,换入换出。

不同进程相同线性地址对应不同物理地址:系统有个页目录 每个进程对应一个页表  页表里面有个基地址, 每个页表的基地址不一样 
两个进程访问相同的虚拟地址的时候  最终会映射到每个进程的基地址加上一个页内偏移(因为两个虚拟地址一样,偏移一样,但是基地址不一样,所以最终到物理地址十不一样的)

函数栈的调用惯例: 1 参数传递顺序(大都从右到左) 2栈维护(函数调用方弹出栈,还是函数本身)3名字修饰(cdecl _函数名 stdcall _函数名+参数字节数) 

堆:程序向运行库申请(避免系统调用开销),运行库向系统申请 brk 和mmap  

brk:data段

mmap:匿名空间 向操作系统申请的一段虚拟地址,没有映射到文件的。一般页大小整数倍

堆分配算法: 空闲链表 --容易越界,回收不知道大小,坏了无法恢复  。  位图:  简单,容错好,碎片多。   

operator new  (函数,可重载,返回void* ,参数size) ,  new operator (算符)


进程载入: os创建进程,控制器到入口函数(通常是运行库的某个入口函数),初始化运行库和环境(堆,IO,线程,全局变量构造(.init) ,调用main, main完后返回入口,进行资源清理--析构全局变量,清理堆,关闭IO等(.finl)

运行时库: 提供 1,入口函数和退出函数 2 Io封装 3标准函数库4堆 5 调试

IO缓冲: 行缓冲,全缓冲

linux 进入和退出系统调用:  

1. 执行int $0x80汇编指令 .  iret退出

2. 执行sysenter汇编指令.  2.6以后内核开始支持,   sysexit退出


信号有2个阶段 :

1,信号产生,内核修改目标进程的信号数据结构。

2,信号传递,内核强迫目标进程对信号做出反应,或改变目标进程的执行状态 或执行信号调用,或者2者都有。


共 享内存可以说是最有用的进程间通信方式,也是最快的IPC形式。采用共享内存通信的一个显而易 见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。(对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而 共享内存则只拷贝两次数据[1]:一次从输入文件到共享内存区,另一次从共享内存区到输出文件。)另一方面:进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时,再重新建立共享内存区域。而是保持共享区域,直到通信完毕为止,这样,数据内容一直保存在共享内存中,并没有写回文件。共享内存中的内容往往是在解除映射时才写回文件的。持续性

一、内核怎样保证各个进程寻址到同一个共享内存区域的内存页面

1、page cache及swap cache中页面的区分:一个被访问文件的物理页面都驻留在page cache或swap cache中,一个页面的所有信息由struct page来描述。struct page中有一个域为指针mapping ,它指向一个struct address_space类型结构。page cache或swap cache中的所有页面就是根据address_space结构以及一个偏移量来区分的。

2、文件与address_space结构的对应:一个具体的文件在打开后,内核会在内存中为之建立一个struct inode结构,其中的i_mapping域指向一个address_space结构。这样,一个文件就对应一个address_space结构,一个address_space与一个偏移量能够确定一个page cache 或swap cache中的一个页面。因此,当要寻址某个数据时,很容易根据给定的文件及数据在文件内的偏移量而找到相应的页面。

3、进程调用mmap()时,只是在进程空间内新增了一块相应大小的缓冲区,并设置了相应的访问标识,但并没有建立进程空间到物理页面的映射。因此,第一次访问该空间时,会引发一个缺页异常。

4、对于共享内存映射情况,缺页异常处理程序首先在swap cache中寻找目标页(符合address_space以及偏移量的物理页),如果找到,则直接返回地址;如果没有找到,则判断该页是否在交换区(swap area),如果在,则执行一个换入操作;如果上述两种情况都不满足,处理程序将分配新的物理页面,并把它插入到page cache中。进程最终将更新进程页表。
注:对于映射普通文件情况(非共享映射),缺页异常处理程序首先会在page cache中根据address_space以及数据偏移量寻找相应的页面。如果没有找到,则说明文件数据还没有读入内存,处理程序会从磁盘读入相应的页面,并返回相应地址,同时,进程页表也会更新。

5、所有进程在映射同一个共享内存区域时,情况都一样,在建立线性地址与物理地址之间的映射之后,不论进程各自的返回地址如何,实际访问的必然是同一个共享内存区域对应的物理页面。
注:一个共享内存区域可以看作是特殊文件系统shm中的一个文件,shm的安装点在交换区上。       


共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区。在/proc/sys/kernel/目录下,记录着共享内存的一些限制,如一个共享内存区的最大字节数shmmax,系统范围内最大共享内存区标识符数shmmni等,可以手工对其调整,但不推荐这样

做。shmat()将这个内存区映射到本进程的虚拟地址空间。(堆和栈中间,称为文件映射区域的地方),下面看出靠近栈

mmap

rea:0x7f5d876e5000  mmp
areast:0x7fffc6df32dc  stack
areahp:0x100c010  heap
next
area:0x7f5d876e3000  shmat
areast:0x7fffc6df3318  stack
areahp:0x100c030 heap

注意:在使用共享内存,结束程序退出后。如果你没在程序中用shmctl()删除共享内存的话,一定要在命令行下用ipcrm命令删除这块共享内存。你要是不管的话,它就一直在那儿放着了。创建共享内存时,shmflg参数至少需要 IPC_CREAT | 权限标识,如果只有IPC_CREAT 则申请的地址都是k=0xffffffff,不能使用;
获取已创建的共享内存时,shmflg不要用IPC_CREAT(只能用创建共享内存时的权限标识,如0640),否则在某些情况下,比如用ipcrm删除共享内存后,用该函数并用IPC_CREAT参数获取一次共享内存(当然,获取失败),则即使再次创建共享内存也不能成功,此时必须更改key来重建共享内存。
简单解释一下ipcs命令和ipcrm命令。

取得ipc信息:
ipcs [-m|-q|-s]
-m      输出有关共享内存(shared memory)的信息
-q      输出有关信息队列(message queue)的信息
-s      输出有关“遮断器”(semaphore)的信息
%ipcs -m

gogo@localhost Net]$ ipcs  -l   查看限制  cat /proc/sys/kernel/shmmax 32M


------ Shared Memory Limits --------
max number of segments = 4096
max seg size (kbytes) = 67108864
max total shared memory (kbytes) = 17179869184
min seg size (bytes) = 1


------ Semaphore Limits --------
max number of arrays = 128
max semaphores per array = 250
max semaphores system wide = 32000
max ops per semop call = 32
semaphore max value = 32767


------ Messages: Limits --------
max queues system wide = 3732
max size of message (bytes) = 65536
default max size of queue (bytes) = 65536

删除ipc
ipcrm -m|-q|-s shm_id
%ipcrm -m 105



MySQL数据库MyISAM和InnoDB存储引擎的比较

MySQL有多种存储引擎,MyISAM和InnoDB是其中常用的两种。这里介绍关于这两种引擎的一些基本概念(非深入介绍)。

MyISAM是MySQL的默认存储引擎,基于传统的ISAM类型,支持全文搜索,但不是事务安全的,而且不支持外键。每张MyISAM表存放在三个文件中:frm 文件存放表格定义;数据文件是MYD (MYData);索引文件是MYI (MYIndex)。

InnoDB是事务型引擎,支持回滚、崩溃恢复能力、多版本并发控制、ACID事务,支持行级锁定(InnoDB表的行锁不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,如like操作时的SQL语句),以及提供与Oracle类型一致的不加锁读取方式。InnoDB存储它的表和索引在一个表空间中,表空间可以包含数个文件。

主要区别:

  • MyISAM是非事务安全型的,而InnoDB是事务安全型的。
  • MyISAM锁的粒度是表级,而InnoDB支持行级锁定。
  • MyISAM支持全文类型索引,而InnoDB不支持全文索引。
  • MyISAM相对简单,所以在效率上要优于InnoDB,小型应用可以考虑使用MyISAM。
  • MyISAM表是保存成文件的形式,在跨平台的数据转移中使用MyISAM存储会省去不少的麻烦。
  • InnoDB表比MyISAM表更安全,可以在保证数据不会丢失的情况下,切换非事务表到事务表(alter table tablename type=innodb)。

应用场景:

  • MyISAM管理非事务表。它提供高速存储和检索,以及全文搜索能力。如果应用中需要执行大量的SELECT查询,那么MyISAM是更好的选择。
  • InnoDB用于事务处理应用程序,具有众多特性,包括ACID事务支持。如果应用中需要执行大量的INSERT或UPDATE操作,则应该使用InnoDB,这样可以提高多用户并发操作的性能。


这篇关于daily reading的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/837144

相关文章

[LeetCode] 739. Daily Temperatures

题:https://leetcode.com/problems/daily-temperatures/description/ 题目 Given a list of daily temperatures T, return a list such that, for each day in the input, tells you how many days you would have to

【HDU】4990 Reading comprehension 等比数列:两层快速幂

传送门:【HDU】4990 Reading comprehension 题目分析:首先根据题目意思可以很容易找到一个等比数列: 当n%2==1时,f(n) = 1 + 2^2 + 2^4 + ... + 2^(n-1) 当n%2==0时,f(n) = 2*f(n-1)。 接下来可以构造矩阵用矩阵快速幂求,也可以像我一样用两层快速幂求。(比赛的时候没想到用矩阵快速幂= =) 当n%2

SAT阅读练习题:Reading Comprehension Test 3

SAT阅读练习题:Reading Comprehension Test 3   10 minutes - 7 questions   The passage is taken from a biography of Florence Nightingale who is mainly remembered for her heroic work as a nurse during the

SAT阅读练习题:Reading Comprehension Test 2

SAT阅读:Reading Comprehension Test 2   10 minutes - 7 questions   The passage is taken from a description of the life of certain Pacific Islanders written by a pioneering sociologist.   By the time

Lost connection to MySQL server at 'reading initial communication packet', system error: 0

连接MySQL提示: ERROR 2013 (HY000): Lost connection to MySQL server at ‘reading initial communication packet’, system error: 0 这是由于库文件初始化连接MySQL时连接失败引起的。 导致此错误的原因有: 1.服务器为正常启动的; 2.mysql设置文件中“bind-address”

Rust: Reading and Writing Files

Reading and Writing Files We need some way to actually get data from the filesystem so we can process it, and write it back when we’re done 我们需要某种方法从文件系统中实际获取数据,以便处理它,并在完成后将其写回来 use std::fs; std::f

nginx 8051#0: *4 recv() failed (104: Connection reset by peer) while reading response header from u

环境    php7   nginx1.8.0    nginx   报错  500  GATWAY网关错误 2017/08/28 10:45:42 [error] 7975#0: *333 recv() failed (104: Connection reset by peer) while reading response header from upstream, clien

SLAM Paper Reading和代码解析

最近对VINS、LIO-SAM等重新进行了Paper Reading和代码解析。这两篇paper和代码大约在三年前就读过,如今重新读起来,仍觉得十分经典,对SLAM算法研发具有十分重要的借鉴和指导意义。重新来读,对其中的一些关键计算过程也获得了更新清晰的了解,现整理分享出来,供有需要的同学参考。 VINS-MONO算法总结-徐胜攀.pdf资源-CSDN文库 对VINS-MONO的算法框架进

configparser.DuplicateSectionError: While reading from '/home/qinghua/.theanorc' [line 18]: section

python代码: import theano 出现错误: configparser.DuplicateSectionError: While reading from '/home/qinghua/.theanorc' [line 18]: section 'nvcc' already exists 解决方法是, vim ~/.theeanorc 删除行: [nvcc]

Paper Reading: EfficientAD:毫秒级延迟的准确视觉异常检测

EfficientAD 简介方法高效的patch描述PDN教师pretraining 轻量级的师生模型逻辑异常检测异常图像的标准化 实验局限性 EfficientAD: Accurate Visual Anomaly Detection at Millisecond-Level Latencies EfficientAD:毫秒级延迟的准确视觉异常检测, WACV 2024 pa