最近调程序,出现illegal instruction问题,没有头绪。 索性把illegal instruction好好窥探一下。 Continue reading »

 

start_kernel is the first function that kernel runs, like the main function in user space program.
In this post, I will try to get a detailed understand of how start_kernel is called on X86_64 and MIPS architecture. Continue reading »

 

很悲剧的一不小心格式化了/home分区所在的目录。这个分区是ext4格式的,被重新格式化为ext4格式,直接使用mkfs.ext4命令做的格式化。恢复步骤:

  • 使用dd命令,将整个分区备份到镜像文件中
$dd if=/dev/sda8 of=sda8.image
  • 下载TestDisk
  • 运行testdisk压缩包中的photore_static
    • 虽然从名字上看是恢复图片的,但恢复其他文件的能力也很强。比如pdf,office文档,源代码文件
    • 该工具会自动识别硬盘分区的属性,比如格式、blocksize等等,使用默认的设置一般都没问题
    • 最后选择recover all就行

感谢这款工具,基本上一些图片、pdf、office、源码都恢复的差不多。但tar压缩包、视频恢复无望。除了个别能看出文件名称外,99%的恢复文件和文件夹都是以数字命名的。基本需要人工逐个筛查。

被频繁修改、保存的文本文件会被恢复出来多份,分别是不同版本的。这应该和文件在硬盘中存储的位置有关。

TestDisk支持各种操作系统,各种格式文件系统,几乎各种硬盘问题(分区表、删除文件恢复、启动段恢复),是文件恢复利器。

尝试失败的工具

  • ext3grep
  • extundelete

这两个工具都是用于恢复被rm命令删除的文件,而本文遇到的情况是格式化,所以没效果。

参考

 

操作系统的任务管理,是个老生常谈的话题。是操作系统的四大功能–进程管理、内存管理、磁盘管理、设备管理中的一大管理。这篇文章介绍进程的生命周期、主要进程状态及其转换关系。并以Linux操作系统为例,浅谈。 Continue reading »

 

Segmentation Fault是常见的程序错误,错误原因说白了就是访问了不该访问的内存。什么是不该访问的内存,操作系统如何判断哪些内存该哪些程序访问呢?

什么是不该访问的内存:出segmentation fault的情景,都应该是因为访问了不该访问的内存。包括:访问的地址不属于进程地址空间、访问的类型是否符合该内存区域类型。进程地址空间的判定方式,本博会在日后文章中再讲。先说说内存区域的访问类型问题。下面一张图给出了Segmentation fault引发的大致机制。图来自参考1的总结文档。

SIGSEGV Overview

linux/include/mm.h中定义了一块内存可以允许的访问类型,包括四种,如下:

#define VM_READ         0x00000001
#define VM_WRITE        0x00000002
#define VM_EXEC         0x00000004
#define VM_SHARED       0x00000008

有四种类型,可读,可写,可执行,共享内存。另外这个头文件里还规定了很多其他属性,先略去不看。这四种属性是最基本的。具体的作用就不做说明了。这样的处理,可以保证内存是安全的,内核可以给数据的读写权限,给代码段执行权限,给共享库或者多线程下的全局数据共享属性。而且内核可以控制这些属性的变化。比如JIT,在程序执行过程中,把一段程序编译所得的代码,先以数据的方式存在内存中,再将这块内存设置为可执行,就可以直接执行了。不设置为可执行,就仅仅是一段存在内存中的机器码而已。

还有一个问题,虽然内存有这些属性,但他们肯定是相对于某个进程而言的,且不同的进程,这些属性也不同。这些是在哪里规定的呢?等日后再深挖

参考:

 

一个程序在终端运行时,我们可以CTRL+C退出该程序或者CTRL+Z暂时停止该程序。那么有办法屏蔽这两个操作吗?

首先,得明白CTRL+C和CTRL+Z做了些什么。stty是Linux下的命令,输出和设置命令行控制参数。stty -a能输出所有命令行设置。如下是本博的命令行设置:
$stty -a
speed 38400 baud; rows 48; columns 159; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = M-^?; eol2 = M-^?; swtch = M-^?; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 hupcl -cstopb cread -clocal -crtscts
-ignbrk brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc ixany imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke
可以看到CTRL+C就等于INTR,CTRL+Z就是SUSP,也就是说这两个分别会向程序发送SIGINT和SIGSTOP信号,这两个信号,一个用于终止进程,一个用于暂停进程,即挂起。

信号是Linux系统用于进程间通信的,内核也可以通过它们向程序发送消息。这些信号都很小,Sponge Liu写了篇文章《Linux内核信号处理机制介绍》,深入浅出的走了介绍。

