当前位置: 首页 > Linux

操作系统面试常见问题

时间:2023-04-06 21:49:54 Linux

标题:操作系统面试常见问题分类:[操作系统]标签:[面试题]日期:2021/05/12作者:hackett微信公众号:加班猿1请说Let's看看进程和线程的概念,为什么会有进程线程,有什么区别,它们是如何同步的。基本概念:进程是对运行时程序的封装,是系统调度和分配资源的基本单位。实现了操作系统的并发;线程是进程的子任务,是CPU调度调度的基本单位,用于保证程序的实时性,实现进程内的并发;线程是操作系统可识别的最小执行和调度单元。区别:1.一个线程只能属于一个进程,一个进程可以有多个线程,但至少有一个线程。线程依赖于进程而存在。2、进程在执行过程中有独立的内存单元,多个线程共享进程的内存。(资源分配给一个进程,同一个进程的所有线程共享该进程的所有资源。同一个进程的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储)但是每个线程都有自己的栈段,也叫运行期,用来存放所有的局部变量和临时变量。)3.进程是资源分配的最小单位,线程是CPU调度的最小单位;4、系统开销:当创建或取消进程时,系统必须为其分配或回收资源,如内存空间、I/O设备等。因此,操作系统付出的开销会明显大于创建或销毁线程时的开销。同理,在进程切换时,涉及到当前整个进程CPU环境的保存和新调度运行进程的CPU环境设置。但是线程切换只需要保存和设置少量寄存器的内容,并不涉及内存管理操作。可见进程切换的开销要比线程切换大很多。5、通信:由于同一个进程中的多个线程拥有相同的地址空间,它们之间的同步和通信的实现变得更加容易。进程间通信IPC,线程可以直接读写进程数据段(如全局变量)进行通信——需要借助进程同步和互斥手段来保证数据的一致性。在某些系统中,线程切换、同步和通信不需要操作系统内核的干预。比较复杂。7、进程之间不会相互影响;如果一个线程挂了,整个进程都会挂掉。8、进程适合多核多机分布;threads适用于多核进程间通信:pipeline(是内核buffer,进程使用advancedFirstout从buffer中访问数据)namedpipeFIFO(对应一个磁盘索引节点,可以被任意访问进程)消息队列(为每条消息指定特定的数据类型,可以根据自定义条件接收特定类型的消息)共享内存(效率高,直接读写内存,不需要拷贝数据)信号量(原子操作,传递数据需要结合共享内存)socket套接字(用于不同机器之间的进程通信)signal(用于通知接收进程某个事件发生了)2MySQL的端口号是多少,如何修改端口号为查看端口号:使用命令showglobalvariableslike'port';查看端口号,mysql默认端口是3306修改端口号:修改端口号:编辑/etc/my.cnf文件3请问有进程,为什么有线程?线程的原因:进程可以使多个程序并发执行,提高资源利用率和系统吞吐量;但它也有一些缺点:进程一次只能做一件事。如果进程在执行过程中被阻塞,整个进程就会挂起,即使进程中的某些工作不依赖于等待资源,仍然不会被执行。与进程相比,线程的优势在于:在资源方面,线程是一种非常“节俭”的多任务运行方式。在Linux系统下,启动一个新的进程必须为其分配一个独立的地址空间,并创建无数的数据表来维护它的代码段、堆栈段和数据段。这是一种“昂贵”的多任务工作方式。在切换效率方面,一个进程中运行的多个线程使用相同的地址空间,线程之间切换所需的时间比进程之间切换所需的时间要短得多。据统计,进程的开销大约是线程的30倍。在通信机制上,它是一种方便的线程间通信机制。对于不同的进程,它们有独立的数据空间,数据的传递只能通过进程间通信进行,不仅耗时,而且很不方便。线程则不然,因为数据空间是同一个表项下线程之间贡献的,所以一个线程的数据可以直接被其他线程使用,不仅速度快,而且方便。除了以上优点,多线程程序作为一种多任务并发的工作方式,还具有以下优点:1.使多CPU系统更加高效。操作系统会保证当线程数不大于CPU数时,不同的线程运行在不同的CPU上。2.改进程序结构。一个漫长而复杂的进程可以分成多个线程,成为几个独立或半独立运行的部分。这样的程序将易于理解和修改。4在单核机器上写多线程程序是否需要考虑加锁?为什么?在单核机器上写多线程程序还是需要线程锁的。因为通常使用线程锁来实现线程同步和通信。在单核机器上的多线程程序中,仍然存在线程同步的问题5请问线程间的同步方法,最好是具体的系统调用。同步。它只取自然值,只支持两种操作:P(SV):如果信号量SV大于0,则减1;如果SV值为0,则挂起线程。V(SV):如果其他进程因为等待SV而挂起,唤醒然后将SV加1;否则,直接将SV加1。其系统调用为:sem_wait(sem_t*sem):在原子操作中将信号量减1。如果信号量值为0,则sem_wait将被阻塞,直到信号量具有非零值。sem_post(sem_t*sem):+1带有原子操作的信号量值。当信号量大于0时,其他正在调用sem_wait等待信号量的线程会被唤醒。Mutex互斥量又称互斥锁,主要用于线程的互斥,不能保证顺序访问,可以用条件锁同步。进入临界区时,需要获取互斥量并加锁;当离开临界区时,需要解锁互斥体来唤醒其他等待互斥体的线程。它的主要系统调用如下:pthread_mutex_init:初始化互斥量pthread_mutex_destroy:销毁互斥量pthread_mutex_lock:在原子操作中锁定一个互斥量。如果目标互斥量已被锁定,则pthread_mutex_lock调用将阻塞,直到互斥量的所有者将其解锁。pthread_mutex_unlock:在原子操作中解锁互斥量。条件变量条件变量,也称为条件锁,用于同步线程间共享数据的值。条件变量提供了一种线程间通信机制:当共享数据达到一定值时,唤醒一个/多个等待共享数据的线程。即当一个共享变量等于某个值时,调用signal/broadcast。这时候操作共享变量就需要加锁了。其主要系统调用如下:pthread_cond_init:初始化条件变量pthread_cond_destroy:销毁条件变量pthread_cond_signal:唤醒一个等待目标条件变量的线程。唤醒哪个线程取决于调度策略和优先级。pthread_cond_wait:等待目标条件变量。需要一个锁定的互斥量来确保操作的原子性。在这个函数中,在进入等待状态前先解锁,收到信号后会再次加锁,以保证线程可以正确访问共享资源。6游戏服务器应该为每个用户创建一个线程还是一个进程,为什么?游戏服务器应该为每个用户创建一个进程。因为同一个进程中的线程会相互影响,一个线程的死亡会影响到其他线程,导致进程崩溃。原因):并不是所有的硬件平台都可以访问任意地址的任意数据;有些硬件平台只能在特定地址获取特定类型的数据,否则会抛出硬件异常。2)性能原因:数据结构(尤其是栈)应该尽可能在自然边界上对齐。原因是为了访问未对齐的内存,处理器需要进行两次内存访问;而对齐的内存访问只需要一次访问。2.规则:1)数据成员的对齐规则:对于结构体(struct)(或union)的数据成员,第一个数据成员放在偏移量为0的地方,每个数据成员的对齐遵循#pragmapack的指定值和数据成员本身的长度,以较小者为准。2)结构体(或联合体)的整体对齐规则:数据成员完成各自的对齐后,结构体(或联合体)本身也必须进行对齐,并按照#pragma指定的值进行对齐pack和结构(或联合)的最大数据成员长度其中,较小的进行。3)结构体作为成员:如果一个结构体中有一些结构体成员,则结构体成员应该从结构体内部最大元素大小的整数倍的地址开始存储。3.定义结构对齐:可以通过预编译命令#pragmapack(n)来改变这个系数,n=1,2,4,8,16,其中n是指定的“对齐系数”。8请回答静态变量何时被初始化。静态变量存放在虚拟地址空间的data段和bss段。在C语言中,它们在代码执行前被初始化,属于编译期初始化。在C++中,由于引入了对象,对象的生成必须调用构造函数,所以C++规定,当且仅当第一次使用对象时,才构造全局或局部静态对象。9请说说用户态和内核态的区别。操作系统的两个运行级别,两者最大的区别就是特权级别不同。用户模式的特权级别最低,内核模式的特权级别较高。运行在用户态的程序不能直接访问操作系统内核数据结构和程序。内核态和用户态的转换方式主要有:系统调用、异常和中断10服务器如何设计,使其可以接收多个客户端的请求多线程、线程池、io多路复用11无限循环+新建线程当connecting方法的效率有点低,如何改进呢?提前创建线程池,使用生产者消费者模型创建任务队列。队列用作关键资源。当有新的连接时,它挂在任务队列上。当队列为空时,所有线程都会休眠。改进死循环:使用selectepoll等技巧12如何唤醒阻塞的socket线程?13如何判断当前线程是忙还是阻塞?使用ps命令查看14处于就绪状态的进程在等待什么?如果调度两个进程使用CPU的运行权15来访问临界区资源,是否都会获得自旋锁?启用抢占的单核CPU可能会导致这种情况。16你知道windows的消息机制吗?请告诉我,当用户操作(鼠标,键盘等)时,系统会将这些时间转换为消息。系统为每个打开的进程维护一个消息队列。系统会将这些消息放入进程的消息队列中,应用程序循环从消息队列中取出消息,完成相应的操作。17浅谈C++你用的是什么锁?使用互斥量和条件变量可以很容易地解决生产者-消费者问题。这里的条件变量起到了替代信号量的作用。18请告诉我有关C++内存溢出和内存泄漏的信息1.内存溢出指示器当程序请求内存时,没有足够的内存供请求者使用。内存溢出就是你想要的内存空间超过了系统实际分配给你的空间。这时候系统就相当于不能满足你的需求,就会报内存溢出的错误。内存溢出的原因:加载到内存中的数据量太大,如果有集合类中的对象的引用一次从数据库中取了太多的数据,用完后没有清除,这样就出现了是代码中的无限循环或循环生成太多重复的对象实体。实体使用的第三方软件中的BUG启动参数内存值设置得太小2.内存泄漏内存泄漏是指由于疏忽或错误导致程序未能释放不再使用的内存的情况。内存泄漏并不是指内存在物理上消失,而是指应用程序分配了某段内存后,由于设计错误导致失去了对该内存段的控制,从而造成内存的浪费。内存泄漏的分类:1.堆泄漏。内存是指程序运行时根据需要通过malloc、reallocnew等从堆中分配的一块内存,完成后必须调用相应的free或delete来删除。如果程序的设计错误导致这部分内存没有被释放,那么之后这块内存就不会被使用,就会出现HeapLeak。2.系统资源泄漏(ResourceLeak)。主要是指程序使用了系统分配的资源,如Bitmap、handle、SOCKET等,却没有使用相应的函数释放它们,造成系统资源的浪费,会严重降低系统性能并导致系统不稳定。3.基类的析构函数没有定义为虚函数。当基类指针指向子类对象时,如果基类的析构函数不是virtual,那么子类的析构函数就不会被调用,子类的资源就得不到正确的释放,从而造成内存泄漏。19你能谈谈协程吗?1.概念:协程,又称微线程、纤程,英文名Coroutine。协程看起来像一个子程序,但是在执行过程中,可以在子程序内部中断,然后切换到执行其他子程序,然后在适当的时候返回继续执行。2)协程和线程的区别,协程最大的优势就是协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自己控制的,所以没有线程切换的开销。与多线程相比,线程越多,协程的性能优势越明显。第二大优点是不需要多线程的锁机制,因为只有一个线程,同时写变量不存在冲突。在协程中,对共享资源进行无锁控制,只需要判断状态即可,因此执行效率比很多线程高很多。3)协程使用的其他多核CPU呢——多进程+协程,既充分利用了多核,又充分发挥了协程的高效性,可以获得极高的性能。Python对协程的支持还是很有限的,生成器中使用的yield可以在一定程度上实现协程。虽然支撑还不完整,但已经可以发挥出不小的威力了。20你能告诉我僵尸进程吗?1)普通进程正常情况下,子进程由父进程创建,子进程再创建新进程。2)孤儿进程一个父进程退出,而它的一个或多个子进程还在运行,那么这些子进程就会成为孤儿进程。孤儿进程会被init进程(进程号为1)收养,init进程会为他们完成状态收集工作。3)僵尸进程一个进程使用fork创建一个子进程。如果子进程退出,父进程没有调用wait或者waitpid获取了子进程的状态信息,那么系统中仍然保存着子进程的进程描述符。这样的进程称为僵尸进程。外部淘汰:通过kill发送SIGTERM或SIGKILL信号,淘汰产生僵尸进程的进程,其产生的僵尸进程成为孤儿进程。这些孤儿进程会被init进程接管,init进程会wait()这些孤儿进程并释放它们被占用的系统进程表中的资源,内部解决:1、子进程退出时,发送SIGCHILD向父进程发送信号,父进程处理SIGCHILD信号。在信号处理函数中调用wait来处理僵尸进程。2.fork两次,原理是让子进程成为孤儿进程,使其父进程成为init进程,僵尸进程可以通过init进程进行处理。21请介绍5种IO模型1.阻塞IO:调用者调用一个函数,等待函数返回,期间什么都不做,一直检查函数是否返回,必须等待函数返回2.非-阻塞IO:非阻塞等待,每隔一段时间检查IO事件是否就绪。没有准备好就去做其他的事情。3.Signal-drivenIO:信号驱动IO:Linux使用sockets进行信号驱动IO,安装一个信号处理函数,进程持续运行,不会阻塞。当IO时间就绪时,进程收到SIGIO信号。然后处理IO事件。4.IOmultiplexing/多路复用IO:Linux使用select/poll函数来实现IO多路复用模型。这两个函数也会阻塞进程,但是和阻塞IO不同的是这两个函数可以同时阻塞多个进程。一个IO操作。而且可以同时检测多个读操作和写操作的IO函数。知道有数据可读或可写,真正调用IO操作函数。5、异步IO:在linux中可以调用aio_read函数告诉内核描述字缓冲区指针和缓冲区大小,文件偏移量和通知方式,然后立即返回,内核将数据复制到缓冲区后通知应用程序.22当服务器正在监听端口,但还没有客户端连接时,进程的状态是什么?这取决于服务器的编程模型。如果像上一个问题的回答中描述的那样,就是处于阻塞状态。如果epoll、select等用于io多路复用,则处于运行状态。23C++如何实现线程池?设置一个producerconsumerqueue,作为criticalresource24Linux下如何获取一个文件的100到200行sed-n'100,200p'inputfileawk'NR>=100&&NR<=200{print}'inputfilehead-200inputfile|tail-10025请说说awk的使用1)作用:风格扫描和处理语言。它允许创建读取输入文件、排序数据、处理数据、对输入执行计算、生成报告以及无数其他功能的短程序。2)Usage:awk[-Ffield-separator]'commands'input-file(s)3)内置变量ARGC命令行参数个数ARGV命令行参数排列ENVIRON支持队列中的系统环境变量FILENAMEFNR浏览的文件名浏览文件中的记录数FS设置输入字段分隔符,相当于命令行-F选项NF浏览记录中的字段数NR读取记录数OFS输出字段分隔符ORS输出记录分隔符RS控制记录分隔符觉得文章还不错的话记得“点赞关注”关注我的微信公众号【超时猿】可以获得更多内容