说说文件描述符
文件描述符就是一个整数,在open时产生。起到一个索引的作用,进程通过PCB中的文件描述符表找到该fd所指向的文件指针。
文件描述符的操作:返回一个文件描述符,内核会在每个进程空间中维护一个文件描述符表,所以打开的文件都将通过此表中的文件描述符来引用。
每个进程在PCB即进程控制块中都保存着一份文件描述符表,文件描述符就是这个表的索引,文件描述表中每个表项都有一个指向已打开文件的指针,已打开的文件在内核用file结构体表示,文件描述符表中的指针指向file结构体。
Linux和os
netstat(显示网络状态):查看IP/Port占用情况,用于显示各种网络相关信息,网络连接,路由表,接口状态等。
netstat输出结果分为两种(1)有缘TCP连接(2)有源Unix域套接口(和网络套接口一样,但只能用于本机通信)
Proto显示连接使用的协议,RefCnt表示连接到本套接口上的进程号,Types显示套接口的类型,State显示套接口当前的状态,Path表示连接到套接口的其它进程使用的路径名。
ipcs:显示进程间通信设施状态的工具
用途:报告进程间通信设备状态。
ipcs -s 信号量
ipcs -m 共享内存
ipcs -q 消息队列
ipcrm手动解除系统上共享内存的分配
查看cpu信息
cat /proc/cpuinfo
查看内存
cat /proc/meminfo
查看硬盘信息
df -lh
查看网卡信息
dmesg | grep eth
常用命令
uname -a
共享内存的使用实现原理
定义:共享内存是最快的IPC形式。它允许多个不相关的进程去访问同一部分逻辑内存。共享内存是由IPC为一个进程创建的一个特殊的地址范围,他将出现在进程的地址空间中。其他进程可以额把同一段共享内存“连接到”它们自己的地址空间去。
原理:两个不同进程,同一块物理内存被映射进程A、B各自的进程地址空间。
BBS段
可执行程序包括BSS段、数据段、代码段(文本段)。
size a.out显示可执行文件大小
du -h dirname(显示目录大小包括子目录)
du -ah –max-depth=num dirname显示第num层之前的所有目录大小
使用过哪些进程间通讯机制,并详细说明(重点)
(1)管道。分为匿名管道和命名管道,他们的数据都只能单向流动,唯一的区别就是匿名管道只能由于有血缘关系的进程间通信。
(2)信号量。信号量是一个计数器,用于控制多个线程对共享资源的访问,他不是用于交换大量数据,而是用于同布的。主要用于进程间以及进程内的各线程之间同步。
(3)信号。用于通知接受进程某事件发生。
(4)消息队列。是消息的链表,它克服了管道面向无格式流和缓冲区受限制等缺点,并且接收方可以根据消息类型按任何顺序接受。
(5)共享内存。同一块物理内存被映射到不同进程的进程空间中。共享内存是最快的IPC方式。和其他通信机制一起使用,比如信号量,来实现进程间的同步与通信。
GDB调试
(1)GDB调试多进程程序
单独调试子进程(可以先用ps |grep”进程名”得到pid)
attach “PID”
使用调试器选项follow-fork-mode
follow-fork-mode parent/child 调试子进程还是父进程
(2)用gdb调试多线程程序
info threads
显示当前可调试的所以线程。
thread id
调试目标id指定的线程
set-scheduler-locking[ off | on | step ]
锁定执行线程
off表示不锁定任何线程。默认值
on表示只有当前被调试的线程会继续执行
step表示在单步执行的时候,只有当前线程会执行
thread apply ID1 ID2 command
让一个或者多个线程执行GDB命令command。
thread apply all command
让所有被调试线程执行GDB命令command。
如何定位内存泄漏
使用Valgrind
它里面好像是对进程的整个地址空间一个字节都对应8bit,对每个CPU的寄存器也有与之对应的1bit
这些bits 负责记录该字节或者寄存器值是否具有有效的、已初始化的值。
对于进程整个地址空间中的每一个字节(byte),还有与之对应的 1 个 bit,负责记录该地址是否能够被读写。
检测原理:
读写时,先检测这个字节对应的bit,看其是否为无效地址
推迟时可以检测列表,对内存是否释放做出确定
动态链接和静态链接的区别
动态库和静态库
先将源文件编译成目标文件:gcc –c a.c b.c
生成静态库:ar –rc libstatic.a a.o b.o
共享库:
同静态库一样编译成目标文件:gcc –c a.c b.c
生成共享库:gcc –fPIC –shared –o libshared.so a.o b.o
由此可见静态库和动态库都是对目标文件的处理,也可以说库文件已经是机器码文件了,静态库和共享库的加载过程有很大的区别。
动态链接是指在生成可执行文件时不将所有程序用到的函数链接到一个文件,因为有许多函数在操作系统带的dll文件中,当程序运行时候直接从操作系统中找。而静态链接就是把所有用到的函数直接链接到exe文件中。
动态链接是只建立一个引用的接口,而真正的代码和数据存放在另外可执行模块中,在运行时再装入;而静态链接是把所有的代码和数据都复制到本模块中,运行时就不再需要库了。
多进程和多线程的区别
进程和线程的区别
(1)二者的相同点
对于我们了来说无论进程和线程,都是用来实现多任务并发的技术手段。二者都可以独立调度,因此功能上无差异。二者都具有各自的实体,是系统独立管理的对象个体。
(2)实现方式的差异
进程是资源分配的基本单位,线程是调度的基本单位。
进程的个体是完全独立的,而线程是彼此依存的(只有少量自己的空间,栈,寄存器等)。多进程环境中,任何一个进程的终止,不会影响到其他进程。多线程环境中,父线程终止,所有子线程终止。子线程调用exit()所有线程同时灭亡。
从系统实现角度来说,进程是使用fork(),fork()是将父进程的全部资源复制给子进程。而线程的clone只是复制了一小部分必要的资源
(3)实体间通信方式不同
进程间通信方式有这么几种:
A、共享内存 B、消息队列 C、信号量 D、有名管道 E、无名管道
G、文件 H、socket
线程间通信方式
A.、互斥量 B、自旋锁 C、条件变量 D、读写锁 E、线程信号
G、全局变量
(4)控制方式的异同
进程与线程的身份标识ID管理方式不一样,进程ID的话,如果深入了解它那个pid_t其实就是一个int型的变量。对于进程管理都是通过PID来实现的。每创建一个进程,内核就会创建一个结构体task_struct来存储该进程的全部信息。操作系统通过PCB对进程管理和调度。
另外操作系统为每个进程分配了一块存储器区域,并在系统建立和维护的进程表 task[] 中进行记录。进程表中包含记录每个进程的表项,表项内容包括指向包含进程的存储地址的指针和进程的执行上下文。程序计数器寄存器通过指向该进程中下一条待执行的指令。
而线程ID是一个long型变量
它的范围大的多,管理方式也不同。
其方式是,在内核创建一个内核态线程与之对应,也就是说每一个用户创建的线程都有一个内核态线程对应。但这种对应关系不是一对一,而是多对一的关系,也就是一个内核态线程可以对应着多个用户级线程。
内核空间实现还为每个内核支持线程设置了一个线程控制快,内核是根据该控制块而感知某个线程是否存在,并加以控制。
信号
信号:用来通知某进程发生了什么事件。
信号的处理方法:
(1)第一种是类似中断的处理程序,对于需要处理的信号,进程可以制定处理函数,由该函数来处理。
(2)第二种方法是,忽略某个信号,对该信号不做任何处理
(3)第三种方法是,对该信号进行阻塞,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。
进程表的表象中有一个信号相关的信号域,域中每一位对应一个信号。有三个信号表,第一个为阻塞信号表blocking,
第二个为忽略信号表pending,第三个为处理信号表handler。
信号到达后查看信号对应的位,0/1,0为未设置此项处理方法,1表示设置了。
i++是否为原子操作?为什么?
不i++的汇编非为三步
内存到寄存器
寄存器+1
寄存器再到内存
说出你所知道的 linux 系统的各类同步机制 (重点) ?
互斥锁
原子量
条件变量
信号量
自旋锁
无锁队列(CAS原子操作)
多路复用
time_wait状态是什么,为什么会有time_wait状态?哪一方会有time_wait状态,如何避免time_wait 状态占用资源 (必须回答的详细)
time_wait状态存在于主动关闭连接的一方收到另一方Fin并返回ack包时的状态,当处于time_wait状态时,我们无法创建新的连接,因为端口被占用。
time_wait存在的原因有两点
(1)可靠的终止TCP连接
若处于time_wait的客户端发送给服务器确认报文段丢失的话,服务器将再次重新发送FIN报文段,那么客户端必须处在一个可接收的状态就是time_wait状态。
(2)保证让迟来的TCP报文段有足够的时间被识别并丢弃。
Linux中一个TCP端口不能打开两次或以上,当客户端处于time_wait状态时我们将无法使用此端口建立新连接,如果不存在time_wait状态,新连接可能会收到旧连接的数据。time_wait持续的时间是2MSL,保证旧的数据可以丢失,因为网络中的数据最大存在MSL
如何避免?
如果是服务器主动关闭连接后异常终止,则因为它总是使用一个知名端口号,所以time_wait状态将导致它不能重新启动,不过我们可以通过socket的选项SO_REUSEADDR来强制进程立即使用处在time_wait状态的占用的端口。
TCP与UDP的区别
(1)面向连接:TCP面向连接,面向连接意味着使用TCP交换数据之前必须先建立连接,结束后再释放连接,TCP中仅有两方彼此通信,多播和广播不能用于TCP。UDP是不可靠传输,传输前不需要建立连接,可以应用多播和广播实现1对多通信。
(2)可靠性:TCP提供端到端的流量控制,对收到的数据进行确认,采用超时重发,对失序的的数据进行重新排序等机制保证数据通信的可靠性。而UDP是一种不可靠的服务,接收方可能不能收到发送方的数据。
(3)TCP是一种流模式的协议,UDP是一种数据报模式的协议。进程的每个输出操作都正好残生一个UDP数据报,并组装成一份待发送的IP数据报。TCP应用程序产生的全体数据与真正发送的单个IP数据报可能没有什么联系。TCP会有粘包和半包的现象。
(4)效率上:速度上,一般TCP速度慢,传输过程中需要对数据进行却热播,超时重发,还要对数据排序。UDP没有这些机制所以速度快。数据比例,TCP头至少20个字节,UDP头8个字节,相对效率高。组装效率上:TCP头至少20个字节,UDP头8个字节,系统组装上TCP相对慢。
(5)用途上:用于TCP可靠性,http,ftp使用。而由于UDP速度快,视频在线游戏多用UDP保证游戏实时性。