进程与线程

进程与线程的区别在面试题中非常常见,然而大多数人一般都只是网上找资料,背背下来就完事了(就和我应对epoll面试题一样……)本文将从一些底层角度去剖析进程与线程——主要是从linux内核角度。 首先还是贴一下我对于这种面试题的一些常规回答: 1. 线程的划分尺度小于进程,简单说是一个程序至少有一个进程,一个进程至少有一个线程。 线程是cpu调度的 基本单位,进程和线程都能创建和撤销线程;同一个进程内的多个线程之间可以并发执行。 2. 进程拥有独立的地址空间和其他资源,而同一个进程中的线程共享(当然各自也会有一些用于运行必不可少的 资源)。这就意味着一个进程崩溃,在保护模式下,不会影响到其他进程,而一个线程崩溃,其同一进程内的 所有线程都会崩溃。因此,多进程比多线程更健壮,但一般来说多进程效率较差,因为线程切换代价较小。 3. 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出 口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控…

对一致性hash的一些理解

传统hash方法有个令人诟病的缺点,就是在容量不够需要扩容的时候,所有原先存储的值都需要重新进行hash映射。 而一致性hash的目标就是为了解决这个缺点而相出的hash算法,尽可能地让重新hash的原值数变少。 附带一个中文wiki 一致hash只是一种想法,真的算法实现各有名称。 根据我对网上所说的最简单的一致hash方法的理解。这里我也简单说一下。 假设我的hash容量有 cap ,而我们实际的hash范围会比这个更大,为的是将一块区域的数值划分给槽,(所谓槽,是我的个人习惯。因为hash在我看来像是被分配到一个槽或者桶里,这里简称被hash之后的所有数值为槽)。 而每当增加一个槽(扩容),最简单的方法就是将相邻的槽里的一部分 分给新的槽。而每当减少一个槽(缩容),最简单的方法就是将它存储的数字转交给相邻的槽。 无论是扩容还是缩容,这个最简单的操作都能够使得重新hash的数量尽可能少。 然而,这个最简单的方法当然是不靠谱的,因为它首先在负载上是根本谈不上均衡的。 一个可行的解决办法是。 将原先的cap个大区域,分成cap个 若干小区域的集合。 怎么说…

久违的更新

2018.8.2,距离我第一次来到百度已经2个月之久,(虽然中间有半个月的考试请假..) 在说实习感想之前,很想分享一下今日份的欣喜与忧愁交加的情绪.今天华姐(我们的经理)无意中在我边上问晨旭哥(带我的mentor) :"他已经能独立干活了么?" :"已经可以了,都已经迁移了一个垂类了" 开心! 这是毋庸置疑的,但是这份欣喜并没有持续太久,因为我也是知道自己有几斤几两的。。。老实说,那个迁移工作在我看来也是很整体的杂活。。要说收获的话,应该是对框架和流程的整体把握有了个清晰点的概念..毕竟这些代码我都是一边看一边改的,除此之外的话,就只剩一点 C++ 的技巧了,(但大多不是C++ 11 的。) 所以总的来说,就是觉得收获的知识非常少。。而且不仅如此,在真正独立解决需求上,也远远不足。比如说,前天给我一个小需求,dnn并行请求视频,给我的估计时间是一天,现在已经是第二天结束了。。 前天下午给的需求,一口承诺昨天可以完成,而昨天策略的朋友晚上还来催我,"今天可以完成么?",我没敢直接回答.而事实上今天回去之前还发现了个大问题,本来想今晚回来赶一下的,结果发现 vpn 连不…

debug工具Valgrind使用简介

腾讯teg挂了之后昨天又被其他部门捞起来了,面了20分钟左右,前面基本畅通无阻,但是问到如何检测内存泄漏的时候懵比了…………卒 介绍一个比较实用的工具 Valgrind,英文海星的朋友可以点这个 链接。一个新手教程。 Valgrind它在实质上还是一个debug工具集合,而其中最受欢迎就是 memcheck,用于检测内存泄漏。 其所有检测内容包括(个人总结 * 内存泄漏 * 使用未初始化的内存 * 内存越界 * 读写已经释放的内存 * 重复释放 内存泄漏 valgrind默认使用 memcheck参数来检查内存泄漏。所以一般只要 valgrind 程序名 即可。 比如源程序 #include void func() { char* ch = new char[10]; ch[0]='1'; } int main() { func(); return 0; } 对其进行检查 ╰─○ valgrind ./learn ==26826== Memcheck,

ThreadPool注解

关于线程池是很早就想去看的,在github上找了star最多的C++ 11 版本,然而一下子看不懂,就搁置在那了。 因为昨天百度面试问到了,我甚至回答我看过但是没看完,有点尴尬,今天花了点时间学了一下基础,并对源码进行了注解。 github 地址 先说一下我现在对上面这个线程池实现原理的理解。 理解之后可以说是很简单了,这个线程池本质上是互斥和条件变量的妙用。 我先开一个事件队列,再开几个线程,首先这些线程在整体上都是死循环,但会在事件队列为空的时候进入睡眠状态(由条件变量控制)。当事件队列非空,那么我就从事件队列中取出一个事件,再将这个事件搭载在线程上运行。事件运行结束后这个线程进入下一个循环,如果事件队列为空,则又会进入睡眠状态。如此循环往复…… 这里再分享一下我的一点学习经历,关于future,胡言乱语的一些理解,有错误后续会更改。 我当前的理解是,future是作为一个异步机制的需要而出现(猜测也是开了个线程异步执行。 future可由packaged_task封装后get_future,promise关联,async生产所得。 可使用get方法获其结…

UNIX网络编程基础总结

前几天因为一直在看IPC(进程间通信),有几个问题去搜的时候无意中发现这些IPC方法其实以及不大常用了,最最常用的还是socket…… 我是一直以为socket只会在网络上使用较多,其他不大会使用,现在发现我可能真的错了,于是打算把学IPC的精力放在巩固和加深socket上,其他IPC只做大概了解。 最基础的 TCP 套接字编程 暂时只贴注释代码 Server /* *********************************************************************** > File Name: k_server.cpp > Author: Key > Mail: keyld777@gmail.com > Created Time: Fri 06 Apr 2018 09:50:54 PM CST *********************************************************************** */ #include #i

shared_ptr的一些理解

瞎看了一点博客自认为搞懂,现在没什么时间写代码,写简单记下来。 shared_ptr的是一种“引用计数型智慧指针”(RCSP),它最核心的本质在于引用计数。 并且这个引用计数器也是一个类指针。 除开这个引用计数器以外,自然还有本重要的指针了,除此之外就没有其他的成员变量。 shared_ptr与uniqe_ptr的重要区别在于,unique_ptr只能指向一个对象,这是由它的析构函数决定的,因为析构函数必定会释放掉指针所指的内存,如果指向多个,将会多次释放,引起错误。 因此,unique_ptr的构造是不允许nullptr的。 与此相对,shared_ptr却可以,而且他默认构造就是指向nullptr,在真正构造非空对象的时候,才会将两个指针用上。 并且在赋值等操作引起计数器变为 0 的时候会立刻delete,而就算没有变为0,在最后析构的时候也会强制delete。 上面那个是我的煞笔言论,shared_ptr的delete内存只会在引用计数为0的时候调用,这就造成了循环引用导致的内存泄漏问题,进而引出了weak_ptr。 写完好像很简单的样子…… 另…