Linux后台开发应该具备技能
一、linux和os:
1、命令:netstat tcpdump ipcs ipcrm 这四个命令的熟练掌握程度基本上能体现实际开发和调试程序的经验
Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Memberships) 等等。
tcpdump 根据使用者的定义对网络上的数据包进行截获的包分析工具。 tcpdump可以将网络中传送的数据包的“头”完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来帮助你去掉无用的信息。
ipcs ipcrm是linux/uinx上提供关于一些进程间通信方式的信息,包括共享内存,消息队列,信号
ipcs用法
ipcs -a 是默认的输出信息 打印出当前系统中所有的进程间通信方式的信息
ipcs -m 打印出使用共享内存进行进程间通信的信息
ipcs -q 打印出使用消息队列进行进程间通信的信息
ipcs -s 打印出使用信号进行进程间通信的信息
ipcrm 命令
移除一个消息对象。或者共享内存段,或者一个信号集,同时会将与ipc对象相关联的数据也一起移除。当然,只有超级管理员,或者ipc对象的创建者才有这项权利啦
ipcrm用法
ipcrm -M shmkey 移除用shmkey创建的共享内存段
ipcrm -m shmid 移除用shmid标识的共享内存段
ipcrm -Q msgkey 移除用msqkey创建的消息队列
ipcrm -q msqid 移除用msqid标识的消息队列
ipcrm -S semkey 移除用semkey创建的信号
ipcrm -s semid 移除用semid标识的信号
2、cpu 内存 硬盘 等等与系统性能调试相关的命令必须熟练掌握,设置修改权限 tcp网络状态查看 各进程状态 抓包相关等相关命令 必须熟练掌握
3、awk sed需掌握
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用
4、共享内存的使用实现原理、然后共享内存段被映射进进程空间之后,存在于进程空间的什么位置?共享内存段最大限制是多少?
5、c++进程内存空间分布(注意各部分的内存地址谁高谁低,注意栈从高到低分配,堆从低到高分配)
6、ELF是什么?其大小与程序中全局变量的是否初始化有什么关系(注意.bss段)
ELF简介只需要看前面的部分http://blog.csdn.net/phoenix500526/article/details/50099919
ELF格式与bss段http://blog.csdn.net/rock_joker/article/details/77887291
7、使用过哪些进程间通讯机制,并详细说明
8、makefile编写,虽然比较基础,但是会被问到
Make 从 makefile(默认是当前目录下的名为‘Makefile’的文件)中读取项目的描述。makefile指定了一系列目标(比如可执行文件)和依赖(比如对象文件和源文件)的编译规则,其格式如下:
目标: 依赖
命令
对每一个目标,make 检查其对应的依赖文件修改时间来确定该目标是否需要利用对应的命令重新建立。注意到,makefile 中命令行必须以单个的 TAB 字符进行缩进,不能是空格。
GNU Make 包含许多默认的规则(参考隐含规则)来简化 makefile 的构建。比如说,它们指定‘.o’文件可以通过编译‘.c’文件得到,可执行文件可以通过将‘.o’链接到一起获得。隐含规则通过被叫做make变量的东西所指定,比如 CC(C 语言编译器)和 CFLAGS(C程序的编译选项);在makefile文件中它们通过独占一行的 变量=值 的形式被设置。对 C++ ,其等价的变量是CXX和CXXFLAGS,而变量CPPFLAGS则是编译预处理选项。
现在我们为上一节的项目写一个简单的 makefile 文件:
CC=gcc
CFLAGS=-Wall意思是编译后显示所有警告。
main: main.o hello_fn.o
clean:
rm -f main main.o hello_fn.o
该文件可以这样来读:使用 C 语言编译器 gcc,和编译选项‘-Wall’,从对象文件‘hello.o’和‘hello_fn.o’生成目标可执行文件 hello(文件‘hello.o’和‘hello_fn.o’通过隐含规则分别由‘hello.c’和‘hello_fn.c’生成)。目标clean没有依赖文件,它只是简单地移除所有编译生成的文件。rm命令的选项 ‘-f’(force) 抑制文件不存在时产生的错误消息。
另外,需要注意的是,如果包含main函数的cpp文件为A.cpp, makefile中最好把可执行文件名也写成 A。
要使用该 makefile 文件,输入 make。不加参数调用make时,makefile文件中的第一个目标被建立,从而生成可执行文件‘hello’:
$ make
gcc -Wall -c -o hello.o hello.c
gcc -Wall -c -o hello_fn.o hello_fn.c
gcc hello.o hello_fn.o -o hello
$ ./hello
Hello, world!
一个源文件被修改要重新生成可执行文件,简单地再次输入 make 即可。通过检查目标文件和依赖文件的时间戳,程序 make 可识别哪些文件已经修改并依据对应的规则更新其对应的目标文件:
$ vim hello.c (打开编辑器修改一下文件)
$ make
gcc -Wall -c -o hello.o hello.c
gcc hello.o hello_fn.o -o hello
$ ./hello
Hello, world!
最后,我们移除 make 生成的文件,输入 make clean:
$ make clean
rm -f hello hello.o hello_fn.o
一个专业的 makefile文件通常包含用于安装(make install)和测试(make check)等额外的目标。
本文中涉及到的例子都足够简单以至于可以完全不需要makefile,但是对任何大些的程序都使用 make 是很有必要的。
9、gdb调试相关的经验,会被问到
教程:http://blog.csdn.net/liigo/article/details/582231
10、如何定位内存泄露?
11、动态链接和静态链接的区别
12、32位系统一个进程最多多少堆内存
13、多线程和多进程的区别(重点 必须从cpu调度,上下文切换,数据共享,多核cup利用率,资源占用,等等各方面回答,然后有一个问题必须会被问到:哪些东西是一个线程私有的?答案中必须包含寄存器,否则悲催)
14、写一个c程序辨别系统是64位 or 32位
#include "stdio.h"
int main(int argc,char * argv[])
{
void* number = 0;
printf("%d\n",sizeof(&number));
}
输出8就是64位的,4就是32位的。根据逻辑地址判断。
15、写一个c程序辨别系统是大段or小段子节序
#include <stdio.h>
int main(int argc, char **argv)
{
int a = 0x12345678;
char *p;
p = (char *)(&a); //指向a的低地址
if (*p == 0x78)
printf("Small Endian.\n");//小端是指数据的高字节保存在内存的高地址中
else
printf("Big Endian.\n"); //大段是指数据的高字节保存在内存的低地址中
return 0;
}
需要c/c++ Linux后台服务器开发高阶知识学习视频资料的朋友
加入到群里一起探讨技术交流
![](https://i-blog.csdnimg.cn/blog_migrate/d3ed948b644cbee9f9e9bdcd86901541.jpeg)
知识点有C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等等。
Linux属于小端模式
16、信号:列出常见的信号,信号怎么处理?
http://www.bubuko.com/infodetail-325160.html
http://www.cnblogs.com/shihaochangeworld/p/5722090.html
17、i++是否原子操作?并解释为什么???????
一.i++
i++的操作分三步:
(1)栈中取出i(内存到寄存器)
(2)i自增1(寄存器自增)
(3)将i存到栈(写回内存)
这三个阶段中间都可以被中断分离开,所以i++不是原子操作。上面的三个步骤中任何一个步骤同时操作,都可能导致i的值不正确自增
二.++i
在多核的机器上,cpu在读取内存i时也会可能发生同时读取到同一值,这就导致两次自增,实际只增加了一次。
综上,我认为i++和++i都不是原子操作。
18、说出你所知道的各类linux系统的各类同步机制(重点),什么是死锁?如何避免死锁(每个技术面试官必问)
通讯有很多方式
1)管道
2)共享内存
3)消息队列
4)TCP socket
5)用文件裸奔:使用文件锁,利用fcntl对一个打开的文件描述符进行操作,文件内容来交互数据;
文件锁具体使用(可以不看)http://blog.csdn.net/hanbo622/article/details/51509573
6)最基本的进程signal一般使用SIGUSR1和SIGUSR2实现用户自定义功能
7)socketpair
等,只要能交流就可以了。这个是IPC(Inter Process Communication)
而同步的方式主要是
1)Mutex(互斥)可以跨进程使用
2)Semphore(信号量)可以跨进程使用
等
两者适用范围场合依据需求决定
PS:事件拿来控制同步也可以,说它是一个通讯方式也可以。
如果配合起来可以是:
Case 1)
进程A将资料写入共享内存(使用Mutex加锁)
进程B从共享内存中读资料(也使用Mutex加锁)
Case 2)使用Semaphore实现的读写锁
进程A将资料写入共享内存(加写锁)
进程B从共享内存中读资料(加读锁)
性能比上面的好很多。
.NET写共享内存的时候尽量写入基本数据类型或者Structure数据效率较高,避免大范围的系列化反序列化的动作影响性能。避免共享内存中有脏数据。
死锁
什么是死锁
死锁是指多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。例如,在某一个计算机系统中只有一台打印机和一台输入 设备,进程P1正占用输入设备,同时又提出使用打印机的请求,但此时打印机正被进程P2 所占用,而P2在未释放打印机之前,又提出请求使用正被P1占用着的输入设备。这样两个进程相互无休止地等待下去,均无法继续执行,此时两个进程陷入死锁状态。
死锁产生的原因
1. 系统资源的竞争
系统资源的竞争导致系统资源不足,以及资源分配不当,导致死锁。
2. 进程运行推进顺序不合适
进程在运行过程中,请求和释放资源的顺序不当,会导致死锁。
产生死锁的四个必要条件:
互斥条件:一个资源每次只能被一个进程使用,即在一段时间内某 资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。
请求与保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源 已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
不可剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能 由获得该资源的进程自己来释放(只能是主动释放)。
循环等待条件: 若干进程间形成首尾相接循环等待资源的关系
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
死锁的避免与预防:
死锁避免的基本思想:
系统对进程发出每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,如果分配后系统可能发生死锁,则不予分配,否则予以分配。这是一种保证系统不进入死锁状态的动态策略。
理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。所以,在系统设计、进程调度等方面注意如何让这四个必要条件不成立,如何确定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态的情况下占用资源。因此,对资源的分配要给予合理的规划。
死锁避免和死锁预防的区别:
死锁预防是设法至少破坏产生死锁的四个必要条件之一,严格的防止死锁的出现,而死锁避免则不那么严格的限制产生死锁的必要条件的存在,因为即使死锁的必要条件存在,也不一定发生死锁。死锁避免是在系统运行过程中注意避免死锁的最终发生。
另:锁的比较
对于线程的mutex锁,效率比线程的读写锁(rwlock)要高,但是没有读写锁实用性强,因为读写锁可以有共享读锁。
对于进程的mutex锁,效率比文件读写锁的效率要高的非常多,文件锁效率虽然非常慢,但是比较安全,在一个进程挂掉之后,如果它获取了mutex锁。则其他进程会阻塞,但是如果用了文件锁,则会自动释放该锁。
然后线程的mutex是比进程的mutex效率高的。。毕竟线程比较轻量级。
锁的使用(不重要可以不看)http://blog.csdn.net/jason_zjj/article/details/54828788
19、列举说明linux系统的各类异步机制
20、exit() _exit()的区别?
_exit 函数的作用是:直接使进程停止运行,清除其使用的内存空间,并清除其在内核的各种数据结构;
exit 函数则在这些基础上做了一些小动作,在执行退出之前还加了若干道工序。exit() 函数与 _exit() 函数的最大区别在于exit()函数在调用exit 系统调用前要检查文件的打开情况,把文件缓冲区中的内容写回文件。也就是图中的“清理I/O缓冲”。
21、如何实现守护进程?
http://blog.csdn.net/rock_joker/article/details/76734632
22、linux的内存管理机制是什么?
23、linux的任务调度机制是什么?
http://www.cnblogs.com/zhaoyl/archive/2012/09/04/2671156.html
24、linux的信号处理机制是什么?
http://www.bubuko.com/infodetail-325160.html
http://www.cnblogs.com/shihaochangeworld/p/5722090.html
25、标准库函数和系统调用的区别?
库函数是语言本身的一部分,而系统函数是内核提供给应用程序的接口,属于系统的一部分。
函数库调用是语言或应用程序的一部分,而系统调用是操作系统的一部分。
用户应用程序访问并使用内核所提供的各种服务的途径即是系统调用。在内核和用户应用程序相交界的地方,内核提供了一组系统调用接口,通过这组接口,应用程序可以访问系统硬件和各种操作系统资源。 标准C库函数提供的文件操作函数如fopen, fread, fwrite, fclose, fflush, fseek等,需包含头文件stdio.h实现仍是调用系统调用中的open,同时也有不调用系统调用的比如说用于字符串操作函数strcpy,strlen,strstr
1.系统调用是为了方便应用使用操作系统的接口,而库函数是为了方便人们编写应用程序而引出的,比如你自己编写一个函数其实也可以说就是一个库函数。
2.系统调用可以理解为内核提供给我们在用户调用的接口函数,可以认为是某种内核的库函数。
3.read就是系统调用,而fread就是C标准库函数.系统调用提供的函数如open, close, read, write, ioctl等,需包含头文件unistd.h.
26、补充一个坑爹坑爹坑爹坑爹的问题:系统如何将一个信号通知到进程?
二、c语言:
1、宏定义和展开(必须精通)
2、位操作(必须精通)
3、指针操作和计算(必须精通)
4、内存分配(必须精通)
5、各类库函数必须非常熟练的实现
6、哪些库函数属于高危函数,为什么?(strcpy等等)
三、c++:
1、一个String类的完整实现必须很快速写出来(注意:赋值构造,operator=是关键)
2、虚函数的作用和实现原理(必问必考,实现原理必须很熟)
3、sizeof一个类求大小(注意成员变量,函数,虚函数,继承等等对大小的影响)
4、指针和引用的区别(一般都会问到)
5、多种类构造和析构的顺序
6、stl各容器的实现原理(必考)
7、extern c 是干啥的,(必须将编译器的函数名修饰的机制解答的很透彻)
8、volatile是干啥用的,(必须将cpu的寄存器缓存机制回答的很透彻)
9、static const等等的用法,(能说出越多越好)
四、数据结构或者算法:
1、《离散数学》范围内的一切问题皆有可能被深入问到(这个最坑爹,最重要,最体现功底,最能加分,特别是各类树结构的实现和应用)
2、各类排序:大根堆的实现,快排(如何避免最糟糕的状态?),bitmap的运用等等
3、hash, 任何一个技术面试官必问(例如为什么一般hashtable的桶数会取一个素数?如何有效避免hash结果值的碰撞)
五、网络编程:
1、tcp与udp的区别(必问)
2、udp调用connect有什么作用?
3、tcp连接中时序图,状态图,必须非常非常熟练
4、socket服务端的实现,select和epoll的区别(必问)
5、epoll哪些触发模式,有啥区别?(必须非常详尽的解释水平触发和边缘触发的区别,以及边缘触发在编程中要做哪些更多的确认)
6、大规模连接上来,并发模型怎么设计
7、tcp结束连接怎么握手,time_wait状态是什么,为什么会有time_wait状态?哪一方会有time_wait状态,如何避免time_wait状态占用资源(必须回答的详细)
8、tcp头多少字节?哪些字段?(必问)
9、什么是滑动窗口(必问)
10、connect会阻塞,怎么解决?(必考必问,提示:设置非阻塞,返回之后用select检测状态)
11、如果select返回可读,结果只读到0字节,什么情况?
12、keepalive 是什么东东?如何使用?
13、列举你所知道的tcp选项,并说明其作用。
14、socket什么情况下可读?
六、db:
1、mysql,会考sql语言,服务器数据库大规模数据怎么设计,db各种性能指标
最后2、:补充一个最最重要,最最坑爹,最最有难度的一个题目:一个每秒百万级访问量的互联网服务器,每个访问都有数据计算和I/O操作,如果让你设计,你怎么设计?