接下来的问题就是,如何屏蔽两个信号。当然,你也可以通过设置stty的方式实现。可以在程序中屏蔽吗?如果可以,如何屏蔽?如果不可以,为啥?

很明显,肯定有些信号不能被屏蔽,比如中断,还应该有杀死进程的信号,要不然内核怎么做操作系统中的老大。实际上,SIGKILL和SIGSTOP信号是不能被屏蔽或阻止的,他们的默认动作总是会被执行的。

那就来个程序,直接屏蔽SIGINT信号吧.

#include 
#include 
#include 
#include 
#include 

bool keep_going = true;

void ignore_notice()
{
  keep_going=false;
  printf("recieved SIGINT,and ignore it.\n");
}

void do_something()
{
  int i=0;
  while(i < 1000000)
    {
      i++;
    }
}

int main ()
{
  if(signal(SIGINT, ignore_notice) == SIG_ERR)
  {
    printf("Fail\n");
    return 1;
  }

  while(keep_going)
    do_something();

  printf("program normally exit.\n");
  return 0;
}

下面语句设置针对SIGINT的动作,第二个参数可以传入函数指针,指定处理方式为函数内容,也可以为SIG_IGN,忽略这个信号,或者SIG_DFL,执行默认的动作。

signal(SIGINT, ignore_notice) == SIG_ERR

参考:

 

什么是分页

分页是操作系统中的内存管理机制。通过这种方式计算机可以为主存存取其他存储介质上的数据。在页存储管理机制中,OS从其他介质中得到相同大小的数据块,这种块即为页。 Continue reading »

 

什么是静态链接库?

静态链接库,即static library或 statically-linked library。和动态链接库,即dynamic library 或dynamicly-linked library相对,是Windows和Linux系统中比较常用的库文件。Windows中分别用SLL和DLL文件表示,Linux中分别是.a和.so文件.

静态链接库实际是一些object files(.o文件)和头文件的压缩包,通过GNU工具链中的ar(archiver)程序创建。

静态链接库、动态链接库和共享库

那为何还要有动态链接库呢?静态练级库虽然能很好的节省编译时间。对于一个简单的ls程序,我们需要有屏幕输出,有字符串和格式操作,有文件系统访问等等函数,都要在一个程序中。此时,这个程序会很大。一个小小的ls可能都会有好几兆。如果还有个rm程序,同样也需要屏幕输出,文件系统访问。那么这两个东西,我们可以放到两个库文件里,在执行ls,或者rm的时候,用到屏幕输出操作,就将相应的函数对应的机器码载入内存中,执行。然后再从内存中释放。接着载入文件系统访问的相关函数。这样我们的程序就能变小很多。这种可以动态装载到内存中的库文件就是动态链接库了。Windows下的DLL文件就是动态链接库。

Continue reading »

 

今天需要对Debian中的默认启动程序做配置,就顺便重新认识一下Linux下的启动过程,并总结对比Debian和Gentoo。

Init创世纪!

再来回顾一下Linux PC的启动过程

  1. BIOS检测硬件,并查找硬盘MBR(Master Boor Record)上的指令
  2. MBR指向GRUB,LILO之类的boot loader
  3. Grub查询载入操作系统内核的位置,并载入指定的内核
  4. 内核载入之后启动init进程。
  5. init启动脚本/etc/rc.d/rc.sysinit, 接着根据运行级别不同,启动指定的进程。

init是系统中所有进程的父进程,它确保所有的文件系统(/etc/fstab中指定的)都已经正确挂在,接着就执行/etc/init.d下的一系列脚本来启动服务。接着init就会激活终端,并将进程agetty和他绑定。agetty确保用户能在终端登录。

实际上init会根据不同的运行级别来启动不同的进程。这个运行级别的控制在/etc/inittab中。 Continue reading »

 

上篇文章前瞻-主流处理器中的数据并行支持(SIMD)>和《前瞻-拿起SIMD的武器I》分别介绍了当今主流CPU中的SIMD扩展 ,以及前人是如何利用SIMD来做优化的,本文<前瞻-拿起SIMD的武器II>将探讨如何使用CPU的向量指令为程序做优化

如何实现?

编程环境

在现在CPU设计中都加入SIMD扩展并不是解决应用性能问题的好方法。如果没有很好的利用途径,再强大的SIMD扩展指令集都是徒劳。接下来,我们从编译器技术和编程方法论上探讨如何使用SIMD指令来实现应用加速。 Continue reading »

2009-2011© 编译点滴 Suffusion theme by Sayontan Sinha

无觅相关文章插件,快速提升流量