1.Unix操作系统允许用户在汇编语言上使用系统调用
Lunix操作系统允许用户在C语言上使用系统调用
2.能加快虚实地址转换的是: 1).增大块表TLB容量 2).让页表常驻内存.
当cpu要访问一个虚拟地址/线性地址时,CPU会首先根据虚拟地址的高20位(20是x86特定的,不同架构有不同的值)在TLB中查找。如果是表中没有相应的表项,称为TLB miss,需要通过访问慢速RAM中的页表计算出相应的物理地址。同时,物理地址被存放在一个TLB表项中,以后对同一线性地址的访问,直接从TLB表项中获取物理地址即可,称为TLB hit。
3.查到的常用同步 进程间的同步机制:信号量 互斥锁 事件 计时器这4种配合等待函数 线程间的同步:volatile变量、interlocked系列函数、SRW读写锁(vista系统及以上)、临界区
4.线程通信:互斥量,信号量,事件,临界区。
进程通信:管道、消息队列、套接字、信号量、信号、共享内存。
5.1).EXT2和EXT3使用索引节点来记录文件信息,索引节点是一个结构,它包含了一个文件的长度、创建及修改时间、权限、所属关系、磁盘中的位置等信息。EXT2并不包含文件的创建时间,EXT3包含。
2)EXT2写入资料会写入缓存中,写满以后再写入硬盘 EXT3会写入缓存中,通知journal,再写入硬盘,再通知journal。(区别:EXT2开机检查有效位,如果错误从硬盘头查错误,EXT3查询journal如果有错误很快就能知道错误在哪。)
3)EXT3支持16TB文件系统和最大2TB文件 EXT4支持1EB和16TB文件.
6.操作系统是什么?
系统观点——计算机资源的管理者
用户观点——用户使用计算机的界面
软件观点——程序和数据结构的集合
7.删除文件不需要删除文件所在的目录,而文件的关联目录项和文件控制块需要随着文件一同删除,同时释放文件的关联缓冲区。
8.
1.先来先服务调度算法(FCFS):就是按照各个作业进入系统的自然次序来调度作业。这种调度算法的优点是实现简单,公平。其缺点是没有考虑到系统中各种资源的综合使用情况,往往使短作业的用户不满意,因为短作业等待处理的时间可能比实际运行时间长得多。 因此选A;
2.短作业优先调度算法 (SPF): 就是优先调度并处理短作业,所谓短是指作业的运行时间短。而在作业未投入运行时,并不能知道它实际的运行时间的长短,因此需要用户在提交作业时同时提交作业运行时间的估计值。
3.最高响应比优先算法(HRN):FCFS可能造成短作业用户不满,SPF可能使得长作业用户不满,于是提出HRN,选择响应比最高的作业运行。响应比=1+作业等待时间/作业处理时间。 因此选C;
4. 基于优先数调度算法(HPF):每一个作业规定一个表示该作业优先级别的整数,当需要将新的作业由输入井调入内存处理时,优先选择优先数最高的作业。
1.
"%5s",表示输出至少5个字符,不够的话,左侧用空格补。
%.5s,最多输出5个字符
unsigned char在32位机的存储范围是0~255 一个字节2的8次方。
2.浮点数不满足加法交换律和结合律。浮点数存在误差,如果直接相减会出现错误
条件0.9f == 0.9 的值为真
条件9 == 0.9*10 的值为真
浮点数存在误差,直接比较大小往往不是预期的结果;通常引入一个比要求精度还要小几个数量级的实数epsilon来帮助比较大小。在我的机器上,精度取1e-8,0.9f == 0.9为假(0.9f是单精度浮点,精度比0.9低)。浮点数不能进行位运算。
3.
int a, b; int c = (a = 2, b = 3, b++); cout << c << endl; //输出3
int a, b; int c = (a = 2, b = 3, b++,a+b); cout << c << endl; //输出6
4.
void f3(int(*p)[4]);
int a[4]={1,2,3,4},
int b[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
f3(&a);
f3(b[1]);
f3(&b[1]);
f3(b);
选项A 数组a是数组首元素地址,加上&表示数组的地址,是可行的,并且有点区别。
选项B和C
b[1]和&b[1]虽然值相等,但是含义不一样,&b[1]是行指针,类型是int (*)[4],和a的类型相同;而b[1]是个int *,和&b[1][0]等价。
5.
下面代码段有哪些安全问题()
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv) {
char cat[] = "cat ";
char *command;
size_t commandLength;
commandLength = strlen(cat) + strlen(argv[1]) + 1;
command = (char *)malloc(commandLength);
strncpy(command, cat, commandLength);
strcat(command, argv[1]);
system(command);
return (0);
}
答案:A B D
分析:字符处理函数strcpy()、strcat()都是不安全的,建议使用strncpy()、strncat(),程序没有对输入合法性进行检查,因此用户可以采用一定手段构造command injection 进行攻击。
6.
int main() {
char ch = -1;
printf(" %02x, %02x", ch, (unsigned char)ch);
return 0;
}
会输出ffffffff ,ff
感觉上面的都没回答到点上;
%x默认输出unsigned int;
所以char会被自动扩展至unsigned int;
因此会扩展符号位;
而unsigned char扩展至unsigned int;
会直接用0填充;
7.在C语言中,函数的隐含存储类别是()
extern(解释)如果在函数定义中没有说明extern或static,则隐含为extern。正确答案是C。
从这道题也可以认识到,以后在C文件中写函数时,假如该函数不是给其他文件调用,要加上static修饰!
8.
int main(void)
{
int i;
for (i = 0; i < 2; i++) {
fork();
printf("-");
}
return 0;
}
所以,上面的那个程序为什么会输入8个“-”,这是因为printf(“-“);语句有buffer,所以,对于上述程序,printf(“-“);把“-”放到了缓存中,并没有真正的输出(参看《C语言的迷题》中的第一题),在fork的时候,缓存被复制到了子进程空间,所以,就多了两个,就成了8个,而不是6个。
另外,多说一下,我们知道,Unix下的设备有“块设备”和“字符设备”的概念,所谓块设备,就是以一块一块的数据存取的设备,字符设备是一次存取一个字符的设备。磁盘、内存都是块设备,字符设备如键盘和串口。块设备一般都有缓存,而字符设备一般都没有缓存。
双条实线框就是多复制了_的子程序
9.printf("%8d\n",100); printf("%6d\n",100); printf("%-8d\n",100); printf("%+8\n",100); 输出结果为: └┘└┘└┘└┘└┘100 └┘└┘└┘100 100└┘└┘└┘└┘└┘ └┘└┘└┘└┘100 "-"左对齐 "+"右对齐
10.
void test(void *data) {
unsigned int value = (此处应填入)
printf("%u", value);
}
using namespace std;
int main() {
unsigned int value = 10;
test(&value);
return 0;
}
*((unsigned int *)data)
实际上只要是*data,我们就知道了它是指针,如果是32位机器,该指针就指着内存中的某个地址,用32位表示,记住这个32位只是初始地址,任何指针都是的。而前面的void 或者int 类型是定义一次读几个字节,如果是int则读4个字节,也就是从*data存的地址开始从内存往后读4个字节就行,而void是空,没有指定要读多少个字节,所以要用指针类型(unsigned int *)强制转化为知道要读几个字节的int指针,然后再用*从开始地址,读取unsigned int个字节出来!
11.
int i=0;
const int ci=i;
auto b=ci; //(1)
int *p=&i;
decltype(*p) c=i;//(2)
(1)auto会忽略顶层const,所以b的类型为int
(2) 如果表达式的内容是解引用操作,则decltype将得到引用类型 就会得到int &类型