常见的笔试面试题(概念性的:死锁,进程通信方式,指向字符变量的指针,文件索引结构,可被重载的运算符)

1. 死锁产生的原因及四个必要条件
产生死锁的原因主要是
(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则
就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
产生死锁的四个必要条件
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之
一不满足,就不会发生死锁。
死锁的解除与预防
理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和
解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确
定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态
的情况下占用资源。因此,对资源的分配要给予合理的规划。
 

2. 进程的通信方式
       (1)管道(Pipe):
管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。
  (2)命名管道(named pipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。
  (3)信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数)。
  (4)消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺
  (5)共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
  (6)内存映射(mapped memory):内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。
  (7)信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
  (8)套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。

 

3. char * const p      char const * p      const char *p 上述三个有什么区别? 
    char * const p; p为指向字符变量的指针,地址不变,地址内容可变
    const char *p;p为指向字符变量的指针,地址可变,地址内容不变
   char const *p; 与 const char *p; 等价

 

4. 文件索引结构

       为了提高文件的检索效率,可以采用索引方法组织文件。

(1)采用索引这种结构,逻辑上连续的文件可以存放在若干不连续的物理块中

(2)但对于每个文件,在存储介质中除存储文件本身外,还要求系统另外建立一张索引表索引表记录了文件信息所在的逻辑块号

          和与之对应的物理块号。索引表也以文件的形式存储在存储介质中,索引表的物理地址则由文件说明信息项给出                

(3)在很多情况下,有的文件很大,文件索引表也就较大。如果索引表的大小超过了一个物理块,可以采用间接索引(多重索引)

          ,也就是在索引表所指的物理块中存放的不是文件信息,而是装有这些信息的物理块地址。这样,如果一个物理块可装下n个物理

          块地址,则经过一级间接索引,可寻址的文件长度将变为n×n块。如果文件长度还大于n×n块,还可以进行类似的扩充,即二级间

         接索引。       

 (4)不过,大多数文件不需要进行多重索引,也就是说,这些文件所占用的物理块的所有块号可以放在一个物理块内。如果对这些文

            件也采用多重索引,则显然会降低文件的存取速度。因此,在实际系统中,总是把索引表的头几项设计成直接寻址方式,也

           就是这几项所指的物理块中存放的是文件信息;而索引表的后几项设计成多重索引,也就是间接寻址方式。在文件较短时,就

           可利用直接寻址方式找到物理块号而节省存取时间。

(5)索引结构既适用于顺序存取,也适用于随机存取,并且访问速度快,文件长度可以动态变化索引结构的缺点是由于使用了

         索引表而增加了存储空间的开销。另外,在存取文件时需要至少访问存储器两次以上,其中,一次是访问索引表,另一次是根据

         索引表提供的物理块号访问文件信息。

(6)由于文件在存储设备的访问速度较慢,因此,如果把索引表放在存储设备上,势必大大降低文件的存取速度。一改进的

          方法当对某个文件进行操作之前,系统预先把索引表放入内存,这样,文件的存取就可直接在内存通过索引表确定物理地

          块号,而访问存储设备的动作只需要一次。当文件被打开时,为提高访问速度将索引表读入内存,故又需要占用额外的内存空间。

5. 哪些运算符可以被重载,哪些不能

   几乎所有的运算符都可用作重载。具体包含:
    算术运算符:+,-,*,/,%,++,--;
    位操作运算符:&,|,~,^,<<,>>
    逻辑运算符:!,&&,||;
    比较运算符:<,>,>=,<=,==,!=;
    赋值运算符:=,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=;
    其他运算符:[],(),->,,(逗号运算符),new,delete,new[],delete[],->*。

    下列运算符不允许重载:
    . , .* , :: , ?:,sizeof

 

6. #pragma pack(2)

    程序编译器对结构的存储的特殊处理确实提高CPU存储 变量 的速度,但是有时候也带来了一些麻烦,我们也屏蔽掉变
    量默认的对齐方式,自己可以设定变量的对齐方式。 编译器中提供了 #pragma pack(n)来设定 变量 以n 字节对齐 方式。
 
#pragma pack规定的对齐长度,实际使用的规则是:
结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。也就是说,当#pragma pack的值等于或超过所有数据成员长度的时候,这个值的大小将不产生任何效果。
结构整体的对齐,则按照结构体中最大的数据成员 和 #pragma pack指定值 之间,较小的那个进行
 
下面举例说明其用法。
#pragma pack(push) //保存对齐状态
#pragma pack(4)//设定为4字节对齐
struct test
{
   char m1;
   double m4;
   int m3;
};
#pragma pack(pop)//恢复对齐状态

以上 结构体 的大小为16,
首先为m1分配空间,其 偏移量 为0,满足我们自己设定的对齐方式(4 字节对齐 ),m1大小为1个字节。
接着为m4分配空间,这时其 偏移量 为4,需要补足3个字节,这样使偏移量满足为n=4的倍数(因为sizeof(double)大于4),m4占用8个字节。
接着为m3分配空间,这时其 偏移量 为12,满足为4的倍数,m3占用4个字节。这时已经为所有 成员变量 分配了空间,共分配了16个字节,满足为n的倍数。
如果把上面的 #pragma pack(4)改为 #pragma pack(8),那么我们可以得到结构的大小为24。

 

 

 

 

 

你可能感兴趣的:(常见的笔试面试题(概念性的:死锁,进程通信方式,指向字符变量的指针,文件索引结构,可被重载的运算符))