苏州企业网站设计方案做商务楼房型图网站
- 作者: 五速梦信息网
- 时间: 2026年04月20日 08:26
当前位置: 首页 > news >正文
苏州企业网站设计方案,做商务楼房型图网站,织梦网站搬迁,某企业网站建设方案1、请你介绍一下死锁#xff0c;产生的必要条件#xff0c;产生的原因#xff0c;怎么预防死锁
1、死锁
两个或两个以上的进程在执行过程中#xff0c;因争夺共享资源而造成的一种互相等待的现象#xff0c;若无外力作用#xff0c;它们都将无法推进下去。此时称系统处…1、请你介绍一下死锁产生的必要条件产生的原因怎么预防死锁
1、死锁
两个或两个以上的进程在执行过程中因争夺共享资源而造成的一种互相等待的现象若无外力作用它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁。这些永远在互相等待的进程称为死锁进程。
2、产生死锁的必要条件
互斥条件指进程对所分配到的资源进行排它性使用即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源则请求者只能等待直至占有资源的进程用毕释放请求和保持条件指进程已经保持至少一个资源但又提出了新的资源请求而该资源已被其它进程占有此时请求进程阻塞但又对自己已获得的其它资源保持不放不剥夺条件指进程已获得的资源在未使用完之前不能被剥夺只能在使用完时由自己释放循环等待条件指在发生死锁时必然存在一个进程——资源的环形链即进程集合 {P0P1P2···Pn} 中的 P0 正在等待一个 P1 占用的资源P1 正在等待 P2 占用的资源……Pn 正在等待已被 P0 占用的资源。
**3、产生死锁的原因 **
竞争资源进程间推进顺序非法
4、预防死锁
有序资源分配法银行家算法
2、说一说进程通信的方式有哪些
进程间通信主要包括管道、命名管道、信号、消息队列、共享内存、内存映射、信号量、Socket。 1、管道 管道也叫无名匿名管道它是是 UNIX 系统 IPC进程间通信的最古老形式所有的 UNIX 系统都支持这种通信机制。管道本质其实是内核中维护的一块内存缓冲区Linux 系统中通过 pipe() 函数创建管道会生成两个文件描述符分别对应管道的读端和写端。无名管道只能用于具有亲缘关系的进程间的通信。 2、命名管道 匿名管道由于没有名字只能用于亲缘关系的进程间通信。为了克服这个缺点提出了有名管道FIFO也叫命名管道、FIFO文件。有名管道FIFO不同于匿名管道之处在于它提供了一个路径名与之关联以 FIFO 的文件形式存在于文件系统中并且其打开方式与打开一个普通文件是一样的这样即使与 FIFO 的创建进程不存在亲缘关系的进程只要可以访问该路径就能够彼此通过 FIFO 相互通信因此通过 FIFO 不相关的进程也能交换数据。 3、信号 信号是 Linux 进程间通信的最古老的方式之一是事件发生时对进程的通知机制有时也称之为软件中断它是在软件层次上对中断机制的一种模拟是一种异步通信的方式。信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断转而处理某一个突发事件。 4、消息队列 消息队列就是一个消息的链表可以把消息看作一个记录具有特定的格式以及特定的优先级对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息对消息队列有读权限的进程则可以从消息队列中读走消息消息队列是随内核持续的。 5、共享内存 共享内存允许两个或者多个进程共享物理内存的同一块区域通常被称为段。由于一个共享内存段会称为一个进程用户空间的一部分因此这种 IPC 机制无需内核介入。所有需要做的就是让一个进程将数据复制进共享内存中并且这部分数据会对其他所有共享同一个段的进程可用。与管道等要求发送进程将数据从用户空间的缓冲区复制进内核内存和接收进程将数据从内核内存复制进用户空间的缓冲区的做法相比这种 IPC 技术的速度更快。 6、内存映射 内存映射Memory-mapped I/O是将磁盘文件的数据映射到内存用户通过修改内存就能修改磁盘文件。 7、信号量 信号量主要用来解决进程和线程间并发执行时的同步问题进程同步是并发进程为了完成共同任务采用某个条件来协调它们的活动。对信号量的操作分为 P 操作和 V 操作P 操作是将信号量的值减 1V 操作是将信号量的值加 1。当信号量的值小于等于 0 之后再进行 P 操作时当前进程或线程会被阻塞直到另一个进程或线程执行了 V 操作将信号量的值增加到大于 0 之时。 8、Socket套接字 套接字Socket就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端提供了应用层进程利用网络协议交换数据的机制。Socket 一般用于网络中不同主机上的进程之间的通信。
3、请你说说进程和线程的区别
地址空间、开销、并发性、内存
进程有独立的地址空间线程有自己的堆栈和局部变量但线程之间没有单独的地址空间进程和线程切换时需要切换进程和线程的上下文进程的上下文切换时间开销远远大于线程上下文切换时间耗费资源较大效率要差一些进程的并发性较低线程的并发性较高每个独立的进程有一个程序运行的入口、顺序执行序列和程序的出口但是线程不能够独立执行必须依存在应用程序中由应用程序提供多个线程执行控制系统在运行的时候会为每个进程分配不同的内存空间而对线程而言除了 CPU 外系统不会为线程分配内存线程所使用的资源来自其所属进程的资源线程组之间只能共享资源一个进程崩溃后在保护模式下不会对其他进程产生影响但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。
4、说一说 epoll 的原理
调用 epoll_create() 会在内核中创建一个 eventpoll 结构体数据称之为 epoll 对象在这个结构体中有 2 个比较重要的数据成员一个是需要检测的文件描述符的信息 struct_root rbr红黑树还有一个是就绪列表struct list_head rdlist存放检测到数据发送改变的文件描述符信息双向链表调用 epoll_ctrl() 可以向 epoll 对象中添加、删除、修改要监听的文件描述符及事件调用 epoll_wt() 可以让内核去检测就绪的事件并将就绪的事件放到就绪列表中并返回通过返回的事件数组做进一步的事件处理。
工作模式
LT 模式水平触发 LTLevel - Triggered是缺省的工作方式并且同时支持 Block 和 Nonblock Socket。在这种做法中内核检测到一个文件描述符就绪了然后可以对这个就绪的 fd 进行 IO 操作如果不作任何操作内核还是会继续通知。ET 模式边沿触发 ETEdge - Triggered是高速工作方式只支持 Nonblock socket。在这种模式下当描述符从未就绪变为就绪时内核通过 epoll 检测到。然后它会假设你知道文件描述符已经就绪并且不会再为那个文件描述符发送更多的就绪通知直到你做了某些操作导致那个文件描述符不再为就绪状态了。但是请注意如果一直不对这个 fd 进行 IO 操作从而导致它再次变成未就绪内核不会发送更多的通知only once。 ET 模式在很大程度上减少了 epoll 事件被重复触发的次数因此效率要比 LT 模式高。epoll 工作在 ET 模式的时候必须使用非阻塞套接口以避免由于一个文件描述符的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。
5、说一说常用的Linux命令
cd切换当前目录ls查看当前文件与目录grep通常与管道命令一起使用用于对一些命令的输出进行筛选加工cp复制文件或文件夹mv移动文件或文件夹rm删除文件或文件夹ps查看进程情况kill向进程发送信号tar对文件进行打包cat查看文件内容top查看操作系统的信息如进程、CPU占用率、内存信息等实时free查看内存使用情况pwd显示当前工作目录Linux环境知道文件名称但是不知道存放路径在哪find / -name “jenkins.xml”
6、说一说进程有多少种状态如何转换
创建、就绪、执行、阻塞、终止
创建一个进程启动首先进入创建状态需要获取系统资源创建进程管理块PCBProcess Control Block完成资源分配。就绪状态在创建状态完成之后进程已经准备好处于就绪状态但是还未获得处理器资源无法运行运行状态获取处理器资源被系统调度当具有时间片开始进入运行状态。如果进程的时间片用完了就进入就绪状态阻塞状态在运行状态期间如果进行了阻塞的操作此时进程暂时无法操作就进入到了阻塞状态在这些操作完成后就进入就绪状态。等待再次获取处理器资源被系统调度当具有时间片就进入运行状态终止状态进程结束或者被系统终止进入终止状态
7、说一说 select 的原理以及缺点
fd_set、select、用户态和内核态切换及数据拷贝、支持的文件描述符数为1024、遍历 1、原理
首先要构造一个关于文件描述符的列表将要监听的文件描述符添加到该列表中这个文件描述符的列表数据类型为 fd_set它是一个整型数组总共是 1024 个比特位每一个比特位代表一个文件描述符的状态。比如当需要 select 检测时这一位为 0 就表示不检测对应的文件描述符的事件为 1 表示检测对应的文件描述符的事件调用 select() 系统调用监听该列表中的文件描述符的事件这个函数是阻塞的直到这些描述符中的一个或者多个进行 I/O 操作时该函数才返回并修改文件描述符的列表中对应的值0 表示没有检测到该事件1 表示检测到该事件。函数对文件描述符的检测的操作是由内核完成的。select() 返回时会告诉进程有多少描述符要进行 I/O 操作接下来遍历文件描述符的列表进行 I/O 操作。
2、缺点
每次调用select都需要把 fd 集合从用户态拷贝到内核态这个开销在 fd 很多时会很大同时每次调用 select 都需要在内核遍历传递进来的所有 fd这个开销在 fd 很多时也很大select 支持的文件描述符数量太小了默认是 1024由 fd_set 决定文件描述符集合不能重用因为内核每次检测到事件都会修改所以每次都需要重置每次 select 返回后只能知道有几个 fd 发生了事件但是具体哪几个还需要遍历文件描述符集合进一步判断
8、请你介绍一下 I/O 多路复用
I/O 多路复用是一种使得程序能同时监听多个文件描述符的技术从而提高程序的性能。I/O 多路复用能够在单个线程中通过监视多个 I/O 流的状态来同时管理多个 I/O 流一旦检测到某个文件描述符上我们关心的事件发生就绪能够通知程序进行相应的处理读写操作。 Linux 下实现 I/O 复用的系统调用主要有 select、poll 和 epoll。 poll 的原理和 select 类似poll 支持的文件描述符没有限制。
9、请你说说 new 的实现原理new 和 malloc 的区别
1、new 的实现原理
如果是简单类型则直接调用 operator new()在 operator new() 函数中会调用 malloc() 函数如果调用 malloc() 失败会调用 _callnewh()如果 _callnewh() 返回 0 则抛出 bac_alloc 异常返回非零则继续分配内存。 如果是复杂类型先调用 operator new()函数然后在分配的内存上调用构造函数。
2、new 和 malloc 的区别
new 是操作符而 malloc 是函数使用 new 操作符申请内存分配时无须指定内存块的大小编译器会根据类型信息自行计算而 malloc 则需要显式地指出所需内存的尺寸new 分配失败的时候会直接抛出异常malloc 分配失败会返回 NULL对于非简单类型new 在分配内存后会调用构造函数而 malloc 不会new 分配成功后会返回对应类型的指针而 malloc 分配成功后会返回 void * 类型new 可以被重载而 malloc 不能被重载使用 malloc 分配的内存后如果在使用过程中发现内存不足可以使用 realloc 函数进行内存重新分配实现内存的扩充new 没有这样直观的配套设施来扩充内存
10、堆和栈的区别
管理方式 对于栈来讲是由编译器自动管理无需手动控制对于堆来说分配和释放都是由程序员控制的空间大小 总体来说栈的空间是要小于堆的。堆内存几乎是没有什么限制的但是对于栈来讲一般是有一定的空间大小的碎片问题 对于堆来讲由于分配和释放是由程序员控制的利用new/delete 或 malloc/free频繁的操作势必会造成内存空间的不连续从而造成大量的内存碎片使程序效率降低。对于栈来讲则不会存在这个问题因为栈是先进后出的数据结构在某一数据弹出之前它之前的所有数据都已经弹出生长方向 对于堆来讲生长方向是向上的也就是沿着内存地址增加的方向对于栈来讲它的生长方式是向下的也就是沿着内存地址减小的方向增长分配方式 堆都是动态分配的没有静态分配的堆。栈有两种分配方式静态分配和动态分配静态分配是编译器完成的比如局部变量的分配动态分配由alloca函数进行分配但是栈的动态分配和堆是不同的它的动态分配是由编译器实现的无需我们手工实现分配效率 栈是机器系统提供的数据结构计算机会在底层对栈提供支持分配专门的寄存器存放栈的地址压栈出栈都有专门的指令执行这就决定了栈的效率很高。堆则是 C/C 函数提供的它的机制是很复杂的例如为了分配一块内存库函数会按照一定的算法在堆内存中搜索可用的足够大小的空间如果没有足够大小的空间可能是由于碎片太多就有可能调用系统功能去增加程序数据段的内存空间这样就有机会分到足够大小的内存然后进行返回。显然堆的效率要比栈低的多。
11、请你说说线程和协程的区别
线程是操作系统的资源线程的创建、切换、停止等都非常消耗资源而创建协程不需要调用操作系统的功能编程语言自身就能完成所以协程也被称为用户态线程协程比线程轻量很多线程在多核环境下是能做到真正意义上的并行而协程是为并发而产生的一个具有多个线程的程序可以同时运行几个线程而协同程序却需要彼此协作的运行线程进程都是同步机制而协程则是异步线程是抢占式而协程是非抢占式的所以需要用户自己释放使用权来切换到其他协程因此同一时间其实只有一个协程拥有运行权相当于单线程的能力操作系统对于线程开辟数量限制在千的级别而协程可以达到上万的级别。
12、简述一下 GDB 常见的调试命令
启动和退出gdb 可执行程序 quit/q给程序设置参数/获取设置参数set args 10 20 show argsGDB使用帮助help查看当前文件代码list/l 从默认位置显示list/l 行号 从指定的行显示list/l 函数名从指定的函数显示查看非当前文件代码list/l 文件名:行号 list/l 文件名:函数名 设置显示的行数show list/listsize set list/listsize 行数设置断点b/break 行号 b/break 函数名 b/break 文件名:行号 b/break 文件名:函数查看断点i/info b/break删除断点d/del/delete 断点编号设置断点无效dis/disable 断点编号设置断点生效ena/enable 断点编号设置条件断点一般用在循环的位置 b/break 10 if i5运行GDB程序start程序停在第一行 run遇到断点才停继续运行到下一个断点停c/continue向下执行一行代码不会进入函数体n/next变量操作p/print 变量名打印变量值 ptype 变量名打印变量类型向下单步调试遇到函数进入函数体s/step finish跳出函数体自动变量操作display 变量名自动打印指定变量的值 i/info display undisplay 编号查看 follow-fork-mode mode 选项的值show follow-fork-mode查看 detach-on-fork 选项的值show detach-on-fork设置 follow-fork-mode mode 选项的值set follow-fork-mode [parent \ child]设置 detach-on-fork 选项的值set detach-on-fork [on \ off]查看当前调试环境中有多少个进程info inferiors切换到指定 ID 编号的进程对其进行调试inferior idset var 变量名变量值 循环中用的较多 until 跳出循环
13、请你说说 delete 和 free 的区别
delete 是操作符而 free 是函数delete 用于释放 new 分配的空间free 有用释放 malloc 分配的空间free 会不会调用对象的析构函数而 delete 会调用对象的析构函数调用 free 之前需要检查要释放的指针是否为 NULL使用 delete 释放内存则不需要检查指针是否为 NULL
14、说一说进程调度算法有哪些
先来先服务FCFS调度算法 先来先去服务调度算法是一种最简单的调度算法也称为先进先出或严格排队方案。每次调度都是从后备作业进程队列中选择一个或多个最先进入该队列的作业进程将它们调入内存为它们分配资源、创建进程当每个进程就绪后它加入就绪队列。当前正运行的进程停止执行选择在就绪队列中存在时间最长的进程运行。短作业优先SJF调度算法 短作业优先SJF的调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业进程将它们调入内存运行短进程优先SPF调度算法从就绪队列中选择一个估计运行时间最短的进程将处理机分配给它使之立即执行直到完成或者发生某件事而阻塞时才释放处理机。优先级调度算法 优先级调度算法又称优先权调度算法该算法既可以用于作业调度也可以用于进程调度该算法中的优先级用于描述作业运行的紧迫程度。在作业调度中优先级调度算法每次从后备作业队列中选择优先级最高的一个或几个作业将它们调入内存分配必要的资源创建进程并放入就绪队列在进程调度中优先级调度算法每次从就绪队列中选择优先级最高的进程将处理机分配给它使之投入运行高响应比优先调度算法 高响应比优先调度算法主要用于作业调度该算法是对 FCFS 调度算法和 SJF 调度算法的一种综合平衡同时考虑每个作业的等待时间和估计的运行时间。在每次进行作业调度时先计算后备作业队列中每个作业的响应比从中选出响应比最高的作业投入运行。时间片轮转调度算法 时间片轮转调度算法主要适用于分时系统。每次调度时把 CPU 分配给队首进程并令其执行一个时间片。时间片的大小从几 ms 到几百 ms。当执行的时间片用完时由一个计时器发出时钟中断请求调度程序便据此信号来停止该进程的执行并将它送往就绪队列的末尾然后再把处理机分配给就绪队列中新的队首进程同时也让它执行一个时间片。多级反馈队列调度算法 多级反馈队列调度算法是时间片轮转调度算法和优先级调度算法的综合和发展通过动态调整进程优先级和时间片大小多级反馈队列调度算法可以兼顾多方面的系统目标。
15、说一说什么是内存泄露如何检测
内存泄漏Memory Leak是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放造成系统内存的浪费导致程序运行速度减慢甚至系统崩溃等严重后果。避免内存泄露的方法主要就是要有良好的编码习惯动态开辟内存空间及时释放内存。也可以采用智能指针来避免内存泄露。使用日志记录在代码中添加日志记录跟踪内存分配和释放情况。可以采用静态分析技术、源代码插装技术等进行检测。常见的一些检测工作有LCLink、ccmalloc、Dmalloc、Electric Fence、Leaky、LeakTracer、MEMWATCH、Valgrind、KCachegrind等等。
17、请你说说线程的通信方式
线程间无需特别的手段进行通信因为线程间可以共享一份全局内存区域其中包括初始化数据段、未初始化数据段以及堆内存段等所以线程之间可以方便、快速地共享信息。只需要将数据复制到共享全局或堆变量中即可。不过要考虑线程的同步和互斥应用到的技术有
信号 Linux 中使用 pthread_kill() 函数对线程发信号互斥锁、读写锁、自旋锁 互斥锁确保同一时间只能有一个线程访问共享资源当锁被占用时试图对其加锁的线程都进入阻塞状态释放 CPU 资源使其由运行状态进入等待状态当锁释放时哪个等待线程能获得该锁取决于内核的调度。 读写锁当以写模式加锁而处于写状态时任何试图加锁的线程不论是读或写都阻塞当以读状态模式加锁而处于读状态时“读”线程不阻塞“写”线程阻塞。读模式共享写模式互斥。 自旋锁上锁受阻时线程不阻塞而是在循环中轮询查看能否获得该锁没有线程的切换因而没有切换开销不过对 CPU 的霸占会导致 CPU 资源的浪费。 所以自旋锁适用于并行结构多个处理器或者适用于锁被持有时间短而不希望在线程切换产生开销的情况。条件变量 条件变量可以以原子的方式阻塞进程直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的条件变量始终与互斥锁一起使用信号量 信号量实际上是一个非负的整数计数器用来实现对公共资源的控制。在公共资源增加的时候信号量就增加公共资源减少的时候信号量就减少只有当信号量的值大于0的时候才能访问信号量所代表的公共资源。
18、请你说一说虚拟内存与物理内存
物理内存 以前还没有虚拟内存概念的时候程序寻址用的都是物理地址。程序能寻址的范围是有限的这取决于 CPU 的地址线条数。比如在 32 位平台下寻址的范围是 2^32 也就是 4G。并且这是固定的如果没有虚拟内存且每次开启一个进程都给 4G 物理内存就可能会出现很多问题 - 因为物理内存是有限的当有多个进程要执行的时候都要给 4G 内存很显然内存不够这很快就分配完了于是没有得到分配资源的进程就只能等待。当一个进程执行完了以后再将等待的进程装入内存。这种频繁的装入内存的操作效率很低 - 由于指令都是直接访问物理内存的那么任何进程都可以修改其他进程的数据甚至会修改内核地址空间的数据这是不安全的虚拟内存 由于物理内存有很多问题所以出现了虚拟内存。虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存一个连续完整的地址空间而实际上它通常是被分隔成多个物理内存碎片还有部分暂时存储在外部磁盘存储器上在需要时进行数据交换。虚拟内存的目的是为了让物理内存扩充成更大的逻辑内存让程序获得更多的可用内存。空间独立。由于每个进程都有自己的页表所以每个进程的虚拟内存空间就是相互独立的。进程也没有办法访问其他进程的页表所以这些页表是私有的。这就解决了多进程之间物理地址冲突的问题。可以扩充内存。每个进程拥有自己独立的虚拟地址空间但不需要让进程中所有的页都必须映射到物理内存中当程序引用到不在物理内存中的页时由硬件执行必要的内存映射将缺失的部分装入物理内存并重新执行失败的指令这也使得有限的内存运行大程序成为可能。安全性强。页表里的页表项中除了物理地址之外还有一些标记属性的比特比如控制一个页的读写权限标记该页是否存在等。在内存访问方面操作系统提供了更好的安全性。
19、请你说说分段和分页
分段 将用户程序地址空间分成若干个大小不等的段每段可以定义一组相对完整的逻辑信息。存储分配时以段为单位段与段在内存中可以不相邻接实现了离散分配。分段主要是为了使程序和数据可以被划分为逻辑上独立的地址空间并且有助于共享和保护。分页 用户程序的地址空间被划分成若干固定大小的区域称为“页”相应地内存空间分成若干个物理块页和块的大小相等。可将用户程序的任一页放在内存的任一块中实现了离散分配。分页主要用于实现虚拟内存从而获得更大的地址空间。段页式 页式存储管理能有效地提高内存利用率解决内存碎片而分段存储管理能反映程序的逻辑结构并有利于段的共享。将这两种存储管理方法结合起来就形成了段页式存储管理方式。段页式存储管理方式即先将用户程序分成若干个段再把每个段分成若干个页并为每一个段赋予一个段名。在段页式系统中为了实现从逻辑地址到物理地址的转换系统中需要同时配置段表和页表利用段表和页表进行从用户地址空间到物理内存空间的映射。系统为每一个进程建立一张段表每个分段有一张页表。段表表项中至少包括段号、页表长度和页表始址页表表项中至少包括页号和块号。在进行地址转换时首先通过段表查到页表始址然后通过页表找到页帧号最终形成物理地址。
20、什么是孤儿进程什么是僵尸进程如何解决僵尸进程
孤儿进程是指一个父进程退出后而它的一个或多个子进程还在运行那么这些子进程将成为孤儿进程。孤儿进程将被 init 进程进程号为1所收养并且由 init 进程对它们完整状态收集工作孤儿进程一般不会产生任何危害。僵尸进程 僵尸进程是指一个进程使用 fork() 函数创建子进程如果子进程退出而父进程并没有调用 wt() 或者wtpid() 系统调用取得子进程的终止状态那么子进程的进程描述符仍然保存在系统中占用系统资源这种进程称为僵尸进程。解决僵尸进程 一般为了防止产生僵尸进程在 fork() 子进程之后我们都要及时在父进程中使用 wt() 或者 wtpid() 系统调用等子进程结束后父进程回收子进程 PCB 的资源。 同时当子进程退出的时候内核都会给父进程一个 SIGCHLD 信号所以可以建立一个捕获 SIGCHLD 信号的信号处理函数在函数体中调用 wt() 或 wtpid()就可以清理退出的子进程以达到防止僵尸进程的目的。
21、说一说什么是大端、小端如何判断大端和小端
**字节序 **
大端字节序是指一个整数的最高位字节23 ~ 31 bit存储在内存的低地址处低位字节0 ~ 7 bit存储在内存的高地址处小端字节序是指整数的高位字节存储在内存的高地址处而低位字节则存储在内存的低地址处如何判断大端还是小端
#include stdio.hint main(){union { short value; char bytes[sizeof(short)]; } test;test.value 0x0102;if((test.bytes[0] 1) (test.bytes[1] 2)) {printf(大端字节序\n);}else if((test.bytes[0] 2) (test.bytes[1] 1)){printf(小端字节序\n);}else{printf(未知\n); }return 0;
}22、请你说说共享内存
共享内存是进程间通信的一种方式。不同进程之间共享的内存通常为同一段物理内存进程可以将同一段物理内存连接到他们自己的地址空间中所有的进程都可以访问共享内存中的地址。如果某个进程向共享内存写入数据所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。优点因为所有进程共享同一块内存共享内存在各种进程间通信方式中具有最高的效率。访问共享内存区域和访问进程独有的内存区域一样快并不需要通过系统调用或者其它需要切入内核的过程来完成。同时它也避免了对数据的各种不必要的复制。缺点共享内存没有提供同步机制这使得我们在使用共享内存进行进程之间的通信时往往需要借助其他手段来保证进程之间的同步工作。
23、简述 C 的内存管理
栈在执行函数时函数内局部变量的存储单元都可以在栈上创建函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中效率很高但是分配的内存容量有限堆就是那些由 new分配的内存块他们的释放编译器不去管由我们的应用程序去控制一般一个new就要对应一个 delete。如果程序员没有释放掉那么在程序结束后操作系统会自动回收自由存储区如果说堆是操作系统维护的一块内存那么自由存储区就是C中通过new和delete动态分配和释放对象的抽象概念。需要注意的是自由存储区和堆比较像但不等价。全局/静态存储区全局变量和静态变量被分配到同一块内存中在以前的C语言中全局变量和静态变量又分为初始化的和未初始化的在C里面没有这个区分了它们共同占用同一块内存区在该区定义的变量若没有初始化则会被自动初始化例如int型变量自动初始为0常量存储区这是一块比较特殊的存储区这里面存放的是常量不允许修改代码区存放函数体的二进制代码 24、请你说说写时拷贝
写时拷贝顾名思义就是“写的时候才分配内存空间”这实际上是一种拖延战术。Linux 的 fork() 使用写时拷贝Copy-on-write页实现。写时拷贝是一种可以推迟甚至避免拷贝数据的技术。内核此时并不复制整个进程的地址空间而是让父子进程共享同一个地址空间。只用在需要写入的时候才会复制地址空间从而使各个进行拥有各自的地址空间。也就是说资源的复制是在需要写入的时候才会进行在此之前只有以只读方式共享。这种技术使地址空间上的页的拷贝被推迟到实际发生写入的时候大大提高了效率。
25、请你说说互斥锁和自旋锁
互斥锁也称为互斥量Mutex是一种用来保护临界区的特殊变量 它可以处于锁定locked 状态 也可以处于解锁unlocked 状态如果互斥锁是锁定的 就是某个特定的线程正持有这个互斥锁如果没有线程持有这个互斥锁那么这个互斥锁就处于解锁状态 每个互斥锁内部有一个线程等待队列用来保存等待该互斥锁的线程。当互斥锁处于解锁状态时 如果某个线程试图获取这个互斥锁 那么这个线程就可以得到这个互斥锁而不会阻塞当互斥锁处于锁定状态时 如果某个线程试图获取这个互斥锁 那么这个线程将阻塞在互斥锁的等待队列内。自旋锁与互斥锁类似但它不是通过休眠使进程阻塞而是在获取锁之前一直处于忙等自旋阻塞状态。自旋锁可以用于以下情况锁被持有的时间短而且线程并不希望在重新调度上花费太多的成本。自旋锁最多只能被一个可执行线程持有如果一个执行线程试图获得一个已经被持有的自旋锁那么该线程就会一直进行忙循环 - 旋转 - 等待锁重新可用。
26、简述一下 C 中的内存对齐
现代计算机中内存空间都是按照 字节byte划分的从理论上讲似乎对任何类型的变量的访问可以从任何地址开始但是实际的计算机系统对基本类型数据在内存中存放的位置有限制它们会要求这些数据的首地址的值是某个数 k通常它为4或8的倍数这就是所谓的内存对齐。
内存对齐的原因
平台原因移植原因不是所有的硬件平台都能访问任意地址上的任意数据的。某些硬件平台只能在某些地址处取某些特定类型的数据否则抛出硬件异常。性能原因数据结构尤其是栈应该尽可能地在自然边界上对齐。原因在于为了访问未对齐的内存处理器需要作两次内存访问而对齐的内存访问仅需要一次访问。
** 内存对齐的规则**
每个特定平台上的编译器都有自己的默认“对齐系数”也叫对齐模数。可以通过预编译命令 #pragma pack(n)n 1,2,4,8,16 来改变这一系数。有效对齐值是给定值 #pragma pack(n) 和结构体中最长数据类型长度中较小的那个有效对齐值也叫对齐单位。结构体第一个成员的偏移量offset为0以后每个成员相对于结构体首地址的 offset 都是该成员大小与有效对齐值中较小那个的整数倍如有需要编译器会在成员之间加上填充字节。结构体的总大小为有效对齐值的整数倍如有需要编译器会在最末一个成员之后加上填充字节。
27、请你说说动态库静态库的区别和优缺点
命名方式不同 静态库命名
Linux : libxxx.a lib : 前缀固定 xxx : 库的名字自己起 .a : 后缀固定Windows : libxxx.lib
动态库命名
Linux : libxxx.so lib : 前缀固定 xxx : 库的名字自己起 .so : 后缀固定Windows : libxxx.dll
链接时间和方式不同
静态库的链接是将整个函数库的所有数据在编译时都整合进了目标代码动态库的链接是程序执行到哪个函数链接哪个函数的库
静态库优缺点
-优点 发布程序时无需提供静态库移植方便运行速度相对快些
静态链接生成的可执行文件体积较大消耗内存如果所使用的静态库发生更新改变程序必须重新编译更新麻烦。
动态库优缺点
优点更加节省内存并减少页面交换动态库改变并不影响使用的程序动态函数库升级比较方便缺点发布程序时需要提供动态库
27、请你说说条件变量
条件变量是利用线程间共享的全局变量进行同步的一种机制一个线程等待条件变量的条件成立而挂起另一个线程使条件成立给出条件成立信号。为了防止竞争条件变量的使用总是和一个互斥锁结合在一起。使用条件变量可以以原子方式阻塞线程直到某个特定条件为真为止。条件变量始终与互斥锁一起使用对条件的测试是在互斥锁互斥的保护下进行的。如果条件为假线程通常会基于条件变量阻塞并以原子方式释放等待条件变化的互斥锁。如果另一个线程更改了条件该线程可能会向相关的条件变量发出信号从而使一个或多个等待的线程执行以下操作 唤醒 再次获取互斥锁 重新评估条件
- 上一篇: 苏州企业网站建设制作服务奎屯市网站
- 下一篇: 苏州市城乡和建设局网站免费微网站制作
相关文章
-
苏州企业网站建设制作服务奎屯市网站
苏州企业网站建设制作服务奎屯市网站
- 技术栈
- 2026年04月20日
-
苏州企业网站建设方案永平建设有限公司网站
苏州企业网站建设方案永平建设有限公司网站
- 技术栈
- 2026年04月20日
-
苏州企业商务网站建设品牌定位策略
苏州企业商务网站建设品牌定位策略
- 技术栈
- 2026年04月20日
-
苏州市城乡和建设局网站免费微网站制作
苏州市城乡和建设局网站免费微网站制作
- 技术栈
- 2026年04月20日
-
苏州市建设交易中心网站首页好的国内网站建设公司
苏州市建设交易中心网站首页好的国内网站建设公司
- 技术栈
- 2026年04月20日
-
苏州市网站wordpress 插件 慢
苏州市网站wordpress 插件 慢
- 技术栈
- 2026年04月20日






