在centos上用gdb调试printf源码

centos中默认情况下库函数是不带调试信息的,所以用gdb无法进入到printf()函数里。 解决办法是: 1.为libc安装调试信息 a. 先要安装一个命令:sudo yum install /usr/bin/debuginfo-install b. 设置一下repos: vi /etc/yum.repos.d/CentOS-Debuginfo.repo, 把enabled设置为1 c. 为标准库安装调试信息: sudo debuginfo-install glibc 2.再来一次gdb并进入printf()函数即可. 我这里看到的第一行代码是 _IO_size_t len = strlen (str);

存储器的多级结构

内存 = cache + 主存储器, cpu可以直接访问 其他的都属于外存,cpu不能直接访问 关于cache:   1. 充当cpu和主存之间的速度缓冲   2. 程序员的代码访问不到cache  

关于磁盘的一些知识

磁盘结构: 一个磁盘有多个盘片(platter),两面(2 surfaces)都可以存储数据,正反两面一般来说各有一个磁头(disk head) 1. 一个盘面由一系列磁道(track)组成,所有platter在同一直径上的磁盘组成一个柱面(cylinder) 2. 一个磁道包含多个扇区(sector) 存取时间的构成 存取时间由4部分组成:    1. 寻道时间(seek time): 磁头移动到正确的磁道上 (几个ms)    2. 旋转时间(rotational latency): 等待目标扇区旋转到磁头的下面 (几个ms)    3. 数据传输时间 (transfer time, 取决于数据传输率指标)(1k数据,零点几个ms)    4. 磁盘控制器带来的时延 (时延很低) 平均总时延一般是10ms左右    ============== 一个磁盘虽有多个磁头,但这些磁头整体上是同步移动的,并不能各移各的。所以多个进程对单个磁盘的访问,其实并不是并行的,而是串行的。

计算机程序、指令与控制器

程序(program) 是 指令(instruction)的集合 指令 = 操作码 + 数据。 由于程序和数据都放在存储器里,所以对控制器(Controller)来说, 上面的等式相当于  从某个地址读出的指令 = 操作码 + 数据的地址。 比如: 而控制器的基本任务就是: 1. 从存储器中取出第1条指令(fetch instruction) 2. 执行这条指令(execute instruction)。 这时可能还会从存储器中取出数据 (fetch operands) 3. 再取出第2条指令 4. …. 如此循环。 图示:

常见寄存器

Data Registers:                暂存ALU的计算结果 Instruction Registers:         存储当前正在执行的指令 Program Counter:               下一条指令的地址 Address Registers:             存储当前指令所访问数据的地址 Control and Status Registers:  can store both data and addresses, i.e., they are combined Data/Address registers. Program Status Word:           程序状态。如进位标志、溢出标志、中断状态等

硬中断

中断是一种电信号,由硬件设备生成,然后传入到中断控制器的输入引脚。 中断控制器则发送一个电信号给CPU. CPU根据中断信号携带的数字标志(中断号),按一定算法找到对应的中断向量的地址(比如8086下是用中断号乘于4),读取这个地址上的值,拿到的就是中断服务程序的内存地址。 最后再执行中断服务程序。

fork()太奇葩了

《UNIX环境高级编程》说: “fork()调用一次,返回两次”。 这什么玩意儿? 作为Java程序员觉得很难理解。虽然书上提到了进程复制,但当时还是转不过弯来。这本书的例子代码里会判断fork()返回值的不同而分别执行父子进程的行为,搞得我更晕了,难道linux父子进程实际上是同一个进程? 后来看了一下《操作系统设计与实现》,才终于明白。 下面用代码解释一下。 /* fork()复制出的子进程跟当前进程所基于的代码一模一样,所以子进程也会执行下面的代码。不过,它不是从第一句开始执行的。 */ int main(){ /*下面这句只会执行一次,即只被父进程执行*/ printf("开始执行。当前进程的ID=%d\n", getpid()); int pid = fork(); /*这句会打印两次,说明子进程从这里开始执行*/ printf("调用fork()之后。当前进程的ID=%d\n", getpid()); /*下面两次打印出来的pid并不相同*/ if(pid > 0){ printf("fork()返回%d.当前进程是父进程,进程ID=%d\n", pid, getpid()); } if(pid == 0){ printf("fork()返回%d.当前进程是子进程,进程ID=%d\n", pid, getpid()); } /*下面这句会打印两次,父子进程都会执行*/ printf("程序准备退出。当前进程的ID=%d\n================\n", getpid()); }