复习总结
Y~哈哈哈
这个作者很懒,什么都没留下…
展开
-
Linux中线程安全问题
一、线程安全的介绍 在目前的计算机科学中,线程是操作系统调度的最小单元,进程是资源分配的最小单元。在大多数操作系统中,一个进程可以同时派生出多个线程。这些线程独立执行,共享进程的资源。在单处理器系统中,多线程通过分时复用技术,处理器在不同的线程间切换,从而更高效地利用系统 CPU资源。在多处理器和多核系统中,线程实际上可以同时运行,也就是每个处理器可以运行一个线程,系统的运算能力相对于...原创 2019-05-17 21:53:58 · 783 阅读 · 0 评论 -
Linux下共享内存的应用场景以及三种共享内存的方式
一、应用场景1、进程间通讯——生产者消费者模式 一个现场负责产生数据,一个现场负责处理数据,那么我们可以用主线程作为生产者,从键盘获取数据写入共享缓冲区,另一个线程作为消费者,从共享缓冲区读取数据,并打印。当然,这里要解决互斥的问题2、父子进程间通讯 由fork()产生的子进程和父进程不共享内存区,所以父子进程间的通讯也可以共享内存,以POSAX共享内存为例:父进程启动后使用...原创 2019-05-11 09:17:17 · 3678 阅读 · 0 评论 -
fread/write和 fwrite/write的区别
1、fread是带缓冲区的,read不带缓冲区2、fwrite属于库函数,write属于系统掉头3、fread可以读一个机构,read在Linux/unix中读二进制与普通文件没有区别4、fopen不能指定要创建文件的权限,open可以指定权限5、fopen返回指针,open返回文件描述符(整数)举例:如果文件的大小是8k,你如果用read/write,且只分配了2K的缓存,则...原创 2019-05-10 19:39:57 · 5273 阅读 · 0 评论 -
二叉树的性质
1、在二叉树的第i层上至多有2^(i-1)个节点(i >= 1)2、深度为k的二叉树之多有2^k -1个节点(i >= 1)3、对任意一颗二叉树T,如果其终端节点数为 a,度为2的节点数为 b,则 a=b+14、具有n个结点的完全二叉树的深度为lgn +15、如果对一棵有n个结点的完全二叉树...原创 2019-05-10 18:14:19 · 165 阅读 · 0 评论 -
有关多线程中fork()的问题
问题1:如果一个多线程程序的某个线程调用了fork函数,那么新创建的子进程是否将自动创建和父进程相同数量的线程呢?答案:否。子进程只拥有一个执行线程,它是调用fork的那个线程的完整复制。并且子进程将自动继承父进程中互斥锁(条件变量与之类似)的状态。也就是说,父进程中已经被加锁的互斥锁在子进程中也是被锁住的问题二:子进程可能不清楚从父进程继承而来的互斥锁的具体状态(是加锁还是解...原创 2019-05-10 16:56:19 · 2387 阅读 · 0 评论 -
线程和信号
1、进程中的所有线程共享该进程的信号,所以线程库将根据线程掩码决定把信号发送给那个具体的线程。因此,如果我们在每个子线程中都单都设置信号掩码,就很容易导致逻辑错误。此外,所有线程共享信号处理函数。也就是说,当我们在一个线程中设置了某个信号的信号处理函数后,它将覆盖其他线程为同一个信号设置的处理函数。这两点都说明,我们应该定义一个专门的线程来处理所有的信号2、如果父进程希望和子进程共享地址空间,...原创 2019-05-10 16:52:21 · 543 阅读 · 0 评论 -
原子操作以及加锁机制
一、原子操作不可被中断的一个或一系列操作。二、处理器如何实现原子操作 32位处理器使用基于对缓存加锁或总线加锁的方式来实现多处理器之间的原子操作(1)总线锁:使用处理器提供一个LOCK#信号,当一个处理器在总线上输出此信号的时候,其他处理器的请求将被阻塞,那么该处理器可以独占使用共享内存。举例:i=7,i++;两个线程对i++进行操作,那我们最终期望的结果是9,但最终的结果...原创 2019-05-10 16:49:56 · 2915 阅读 · 0 评论 -
信号量以及信号量和自旋锁的区别
Linux中的信号量是一种睡眠锁。如果有一个任务试图获得一个不可用(已经被占用)的信号量时,信号量会将其推进一个等待队列,然后让其睡眠。这时处理器能重获自由,从而去执行其他代码。当持有的信号量可用(被释放)后,处于等待队列中的那个任务将被唤醒,并获得该信号量信号量和自旋锁的区别:(1)信号量不会禁止内核抢占,持有信号量的代码可以抢占,而自旋锁不可以。这意味着信号量不会对调度的等待时...原创 2019-05-10 16:48:12 · 2856 阅读 · 0 评论 -
自旋锁
自旋锁最多只能被一个可执行线程持有。如果一个执行线程试图获得一个被已经持有(即争用)的自旋锁,那么该线程就会一直进行忙循环—旋转—等待锁重新可用。要是锁未被争用,请求锁的指向线程便能立刻得到它,继续执行。在任意时间,自旋锁都可以防止多于一个的执行线程同时进入临界区。同一个锁可以用在多个位置,例如,对于给定数据的所有访问都可以得到保护和同步举例:门和锁:自旋锁相当于是钥匙,如果你到门口,...原创 2019-05-10 16:47:22 · 210 阅读 · 0 评论 -
如何实现一个不可以被继承的类
由于派生类对象的构造,要先构造基类部分,而且派生类可以继承基类的private成员,但是却不能访问,因此可以把基类的构造函数实现成private私有的构造函数,那么任何一个派生类在继承这个基类的时候,都会由于无法调用基类的私有构造函数,而导致这个基类不能被任何派生类继承...原创 2019-05-15 17:55:53 · 283 阅读 · 0 评论 -
如何实现一个类定义的对象不能进行拷贝构造和赋值呢
可以实现一个基类,把这个基类的拷贝构造和operator=赋值函数私有化,那么任何这个基类继承的派生类,都不能拷贝和operator=了还有一种办法:把这个类的拷贝构造和operator=赋值函数私有化,这样做完全可以,但是对于每一个类的进行更改,代码修改量比较大,所以还是建议使用上面的方法...原创 2019-05-15 18:01:31 · 451 阅读 · 0 评论 -
set的底层实现实现为什么不用哈希表而使用红黑树
1、set中元素是经过排序的,红黑树也是有序的,哈希是无序的2、如果只是单纯的查找元素的话,那么肯定要选哈希表了,因为哈希表在的最好查找时间复杂度为O(1),并且如果用到set中那么查找时间复杂度的一直是O(1),因为set中是不允许有元素重复的。而红黑树的查找时间复杂度为O(lgn)...原创 2019-05-15 18:15:01 · 2572 阅读 · 0 评论 -
同步/异步在不同的模型中含义不相同以及阻塞、非阻塞
一、I/O模型中的同步/异步1、在I/O模型中,同步I/O是说I/O的读写操作,是在I/O事件发生之后,由应用程序来完成的。对于异步I/O来说,它可以直接对I/O执行读写操作,这些操作告诉用户内核缓冲区的位置,以及I/O操作完成之后内核通知应用程序的方式2、异步I/O总是立即返回的,因为真正的读写操作已经由内核接管。同步I/O的读写操作由应用程序自己完成。换言之,同步I/O内核通知的是就...原创 2019-05-11 18:07:37 · 218 阅读 · 0 评论 -
大端小端问题总结及相关面试题
参考https://blog.csdn.net/lishitao_578/article/details/72956312原创 2019-05-11 12:35:09 · 597 阅读 · 0 评论 -
delete和delete[]的区别以及什么时候用new[]申请可以用delete来释放
一、什么时候用new[]申请,可以用delete释放 1、在C++中,把单个元素的内存开辟释放和数组的内存开辟释放是分开的。因为在C++里面,开辟内存和构造对象是一起发生的,析构对象和释放内存是一起发生的int *a = new int; //delete a 或 delete[] 都可以int *p = new int[]; //delete p 或 delete p[] 都可以...原创 2019-05-11 10:58:10 · 2008 阅读 · 0 评论 -
new和 malloc区别以及delete和free的区别
一、new和malloc的区别其实new的底层也是使用malloc来实现的,只不过在类类型中比malloc多了一个调用构造函数来初始化的功能1、返回值new开辟内存需要指定类型,返回指定类型的指针,因此不需要进行强转 malloc的返回值是一个指针,指向一段可用内存的起始地址。因此malloc的返回值需要强转成指定类型的地址2、内存开辟与初始化malloc只负责开辟内存,内有初...原创 2019-05-11 10:18:18 · 1034 阅读 · 0 评论 -
Linux环境下段错误产生原因及调试方法
一、段错误是什么? 段错误指访问的内存超出了系统给这个程序设定的内存空间,例如访问了不存在的内存地址,访问了系统保护的内存地址,访问了只读的内存地址等二、一一举例说明访问不存在的内存地址#include<stdio.h>void mian(){ int *ptr = NULL; *ptr = 0;}访问系统受保护的内存地址#inclu...原创 2019-05-11 09:19:06 · 242 阅读 · 0 评论 -
把一个数组中的0全部移到数组的最后边或者数组的最前边
把所有为0的数移到数组的最后边思想:从前往后遍历一遍数组,将数组中的零全部用一个整型变量 ZeroNum记录下来,当碰到一个非零的数据,就让这个数向前移动ZeroNum个单位,即arr[i-ZeroNum] = arr[i]; 把数组遍历完成之后,为0个个数就全部统计出来了,那么就将数组的后ZeroNum个位置全都改为0即可代码如下:时间复杂度:O(n),空间复杂度:O(1)voi...原创 2019-05-15 21:13:55 · 3254 阅读 · 0 评论 -
int *const p和const int *p区别
const int *p;上面这条语句中,const修饰的是p指向的内存的值不能被修改,但是p本身是可以修改的int *const p;上面这条语句中,const修饰的是p本身是常量,不能被修改,但是p指向的内存是可以被修改的下面给出几种错误的类型转换const int *p ==> int *q;int **p ==> const int **q;con...原创 2019-05-15 20:04:48 · 509 阅读 · 0 评论 -
C++this指针干什么用的
class Test{public: void func(){ cout<<"mvalue:"<<mvalue<<endl; }private: int mvalue;};int main(){ Test t1,t2; t1.func(); t2.func(); return...原创 2019-05-15 19:57:17 · 1141 阅读 · 0 评论 -
malloc、kmalloc、vmalloc函数的区别
malloc()返回的页在进程的虚拟地址空间内是连续的,但在物理地址空间内不一定连续kmalloc()确保分配的内存区域在物理空间上是连续的(自然在虚拟地址空间上也是连续的)vmalloc()只确保分配的页(内存区域)在虚拟地址空间内是连续的。它通过分配非连续的物理内存块,再“修正”页表,把内存映射到逻辑地址空间连续的区域中...原创 2019-05-10 16:40:27 · 561 阅读 · 0 评论 -
系统调用号
在Linux中,每个系统调用被赋予一个系统调用号。这样,通过独一无二的号就可以关联系统调用。当用户空间的进程执行一个系统调用的时候,这个系统调用号就用来指明到底是要执行哪个系统调用;进程不会提及系统调用的名称。 系统调用号相当重要,一旦分配就不能再又任何变更,否则编译好的应用程序就会崩溃。此外,如果一个系统调用被删除,它所占用的系统调用号也不允许被回收利用,否则,以前编译过的代码...原创 2019-05-07 21:51:28 · 2278 阅读 · 0 评论 -
僵尸进程概念以及处理方式
一、僵死进程的概念子进程先于父进程结束,而父进程又没有调用wait或者waitpid获取其退出信息。子进程还需要在其PCB中保存其退出的相关信息,所以,子进程的执行主体已经结束,但是操作系统并没有释放该进程PCB结构,以满足父进程后续对该子进程退出信息的查询(如果父进程还在运行)。在子进程结束运行之后,父进程读取其退出状态之前,我们称该子进程为僵尸进程二、处理方式...原创 2019-04-27 16:31:59 · 772 阅读 · 0 评论 -
fork系统调用
一、进程的创建过程(fork底层调用) fork是复制进程,那么首先就要搞清楚进程是什么?进程是一个正在运行的程序,是系统分配资源的基本单位。系统管理进程是通过对进程控制块(PCB)的管理完成的。每个进程的产生分两步,第一步:分配PCB,第二步:准备进程实体,如分配内存空间等。目前fork底层是通过do_fork方法传入的不同参数来实现的。首先为进程分配一个唯一标识符pid,这一步失败就会退...原创 2019-04-27 16:26:29 · 496 阅读 · 0 评论 -
两种高效的并发模式——半同步/半异步、领导者/追随者模式
一、并发模式中的同步和异步的区别1、同步:程序完全按照代码顺序执行(简单理解就是,我调用一个功能该功能没有结束前,我就一直死等结果)2、异步:程序的执行需要由系统事件来驱动,常见的系统事件包括中断、信号等(简单理解为:调用一个功能,不需要指代该功能最后执行的结果,该功能有结果后再通知我就行(回调通知)。也可以理解为:数据拷贝的时候,进程是否阻塞来作为同步和异步的区别)。常见的系统事件包括中...原创 2019-04-26 15:45:30 · 393 阅读 · 0 评论 -
池——线程池、进程池、内存池、连接池
为什么要使用线程池和进程池?(1)动态创建子进程(子线程)是比较耗时的,这将导致较慢的客户响应(2)动态创建的子进程(或子线程)通常只用来为一个客户服务(除非做特殊处理),这将导致系统上产生大量的细微进程(或线程)。进程(或线程)间的切换将消耗大量的CPU(3)动态创建的子进程是当前进程的完整映像当前进程必须谨慎地管理其分配的文件描述符和堆内存等系统资源,否则子进程可能复制这些资源,...原创 2019-04-26 15:35:48 · 587 阅读 · 0 评论 -
gbd调试多线程和多进程
一、gdb调试多进程1、如果一个进程通过fork系统调用创建了子进程,gdb会继续调试原来的进程,子进程则正常运行。调试子进程的方法有两种(1)单独调试子进程(因为子进程从本质上来说也是一个进程,所以可以通过gdb进行调试)利用ps –ef | grep 文件名,得出子进程的PID(假设为5876) gdb (gdb) attach 5876 /*将子进程5876附加到gdb...原创 2019-04-24 08:15:11 · 299 阅读 · 0 评论 -
面试题——TCP网络编程总结
1、TCP网络编程中三次握手、四次挥手的状态有几种 在三次握手中客户端是主动打开,服务器端是被动打开,客户端的状态有6种(TIME_WAIT 2MSL之后变成CLOSED状态),服务器端状态5种(1)三次握手:刚开始客户端和服务器端都属于关闭状态即closed,接着客户端主动打开,给服务器端发送请求报文后客户端变成STN-SENT(同步已发送)状态,服务器被动打开,接收到请求报文并给客...原创 2019-04-21 16:45:04 · 648 阅读 · 0 评论 -
面试题——三种体系结构——OSI、TCP/IP、五层协议体系结构
1、体系结构为什么分层?几种体系结构分别有几层,每一层的实现?(要超详细)分层可以带来的好处:(1)各层之间是独立的(2)灵活性好:当任何一层发生变化时(例如由于技术的变化),只要层间接口关系保持不变,则在这层以上或以下各层均不受影响。此外对某一层提供的服务还可以进行修改,当某层提供的服务不再需要时,甚至可以将这层取消(3)结构上可分割开(4)易于实现和维护(5)能促进标准化工作。分层带来...原创 2019-04-21 16:32:08 · 1936 阅读 · 0 评论 -
哈希涉及到的面试题
问题实例(海量数据处理)hash 表在海量数据处理中有着广泛的应用,我们来看一道百度面试题:题目一:海量日志数据,提取出某日访问百度次数最多的那个IP。方案:IP的数目还是有限的,最多2^32个,所以可以考虑使用hash将ip直接存入内存,然后进行统计。方法介绍对于海量数据而言,由于无法一次性装进内存处理,导致我们不得不把海量的数据通过hash映射分割成相应的小块数据,...原创 2019-04-17 15:24:15 · 677 阅读 · 0 评论 -
I/O复用、select、poll、epoll的区别以及epoll的内核实现
一、select系统调用(1)select系统调用的用途是:在一段指定的时间内,监听用户感兴趣的文件描述符上的可读、可写和异常事件。(2)select的实现select的参数类型fd_set没有将文件描述符和事件绑定,它仅仅是一个文件描述符集合,因此select需要提供3个这种类型的参数来分别传入和输出可读、可写及异常等事件。这一方面使得select不能处理更多类型事件,另一方面由于内...原创 2019-04-27 16:36:14 · 185 阅读 · 0 评论 -
进程间通信
一、Linux下进程间通信方式有哪些方式?(IPC表示进程间通信)信号、管道(有名、无名)、信号量、消息队列、共享内存、socket1、信号(1)信号是系统预先定义好的一些特定的事件,信号可以被产生,也可以被接收,产生和接收的主题都是进程。接收到信号的进程会采取相应的一些行动。一般信号是由于某些错误条件而产生的,比如内存段冲突、浮点处理器错误或非法指令等。信号也可以作为进程间传递消息...原创 2019-04-27 16:38:40 · 233 阅读 · 0 评论 -
slab分配器
slab分配器扮演了通用数据结构缓存层的角色slab层的设计有如下几个基本原则(1)频繁使用的数据结构也会频繁分配和释放,因此应当缓存他们(2)频繁分配和回收必然导致内存碎片(难以找到大块连续的可用内存)。为了避免这种现象,空闲链表的缓存会连续地存放,因为已释放的数据结构又会放回空闲链表(3)回收的对象可以立即投入下一次分配,因此,对于频繁的分配和释放,空闲链表能够提高其性能(...原创 2019-05-10 14:20:57 · 248 阅读 · 0 评论 -
进程管理
一、进程1、程序本身并不是进程,进程是处于执行期的程序以及相关资源的总称。其资源包括:打开的文件、挂起的信号、内核内部数据、处理器状态、一个或多个具有内存映射的内存地址空间以及一个或多个执行线程、用来存放全局变量的数据段等。其实进程就是正在执行的程序代码的实时结果2、进程的存活起始时间以及fork相关 进程在创建它的时刻开始存活 在Linux中同城是调用fork()系统的结果,...原创 2019-05-07 18:43:51 · 272 阅读 · 0 评论 -
IP协议详解
一、IP服务的特点IP协议是TCP/IP协议族的动力,它为上层协议提供了无状态、无连接、不可靠的服务1、无状态是指IP通信双方不同步传输数据的状态信息,因此所有IP数据报的发送、传输和接收都是相互独立、没有上下文关系的。该服务最大的缺点:无法处理乱序和重复的IP数据报。比如发送端发送出的第N个IP数据报可能比第N+1个IP数据报后到达接收端,而同一个IP数据报也可能经过不同的...原创 2019-05-01 12:37:42 · 440 阅读 · 0 评论 -
中断和处理
一、中断中断本质上是一种特殊的电信号,由硬件设备发向处理器。处理器接受到中断后,会马上向操作系统反映此信号的到来,然后就由操作系统负责处理这些新到来的数据。硬件设备生成中断的时候并不考虑与处理器的时钟同步,换句话说就是中断随时可以产生。因此,内核随时可能因为新到来的中断而被打断不同的设备对应的中断不同,而每个中断都通过一个唯一的数字标志。二、中断处理程序在响应一个特定中断的时...原创 2019-05-08 21:41:21 · 651 阅读 · 0 评论 -
系统调用二
关于系统调用地举例:https://blog.csdn.net/YL970302/article/details/85677588一、与内核通信系统调用在用户空间进程和硬件设备之间添加了一个中间层,该层主要作用有三个:(1)它为用户空间提供了一种硬件的抽象接口。举例来说,当需要读写文件的时候,应用程序就可以不去管磁盘类型和介质,甚至不用去管文件所在的文件系统到底是哪种类型(2)系统...原创 2019-05-08 21:40:37 · 208 阅读 · 0 评论 -
高级I/O函数——pipe、dup、dup2、sendfile、mmap、munmap、splice、fcntl
一、创建文件描述符的函数1、pipe函数(创建管道)(1)pipe函数的定义:#include<unistd.h>int pipe(int fd[2]); 通过pipe函数创建的这两个文件描述符fd[0],fd[1]分别构成管道的两端,并且fd[1]只能用于往管道中写数据,fd[0]只能从管道中读取数据,不能反过来使用。默认情况下,这一对文...原创 2019-04-27 16:54:42 · 450 阅读 · 0 评论 -
两种高效的事件处理模式——Reactor和Proactor模式
I/O模型中的同步和异步的区别?区分是内核向应用程序通知的是何种I/O事件(就绪事件还是完成事件),以及由谁来完成I/O读写(应用程序还是内核)1、Reactor模式(同步I/O模型通常用于实现Reactor模式)它要求主线程(I/O处理单元,下同)只负责监听文件描述符上是否有事件发生,有的话就立刻将该事件通知工作线程。除此之外,主线程不做任何其他实质性的工作。读写数据,接受新...原创 2019-04-24 22:43:52 · 850 阅读 · 0 评论 -
I/O模型中同步和异步的区别
1、同步:程序完全按照代码顺序执行(简单理解就是,我调用一个功能该功能没有结束前,我就一直死等结果)2、异步:程序的执行需要由系统事件来驱动,常见的系统事件包括中断、信号等(简单理解为:调用一个功能,不需要指代该功能最后执行的结果,该功能有结果后再通知我就行(回调通知)。也可以理解为:数据拷贝的时候,进程是否阻塞来作为同步和异步的区别)。...原创 2019-04-24 22:40:01 · 524 阅读 · 0 评论