51、对称加密算法和非对称加密算法
- 对称加密算法
对称加密才用了对称密码编码技术,它的特点是文件加密和解密使用相同的密钥,即加密密钥也可以用解密密钥,这就是对称加密算法,常见的有:DES、IDEA。 - 非对称加密算法
非对称加密算法需要两个密钥:公开密钥和私有密钥,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;反之,则用对应的公开密钥解密。非对称加密不适合对文件加密,只适合对少量数据进行加密,典型的应用是数字签名。
52、volatile关键字的作用
volatile变量是随时可能发生变化的,它告诉编译器,与volatile变量有关的运算,不要进行任何优化,每次读取volatile变量时都重新从内存读取。
53、c++中动态联编和静态联编
静态联编说的是在编译时就已经确定好了调用和被调用两者的关系;
动态联编说的是程序在运行时才确定调用者和被调用者的关系,典型的应用是虚函数实现的多态性。
54、深拷贝和浅拷贝
浅拷贝是指将对象内的数据完全一致的复制;
深拷贝不是这样,它可以将内部的数据按照需要用特殊的方法拷贝,比如说对象内部有一个动态数组,浅拷贝只拷贝指针,而深拷贝则重新申请空间将数据复制过来。
55、什么是柔性数组?
数组大小待定的数组就是柔性数组。
一般结构体的最后一个元素可以是大小未知的数组。
56、库函数和系统调用的区别?
库函数调用时面向应用开发的,与系统无关,移植性好。
系统调用是面向底层,偏向硬件,系统内核软中断实现,移植性差,系统调用是用户程序和内核交互的接口,系统调用的过程如下:
- 执行用户程序
- 根据glibc的函数实现,取得系统调用号,并执行int$0x80产生中断
- 进行地址空间的转换和堆栈的切换,执行SAVE _ALL(进入内核模式)
- 进行中断处理,根据系统调用表调用内核函数
- 执行内核函数
- 执行RESTORE_ALL并返回用户模式
系统调用比库函数调用快。
57、构造函数里面”初始化列表”和”赋值”的区别
对于内置类型来说,没有区别,对于非内置类型则有区别,如下:
初始化列表只会调用一次构造函数,而赋值会先调用构造,再调用一次赋值函数,什么情况下只能使用初始化列表:
- 没有默认构造函数的类;
- 类中存在const成员或者引用类型的成员(它们只能被初始化);
58、为什么要字节对齐?
自然对齐:一个变量的内存正好是它长度的整数倍。
需要字节对齐的根本原因在于CPU的效率问题,假设32位机器上int型变量地址是0x00000002,那么CPU取值时需要访问两次内存,一次是0x00000002-0x00000003的short,然后是0x00000004-0x00000005的short,而如果该int型变量的地址是0x00000003,那么CPU则要访问3次内存,即char-short-char,而如果变量是自然对齐的,则CPU访问一次内存就够了。
struct stu
{
char sex;
int length;
char name[10];
};
sizeof(struct stu) = 20;//结构体中每个数据类型都要对齐
什么情况下需要手动设置对齐:
1. 设计不同CPU下的通信协议(设计一个结构体,32位和64位都用时)
2. 编写硬件驱动程序时寄存器的结构
手动设置对齐方式有两种:
1. 代码里添加预编译标识
#pragma pack(n)
#pragma pack()
2. GNU编译时
#define GNUC_PACKED__attribut__((packed))
59、浅谈僵尸进程
僵尸进程:当子进程退出时,父进程没有调用wait函数或者waitpid()函数等待子进程结束,又没有显式忽略SIGCHLD信号,那么它将一直保持在僵尸状态,如果这时父进程结束了,init进程会自动接收这个子进程,为它收尸,但如果父进程是一个循环,不会结束,那么子进程就会一直保持僵死状态。
进程状态:
僵尸|休眠|不可中断的休眠|运行|停止式跟踪
Z |S |D |R |T
补救办法:杀死僵尸进程的父进程,让init进程来接手,清理掉子进程这个僵尸进程。
僵尸进程的状态:一个进程在调用exit()函数结束时,并没有真正的被销毁,而是留下一个称为僵尸进程的数据结构,僵尸进程放弃了几乎所有的内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保持一个位置,记载该进程的退出状态等信息。
避免僵尸进程的方法:
- 使用signal函数忽略SIGCHLD信号
- 调用wait或者waitpid()函数
- fork两次,父进程fork子进程后继续执行,子进程fork一个孙进程后退出,此时孙进程会被init进程接管,避免僵尸进程,当然子进程的退出还是要进行处理的。
60、fork函数浅析
pid_t fork();
返回值:若成功调用一次则返回两个值,子进程返回0,父进程返回子进程的进程id,否则,出错返回-1.
子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。
注意:子进程拥有的是副本,它跟父进程之间是不共享这些存储空间(但是共享代码段)的,因此子进程拥有独立的地址空间。
fork可能出错的原因:
- 当前进程数量已经达到了系统规定的上限;
- 系统内存不足;