参考文章
引文及相关资料
linux和os:
netstat tcpdump ipcs ipcrm (如果这四个命令没听说过或者不能熟练使用,基本上可以回家,通过的概率较小 ^_^ ,这四个命令的熟练掌握程度基本上能体现面试者实际开发和调试程序的经验)
http://blog.csdn.net/waltonhuang/article/details/52212533
cpu 内存 硬盘 等等与系统性能调试相关的命令必须熟练掌握,设置修改权限 tcp网络状态查看 各进程状态 抓包相关等相关命令 必须熟练掌握
http://blog.csdn.net/waltonhuang/article/details/52212623
awk sed需掌握
共享内存的使用实现原理(必考必问,然后共享内存段被映射进进程空间之后,存在于进程空间的什么位置?共享内存段最大限制是多少?)
http://blog.csdn.net/waltonhuang/article/details/52212727
每个共享内存区域对应特殊文件系统shm中的一个文件。
注:shmget的内部实现包含了许多重要的系统V共享内存机制;shmat在把共享内存区域映射到进程空间时,并不真正改变进程的页表。当进程第一次访问内存映射区域访问时,会因为没有物理页表的分配而导致一个缺页异常,然后内核再根据相应的存储管理机制为共享内存映射区域分配相应的页表。
通过shmat将这个内存区映射到本进程的虚拟地址空间。
在/proc/sys/kernel/目录下,记录着系统V共享内存的一下限制,如一个共享内存区的最大字节数shmmax,系统范围内最大共享内存区标识符数shmmni等,可以手工对其调整,但不推荐这样做。
c++进程内存空间分布(注意各部分的内存地址谁高谁低,注意栈从高道低分配,堆从低到高分配)
ELF是什么?其大小与程序中全局变量的是否初始化有什么关系(注意.bss段)
ELF(Executable Linkable Format)
使用过哪些进程间通讯机制,并详细说明(重点)
Python中可以使用mutiprocessing ,里面提供queue和pipe等进行通信。
这一系列的文章都写得很好,c实现进程间通信:
Linux环境进程间通信(二): 信号(上)
makefile编写,虽然比较基础,但是会被问到
make命令执行时,需要一个makefile文件,来告诉make命令怎样去编译和链接程序。
比如说如下的规则:
- 如果这个工程没有编译过,那么就要把所有的c文件编译和链接。
- 如果编译过了,如果有些c文件被修改,那就要重新编译这些c文件然后链接
- 如果修改了一些h文件,那就要重新编译引用这些h文件的c文件并链接。
gdb调试相关的经验,会被问到
Python用到了pdb
c是用gdb
用GDB调试程序(一)
- 在gcc的时候加上-g,把调试信息加到可执行文件中。
l列出代码break 16在16行设置断点rrun运行nnext 运行下一条sstep 有函数的话step inc继续运行到下一个断点p打印变量i localinfo查看local变量set var i = 1修改变量qquit 退出display查看表达式的值
如何定位内存泄露?
说了半天结果说让看wiki
mtrace
动态链接和静态链接的区别
http://www.cnblogs.com/kex1n/archive/2011/09/06/2168435.html
http://blog.csdn.net/gamecreating/article/details/5504152
静态链接就是在生成exe的时候已经把代码链接进去程序中,因此程序比较大,但是因为不需要动态链接所以效率比较高。
动态链接是在程序运行的时候需要的时候再引入dll,生成的exe比较小,如果缺失dll,程序就无法运行了。
32位系统一个进程最多多少堆内存
http://blog.csdn.net/pkueecser/article/details/8719827
首先,32 位地址最多可以映射 4 GB 的内存。
windows原来规定操作系统占2GB,剩下2GB可以申请。
但是微软又允许在boot.init加入/3GB参数,于是可以申请3GB内存。
32位操作系统每个进程4G虚拟内存,由上图可知:0x00000000-0xbfffffff,用户空间3G;0xc0000000-0xffffffff,内核空间1G
多线程和多进程的区别(重点 面试官最最关心的一个问题,必须从cpu调度,上下文切换,数据共享,多核cup利用率,资源占用,等等各方面回答,然后有一个问题必须会被问到:哪些东西是一个线程私有的?答案中必须包含寄存器,否则悲催)
http://blog.csdn.net/waltonhuang/article/details/52193276
写一个c程序辨别系统是64位 or 32位
判断一个指针的size,如果是4则是32位,如果是8则是64位。
写一个c程序辨别系统是大端or小端字节序
http://blog.csdn.net/waltonhuang/article/details/52092863
信号:列出常见的信号,信号怎么处理?
常见信号:
SIGHUP 终端挂起。用户推出shell的时候,由该进程启动的所有进程都会收到这个信号,默认动作为终止进程。
SIGINT 键盘中断。 CTRL+C。用户终端向正在运行的程序发出这个信号,默认动作为终止进程。
SIGQUIT CTRL+D CTRL+\ 退出。 终止进程。
SIGFPE 计算错误时终止进程并产生core文件。
SIGKILL 强制退出。不做清理和暂存。
SIGALRM 定时器超时。
SIGTERM 与SIGKILL的不同是,可以被阻塞。程序在终止前可以保存文件和清理临时文件。
i++是否原子操作?并解释为什么???????
i++ 是否为原子操作 和 Java中的volatile关键字
i++在两个线程里边分别执行100次,能得到的最大值和最小值分别是多少?
最小值:假设A线程的寄存器是ra,B线程的寄存器是rb,假设以下步骤:
- 线程A第一次i++,ra=i=0,ra++, ra=1, 但是还没写回去i。
- 线程B完整执行99次i++,i=99。
- 线程A将ra的值写回去i,i=ra=1。
- 线程B读i的值,写进去寄存器,rb=1, 自增,rb++, rb = 2, 但还没写回去。
- 线程A执行完了所有的i++。
- 线程B把rb的结果写回去i,i=2。
最大值:
- 线程A全部执行完了,i=100。
- 轮到线程B执行100次i++, i=200。
说出你所知道的各类linux系统的各类同步机制(重点),什么是死锁?如何避免死锁(每个技术面试官必问)
好文:这个写的很清晰啊:pthread的各种同步机制
代码例程:
http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
- 原子操作,不会被任何事务给打断,通常用于资源计数,引用计数。TCP/IP协议栈的IP碎片计数。
- 信号量。就像一个房间有好几把钥匙,拿到钥匙就能进去访问。设置为1的时候变为了mutex。绝大部分情况下作为互斥锁使用。
- 读写信号量。可以允许多个读,一个写。一旦有人在写,就大家都不能读。但是如果没人在写,就可以允许很多一起读。
- 自旋锁。自旋锁与互斥锁的区别在于不会导致睡眠,如果自旋锁被其他执行单元持有了,那么调用者就一直自旋在那循环地看持有者是否已经释放,而不睡眠。在持有时间短的情况下使用会比互斥锁高效。
- 大内核锁。
- 读写锁,一种特殊的自旋锁。
- 大读者锁。高性能的读写锁。实现机制:每个CPU都有一个读者锁写者锁,读者只需要获取本地CPU的读者锁,写者锁要获取所有CPU的锁。
- RCU(Read-Copy-Update)读不需要获取锁,写的话是先拷贝当前的文件,然后对副本修改,最后找时机(没有其他执行单元在读)使用回调函数把修改保存回去。如果多个写,需要写进程之间本身做好同步。
顺序锁(seqlock)读者可以在写的时候读,写者也可以在读的时候写,但是写与写之间还是互斥的。利用了一个序号,写的时候要对序号加1,这样读的人可以知道读的期间有没有人写。
死锁。就是几个进程申请资源,出现了无限循环等待的现象。
四个必要条件
- 资源是互斥的
- 不可抢占
- 占有且申请
- 循环等待
A、B进程都需要打印机和CDROM。现在A占有了打印机,B占有了CDROM。
1. 打印机和CDROM都是互斥的,打印机一个时间只能让一个进程使用,CDROM也是。
2. A进程不能要求B进程放弃它拥有的CDROM,B进程也不能要求A放弃它所拥有的打印机。
3. A占有了打印机还去申请CDROM,B占有了CDROM还去申请打印机。
4. A等待B,B也在等待A。
解决方案也从这四个条件来着手。
1. 资源的互斥是客观的,要改变的话不现实。
2. 申请资源不可满足的时候释放已经申请到的资源。
3. 只有在全部资源都可以得到的情况下才一次性分配。
4. 资源有序分配。给所有资源编号,进程对资源的请求必须是严格递增的序列,只有在占有了小号资源的情况下才能申请了大号资源。(假设打印机是小号资源,CDROM是大号资源)
列举说明linux系统的各类异步机制
在IO方面,有异步IO。
在进程间通信方面,有信号。
exit() _exit()的区别?
linux系统编程之进程(四):进程退出exit,_exit区别即atexit函数
exit()要调用终止处理程序和清除IO缓存后再退出
_exit()是“立即”终止程序。
如何实现守护进程?
daemon
linux系统编程之进程(八):守护进程详解及创建,daemon()使用
daemon的函数原型是
daemon(int nochdir, int noclose)
nochdir = 0,说明要变换目录到/
noclose = 0,说明要将标准输入、标准输出、标准错误重定向到/dev/null。
因此直接调用这个函数就可以实现守护进程了。
如果想自己实现守护进程。要做以下步骤:
1. fork()出子进程,父进程退出
2. 子进程创建新的session,调用setsid()
3. 子进程调用chdir,变换目录到/
4. 子进程设置文件创建掩膜
5. 子进程关闭不需要的文件描述符
linux的内存管理机制是什么?
首先,nowcoder上的题目指出,物理内存小于2G,交换分区应该为物理内存的2倍。物理内存大于2G,交换分区应该为物理内存+2G。
linux采用分页管理。每个页的大小是4KB。
进程运行时,先分配虚拟的页表,而不把数据和代码加载到物理内存。如果在访问时发现数据或者代码在虚拟页表中而不在物理内存中,则发生缺页错误,然后把数据和代码加载到物理内存中。如果物理内存满了,则采用页面置换算法置换。
linux的任务调度机制是什么?
首先,任务调度可以经过两个过程:选择算法(使用goodness函数计算权值,选取优先级高的)和上下文切换。
另外,任务调度可以分为主动调度(因为要等待输入而挂起等)和被动调度(被强占)
标准库函数和系统调用的区别?
很多库函数是对系统调用的简单封装。
系统调用是跟操作系统相关的,可移植性不好。
标准库函数与操作系统无关,可移植性好。
系统调用是内核空间和内核时间。
标准库函数是用户空间和用户时间。
如果用户直接使用系统调用,需要在用户空间和内核空间之间切换,开销比较大。比如说读写文件,如果直接用系统调用,会因为反复的切换而开销大。使用库函数,可以利用缓冲区,等往缓冲区写完了,再系统调用一次性把数据写入到硬件媒介。
补充一个坑爹坑爹坑爹坑爹的问题:系统如何将一个信号通知到进程?(这一题哥没有答出来)
内核给进程发送信号,是在进程所在的进程表项的信号域设置对应的信号的位。
进程检查信号的时机是:进程即将从内核态返回用户态时。如果进程睡眠了,要看睡眠能不能被中断,如果能被中断则唤醒。
进程有一个链表的数据结果,维护一个未决信号的链表。
信号在进程中注册,其实就是把该信号加入到这个未决信号链表当中。
可靠信号不管链表中是否已经有这个信号了,还是会加进去。不可靠信号,如果链表中已经有这个信号了,就会忽略。
进程处理信号的时机就是从内核态即将返回用户态度的时候。
执行用户自定义的信号处理函数的方法很巧妙。把该函数的地址放在用户栈栈顶,进程从内核返回到用户态的时候,先弹出信号处理函数地址,于是就去执行信号处理函数了,然后再弹出,才是返回进入内核时的状态。
被屏蔽的信号,取消屏蔽后还会被检查。
本文总结了腾讯后台开发面试中的核心知识点,包括Linux命令、内存管理、进程间通信、多线程、同步机制等内容,特别强调了对共享内存、信号处理、内存泄漏检测等的理解与应用。

9102

被折叠的 条评论
为什么被折叠?



