145 lines
9.3 KiB
Plaintext
145 lines
9.3 KiB
Plaintext
|
硬链接和软连接区别
|
|||
|
kill用法,某个进程杀不掉的原因(进入内核态,忽略kill信号)
|
|||
|
linux用过的命令
|
|||
|
系统管理命令(如查看内存使用、网络情况)
|
|||
|
管道的使用 |
|
|||
|
grep的使用,一定要掌握,每次都会问在文件中查找
|
|||
|
shell脚本
|
|||
|
find命令
|
|||
|
awk使用
|
|||
|
|
|||
|
作者:oscarwin
|
|||
|
链接:https://www.nowcoder.com/discuss/59394
|
|||
|
来源:牛客网
|
|||
|
|
|||
|
进程与线程
|
|||
|
|
|||
|
(1) 进程与线程区别?
|
|||
|
(2) 线程比进程具有哪些优势?
|
|||
|
(3) 什么时候用多进程?什么时候用多线程?
|
|||
|
(4) LINUX中进程和线程使用的几个函数?
|
|||
|
(5) 线程同步?
|
|||
|
在Windows下线程同步的方式有:互斥量,信号量,事件,关键代码段
|
|||
|
在Linux下线程同步的方式有:互斥锁,自旋锁,读写锁,屏障(并发完成同一项任务时,屏障的作用特别好使)
|
|||
|
知道这些锁之间的区别,使用场景?
|
|||
|
进程间通讯方式
|
|||
|
|
|||
|
管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
|
|||
|
|
|||
|
命名管道 (FIFO) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
|
|||
|
|
|||
|
信号量:信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据,有XSI信号量和POSIX信号量,POSIX信号量更加完善。
|
|||
|
|
|||
|
消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
|
|||
|
|
|||
|
共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。(原理一定要清楚,常考)
|
|||
|
|
|||
|
信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生,常见的信号。
|
|||
|
|
|||
|
套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
|
|||
|
|
|||
|
匿名管道与命名管道的区别:匿名管道只能在具有公共祖先的两个进程间使用。
|
|||
|
共享文件映射mmap
|
|||
|
mmap建立进程空间到文件的映射,在建立的时候并不直接将文件拷贝到物理内存,同样采用缺页终端。mmap映射一个具体的文件可以实现任意进程间共享内存,映射一个匿名文件,可以实现父子进程间共享内存。
|
|||
|
常见的信号有哪些?:SIGINT,SIGKILL(不能被捕获),SIGTERM(可以被捕获),SIGSEGV,SIGCHLD,SIGALRM
|
|||
|
内存管理
|
|||
|
|
|||
|
1. 虚拟内存的作用?
|
|||
|
2. 虚拟内存的实现?
|
|||
|
3. 操作系统层面对内存的管理?
|
|||
|
4. 内存池的作用?STL里内存池如何实现?
|
|||
|
5. 进程空间和内核空间对内存的管理不同?
|
|||
|
6. Linux的slab层,VAM?
|
|||
|
7. 伙伴算法
|
|||
|
8. 高端内存
|
|||
|
进程调度
|
|||
|
|
|||
|
1. Linux进程分为两种,实时进程和非实时进程;
|
|||
|
2. 优先级分为静态优先级和动态优先级,优先级的范围;
|
|||
|
3. 调度策略,FIFO,LRU,时间片轮转
|
|||
|
4. 交互进程通过平均睡眠时间而被奖励;
|
|||
|
死锁
|
|||
|
|
|||
|
(1) 死锁产生的条件;
|
|||
|
(2) 死锁的避免;
|
|||
|
命令行
|
|||
|
|
|||
|
Linux命令 在一个文件中,倒序打印第二行前100个大写字母
|
|||
|
```
|
|||
|
cat filename | head -n 2 | tail -n 1 | grep '[[:upper:]]' -o | tr -d '\n'| cut -c 1-100 | rev
|
|||
|
```
|
|||
|
|
|||
|
与CPU,内存,磁盘相关的命令(top,free, df, fdisk)
|
|||
|
网络相关的命令netstat,tcpdump等
|
|||
|
sed, awk, grep三个超强大的命名,分别用与格式化修改,统计,和正则查找
|
|||
|
ipcs和ipcrm命令
|
|||
|
查找当前目录以及字母下以.c结尾的文件,且文件中包含"hello world"的文件的路径
|
|||
|
创建定时任务
|
|||
|
IO模型
|
|||
|
|
|||
|
五种IO模型:阻塞IO,非阻塞IO,IO复用,信号驱动式IO,异步IO
|
|||
|
select,poll,epoll的区别
|
|||
|
select:是最初解决IO阻塞问题的方法。用结构体fd_set来告诉内核监听多个文件描述符,该结构体被称为描述符集。由数组来维持哪些描述符被置位了。对结构体的操作封装在三个宏定义中。通过轮寻来查找是否有描述符要被处理,如果没有返回
|
|||
|
存在的问题:
|
|||
|
1. 内置数组的形式使得select的最大文件数受限与FD_SIZE;
|
|||
|
2. 每次调用select前都要重新初始化描述符集,将fd从用户态拷贝到内核态,每次调用select后,都需要将fd从内核态拷贝到用户态;
|
|||
|
3. 轮寻排查当文件描述符个数很多时,效率很低; poll:通过一个可变长度的数组解决了select文件描述符受限的问题。数组中元素是结构体,该结构体保存描述符的信息,每增加一个文件描述符就向数组中加入一个结构体,结构体只需要拷贝一次到内核态。poll解决了select重复初始化的问题。轮寻排查的问题未解决。
|
|||
|
epoll:轮寻排查所有文件描述符的效率不高,使服务器并发能力受限。因此,epoll采用只返回状态发生变化的文件描述符,便解决了轮寻的瓶颈。
|
|||
|
为什么使用IO多路复用,最主要的原因是什么?
|
|||
|
epoll有两种触发模式?这两种触发模式有什么区别?编程的时候有什么区别?
|
|||
|
上一题中编程的时候有什么区别,是在边缘触发的时候要把套接字中的数据读干净,那么当有多个套接字时,在读的套接字一直不停的有数据到达,如何保证其他套接字不被饿死(面试网易游戏的时候问的一个问题,答不上来,印象贼深刻)。
|
|||
|
1. select/poll/epoll区别
|
|||
|
2. 几种网络服务器模型的介绍与比较
|
|||
|
3. epoll为什么这么快(搞懂这篇文章,关于IO复用的问题就信手拈来了)
|
|||
|
线程池
|
|||
|
|
|||
|
Linux的API
|
|||
|
|
|||
|
fork与vfork区别
|
|||
|
fork和vfork都用于创建子进程。但是vfork创建子进程后,父进程阻塞,直到子进程调用exit()或者excle()。
|
|||
|
对于内核中过程fork通过调用clone函数,然后clone函数调用do_fork()。do_fork()中调用copy_process()函数先复制task_struct结构体,然后复制其他关于内存,文件,寄存器等信息。fork采用写时拷贝技术,因此子进程和父进程的页表指向相同的页框。但是vfork不需要拷贝页表,因为父进程会一直阻塞,直接使用父进程页表。
|
|||
|
exit()与_exit()区别
|
|||
|
exit()清理后进入内核,_exit()直接陷入内核。
|
|||
|
孤儿进程与僵死进程
|
|||
|
1. 孤儿进程是怎么产生的?
|
|||
|
2. 僵死进程是怎么产生的?
|
|||
|
3. 僵死进程的危害?
|
|||
|
4. 如何避免僵死进程的产生?
|
|||
|
Linux是如何避免内存碎片的
|
|||
|
1. 伙伴算法,用于管理物理内存,避免内存碎片;
|
|||
|
2. 高速缓存Slab层用于管理内核分配内存,避免碎片。
|
|||
|
共享内存的实现原理?
|
|||
|
共享内存实现分为两种方式一种是采用mmap,另一种是采用XSI机制中的共享内存方法。mmap是内存文件映射,将一个文件映射到进程的地址空间,用户进程的地址空间的管理是通过vm_area_struct结构体进行管理的。mmap通过映射一个相同的文件到两个不同的进程,就能实现这两个进程的通信,采用该方法可以实现任意进程之间的通信。mmap也可以采用匿名映射,不指定映射的文件,但是只能在父子进程间通信。XSI的内存共享实际上也是通过映射文件实现,只是其映射的是一种特殊文件系统下的文件,该文件是不能通过read和write访问的。
|
|||
|
二者区别:
|
|||
|
1、 系统V共享内存中的数据,从来不写入到实际磁盘文件中去;而通过mmap()映射普通文件实现的共享内存通信可以指定何时将数据写入磁盘文件中。注:前面讲到,系统V共享内存机制实际是通过映射特殊文件系统shm中的文件实现的,文件系统shm的安装点在交换分区上,系统重新引导后,所有的内容都丢失。
|
|||
|
2、 系统V共享内存是随内核持续的,即使所有访问共享内存的进程都已经正常终止,共享内存区仍然存在(除非显式删除共享内存),在内核重新引导之前,对该共享内存区域的任何改写操作都将一直保留。
|
|||
|
3、 通过调用mmap()映射普通文件进行进程间通信时,一定要注意考虑进程何时终止对通信的影响。而通过系统V共享内存实现通信的进程则不然。注:这里没有给出shmctl的使用范例,原理与消息队列大同小异。
|
|||
|
|
|||
|
系统调用与库函数(open, close, create, lseek, write, read)
|
|||
|
同步方法有哪些?
|
|||
|
1. 互斥锁,自旋锁,信号量,读写锁,屏障
|
|||
|
2. 互斥锁与自旋锁的区别:互斥锁得不到资源的时候阻塞,不占用cpu资源。自旋锁得不到资源的时候,不停的查询,而然占用cpu资源。
|
|||
|
3. 死锁
|
|||
|
其他
|
|||
|
|
|||
|
++i是否是原子操作
|
|||
|
明显不是,++i主要有三个步骤,把数据从内存放在寄存器上,在寄存器上进行自增,把数据从寄存器拷贝会内存,每个步骤都可能被中断。
|
|||
|
判断大小端
|
|||
|
|
|||
|
```
|
|||
|
union un
|
|||
|
{
|
|||
|
int i;
|
|||
|
char ch;
|
|||
|
};
|
|||
|
void fun()
|
|||
|
{
|
|||
|
union un test;
|
|||
|
test.i = 1;
|
|||
|
if(ch == 1)
|
|||
|
cout << "小端" << endl;
|
|||
|
else
|
|||
|
cout << "大端" << endl;
|
|||
|
}
|
|||
|
```
|