操作系统面试知识点。
先了解一下CAS无锁队列的概念。CAS的意思是Compare And Swap,从字面意思上面也可以知道实际就是对数据进行交换的一种原子操作。对应到CPU指令的话就是cmpxchg。
无锁队列的内部实现实际也是原子操作,可以避免多线程调用出现的不可预知的情况。主要的核心就是函数__sync_bool_compare_and_swap,返回值为bool型,原子交换操作成功返回true,失败返回false。
【注】原子操作:原子操作通俗的将就是一段指令的执行期间不会被其他的进程或者线程打断,可以保证执行的一致性。
在早期的时间片轮转法中,系统将所有的就绪进程按先来先服务的原则,排成一个队列,每次调度时,把CPU分配给队首进程,并令其执行一个时间片.时间片的大小从几ms到几百ms.
当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便据此信号来停止该进程的执行,并将它送往就绪队列的末尾;
然后,再把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片.
这样就可以保证就绪队列中的所有进程,在一给定的时间内,均能获得一时间片的处理机执行时间.
为了防止多进程竞争共享资源,而造成的数据错乱,所以需要保护机制,使得共享的资源,在任意时刻只能被一个进程访问。
信号量就实现了这一保护机制。
上下文简单说来就是一个环境,保存用户空间状态是上文,切换后在内核态执行的程序是下文。
1.进程上下文:
进程上下文就是进程中使用的进程块,线程块,相关硬件地址,等内部的内容状态。上下文指的是在这一个状态下,上文表示的是状态之前的进程的基础状态,下文表示这一状态之后的进程状态。
(1)进程上文:
其是指进程由用户态切换到内核态是需要保存用户态时cpu寄存器中的值,进程状态以及堆栈上的内容,即保存当前进程的进程上下文,以便再次执行该进程时,能够恢复切换时的状态,继续执行。
(2)进程下文:
其是指切换到内核态后执行的程序,即进程运行在内核空间的部分。
2.中断上下文:
中断上下文指操作系统将这个进程暂时冻结的时候,需要保存的进程相关内容,以及什么时候进程可以重新恢复。我们认为,保存进程的中止现场便于下次恢复。
(1)中断上文:
硬件通过中断触发信号,导致内核调用中断处理程序,进入内核空间。这个过程中,硬件的一些变量和参数也要传递给内核,内核通过这些参数进行中断处理。中断上文可以看作就是硬件传递过来的这些参数和内核需要保存的一些其他环境(主要是当前被中断的进程环境)。
(2)中断下文:
执行在内核空间的中断服务程序。
【注】
中断上下文代码中注意事项:
运行于进程上下文的内核代码是可抢占的,但中断上下文则会一直运行至结束,不会被抢占。
【注】中断处理程序代码要受到一些限制,在中断代码中不能出现实现下面功能的代码:
(1)睡眠或者放弃CPU
因为内核在进入中断之前会关闭进程调度,一旦睡眠或者放弃CPU,这时内核无法调度别的进程来执行,系统就会死掉。牢记:中断服务子程序一定不能睡眠(或者阻塞)。
(2)尝试获得信号量
如果获得不到信号量,代码就会睡眠,导致(1)中的结果。
(3)执行耗时的任务
中断处理应该尽可能快,因为如果一个处理程序是IRQF_DISABLED类型,他执行的时候会禁止所有本地中断线,而内核要响应大量服务和请求,中断上下文占用CPU时间太长会严重影响系统功能。中断处理程序的任务尽可能放在中断下半部执行。
(4)访问用户空间的虚拟地址
因为中断运行在内核空间。
例子:我们在使用KVM虚拟化的时候,Linux和Ring级别,Ring级别的上下文切换就是进程上下文。
我们的CPU在出现io_wait的时候,就是一种典型的中断上下文。
作为服务器的文件系统,ext2,ext3,ext4,xfs,btrfs,raiserfs,zfs。
手机用的操作系统,进入了内核,f2fs,flash 优化。
嵌入式用的操作系统 squashfs。
windows 下的refs,mac的hfs。
可插拔的fat32,exfat,fat16。
然后还有fuse下的文件系统,例如mergefs,SnapRAID。
此外分布式的文件系统也有很多CephFS等。
Linux:
1、首先是BIOS加电自检、初始化,这个过程会检测相关硬件(cpu、内存、显卡、硬盘等),然后读取一个启动顺序,以硬盘为例,会读取硬盘中的MBR。
2、加载内核 读取/boot里边的配置文件。
3、启动初始化进程,开始运行/sbin/init
4、读取/etc/inittab确定运行级别
5、根据/etc/rc.d/rcN.d加载开机启动程序,rcN.d都是链接文件,都指向/etc/rc.d/init.d 再运行/etc/rc.d/rc.local
6、用户登录(3种方式 ssh、命令行、图形化)
7、进入login shell,以命令行为例,首先读取/etc/profile这个全局配置文件,然后再针对当前用户读取家目录中的/.bash_profile和/.bash_login和~/.profile
8、最后一步就是打开non-login shell,进入图形化后 手动新建一个终端,但这个shell不读取/etc/profile
Windows:
1、电脑开机后,开始启动BIOS,开始BIOS自检。
2、通过自检后,bios找到硬盘上的主引导记录MBR.
3、MBR开始读取硬盘分区表DPT,找到活动分区,找到活动分区中的分区引导记录PBR,并且把控制权交给PBR.
4、PBR搜索活动区中的启动管理器bootmgr,找到后,PBR把控制权交给bootmgr(相当于xp里的ntldr文件)。
5、Bootmgr寻找活动分区中的boot文件夹中的BCD文件(启动配置数据,相当于xp里的boot.ini文件)。
6、找到BCD后,Bootmgr首先从BCD 中读取启动管理器bootmgr菜单的语言版本信息,然后再调用BOOTMGR与相应语言的BOOTMGR.EXE.MUI (在boot文件夹对应语言文件夹中)组成相应语言的启动菜单,之后在显示器上显示多操作系统选择画面。
7、如果存在多个操作系统而且系统设置的等待时间不是0,那么屏幕就显示多个操作系统的选择界面。如果没有多系统,那么直接进入当前的windows 系统,不显示选择界面。
8、选择windows 系统后,bootmgr就会读取BCD里win系统所在的盘里的windows\system32\winload.exe文件,并且将控制权交给winload.exe。
9、Winload.exe加载windows内核、硬件、服务等,之后加载桌面等信息,从而启动整个windows 系统。
10、上面几步可以概括一下就是:
BIOS—MBR—DPT—PBR—Bootmgr—BCD—系统选择界面—选择windows—Winload.exe—内核加载等 —启动整个windows系统
定义联合体,一个成员是多字节,一个是单字节,给多字节的成员赋一个最低一个字节不为0,其他字节为0的值,再用第二个成员来判断,如果第二个字节不为0,就是小端,若为0,就是大端。
void judge_bigend_littleend3()
{
union
{
int i;
char c;
}un;
un.i = 1; //
if (un.c == 1) //
printf("小端\n"); // 1000
else
printf("大端\n"); // 0001
}