momo zone

调核人的blog

Monthly Archives: 五月 2010

chrome 试用

前几天在suse 下整了一下linux 下首个chrome 稳定版,感觉还不错,对比firefox 明显感觉在渲染字体方面快一些。 js的渲染优势因为网速问题基本可以忽略。下载对话框很有新意。置顶标签很实用,省空间(和同样基于webkit的safari 一样)。最令人意外的是,chrome有和safari 一模一样的开发人员工具(这也是我在win上使用safari的唯一理由)。难道只要是基于webkit的都有这个东西? 呵呵,毫不犹豫地弃firefox投chrome。 结束了linux上firefox最佳浏览器的历史(这个平台上有其他可选吗?)。

Advertisements

关于0号和1号进程堆栈的疑惑

这一部分困惑了很久,但这个不是理解kernel的一个重点。

先看看大牛的解释:

由于创建新进程的过程是通过完全复制父进程代码段和数据段的方式实现的,因此在首次使用fork()创建新进程init时,为了确保新进程用户态堆栈没有进程0的多余信息,要求进程0在创建首个新进程之前不要使用用户态堆栈,也即要求任务0不要调用函数。因此在main.c主程序移动到任务0执行后,任务0中的代码fork()不能以函数形式进行调用。程序中实现的方法是采用gcc函数内嵌(内联)的形式来执行这个系统调用。参见下面程序第23行。虽然其中的系统中断调用还是避免不了使用,但是系统调用使用任务的内核态栈,而每个任务都有自己独立的内核态栈,因此系统调用不会影响这里讨论的用户态栈。
   
另外,在创建新进程init的过程中,系统对其进行了一些特殊处理。在为新进程init复制其父进程(进程0)的页目录和页表项时并没有为它们处于内核区
的代码和数据执行写时复制(Copy on Wirte)操作
,进程0和进程init实际上同时使用着内核代码区内(小于1MB的物理内存)相同的代码和数据物理内存页面,只是执行的代码不在一处,因此实际上它们也
同时使用着相同的用户堆栈区。为了不出现冲突问题,就必须要求任务0在整个执行过程中禁止使用到用户堆栈区域,而让进程init能单独使用堆栈。因此pause()也必须采用内嵌函数形式来实现。
    当系统中一个进程(例如init进程的子进程,进程2)执行过execve()调用后,进程2的代码和数据区会位于系统的主内存区中,因此系统可以利用写时复制技术来处理其他新进程的创建和执行。
    对于Linux来说,所有任务都是在用户模式下运行的,包括很多系统应用程序,如shell程序、网络子系统程序等。内核源代码lib/目录下的库文件就是专门为这里新创建的进程提供支持函数的。

看完后可以明确以下几点:
1.进程1是通过fork()复制进程0得到的,和进程2以及后续创建的进程不同的是没有接着使用execve(),而是“手动”地进行了一些特殊处理。
2.因为1,所以进程0和1的数据段和代码断指向相同物理地址。
3.又因为2,所以用户堆栈段也是一样的。

其实关键的就是因为第一点,没有使用execve()
不过即使这样如果真的在创建进程1之前往进程0的用户堆栈写东西,也不会导致系统崩溃,因为新创建的进程仅仅复制了这些无用的堆栈信息,但永远也不会去读它(写黑客程序除外)。

google 的logo ~ 服了

对于一个80后看到这两天的google的logo深受感动~~
游戏规则,图形,过关动画(暂且这样称呼吧)都和当年的原作一模一样。此刻namco泪流满面 ……

这个网页没有使用flash(声音除外),实现方法和google首页的动画效果是一样的:把动画元素放在一个大的png文件中,用js分割获得其中一个元素,并用js控制dom树,设置元素位置和其他属性。难度还是相当高的。用ff看会卡,用ie反而不会,很奇怪。

open suse 的国内镜像

http://lizardsource.cn

#whois lizardsource.cn
Domain Name: lizardsource.cn
ROID: 20080527s10001s42620050-cn
Domain Status: ok
Registrant Organization: 孟佳洁
Registrant Name: 孟佳洁
Administrative Email: domain@cnkuai.cn
Sponsoring Registrar: 北京万网志成科技有限公司
Name Server:ns.cnkuai.cn
Name Server:ns.cnkuai.com
Registration Date: 2008-05-27 22:52
Expiration Date: 2011-05-27 22:52

速度不错

zope mysql DA (Zproduct) 安装手记

zope 和其他web应用服务一样可以对应用打包,重新发布从而方便部署。不同的是zope的部署对象名字叫zproduct,而且它
可以很“自由”的被发布和部署,只要按照zope的文档编写需要发布的代码即可。这和java不同,java不仅要求其代码符合
规范,而且其发布包(比如ear)内需要相应的xml来指导这些代码的安装,以及利用xml来自动配置执行环境。从java的思维
来看zope的设计似乎过于松散而显得不够完善,因为java enterprise有像SUN/ORACLE,IBM以及HP这样的大公司直接支持,
十几年的发展令它变得很成熟。好在它们的应用场合不同,很多情况下松散的结构更便于测试,调试和轻量级应用。
作业平台:
kernel: 2.6.31.12-0.1
glibc: 2.10.1-10.4
gcc: gcc-4.4.1
python: 2.4.6
zope: 2.11.5
 
这次安装的zproduct ZMYsqlDA 主要有两部分组成:
(1)MySQL-python :python库文件。mysql数据的接口驱动,直接和mysql打交道。
(2)ZMySQLDA:DA的接口程序,由python编写。
首先解包ZMySQLDA-0.9.0.tar.gz 到路径/opt/Zope-2.11/ , 这样zproduct 将被安装lib/python/Products目录下。
然后将MySQL-python-1.2.3c1 解包到路径/opt/Zope-2.11/lib/python 下。
启动zope 实例:
#sh /opt/Zope-2.11/lib/python/zopeTest/bin/runzope &
登录ZMI查看product列表未发现 ZMYsqlDA,说明安装失败。
查看zope log:
#tail -f /opt/Zope-2.11/lib/python/zopeTest/log/

2010-05-11T06:02:35 ERROR Application Could not import Products.ZMySQLDA          
Traceback (most recent call last):                                                
  File "/opt/Zope-2.11/lib/python/OFS/Application.py", line 709, in import_product
    product=__import__(pname, global_dict, global_dict, silly)                    
  File "/opt/Zope-2.11/lib/python/Products/ZMySQLDA/__init__.py", line 91, in ?   
    import DA                                                                     
  File "/opt/Zope-2.11/lib/python/Products/ZMySQLDA/DA.py", line 91, in ?         
    from db import DB                                                             
  File "/opt/Zope-2.11/lib/python/Products/ZMySQLDA/db.py", line 98, in ?         
    from MySQLdb.converters import conversions                                    
  File "/opt/Zope-2.11/lib/python/MySQLdb/__init__.py", line 31, in ?             
    raise ImportError, "this is MySQLdb version %s, but _mysql is version %s" %  
ImportError: this is MySQLdb version (0, 9, 0, ‘final’, 1), but _mysql is version (1
, 2, 3, ‘gamma’, 1)                                                                
——                                                                             
2010-05-11T06:02:36 ERROR Application Couldn’t install ZMySQLDA                    
Traceback (most recent call last):                                                 
  File "/opt/Zope-2.11/lib/python/OFS/Application.py", line 758, in install_product
    global_dict, global_dict, silly)
  File "/opt/Zope-2.11/lib/python/Products/ZMySQLDA/__init__.py", line 91, in ?
    import DA
  File "/opt/Zope-2.11/lib/python/Products/ZMySQLDA/DA.py", line 91, in ?
    from db import DB
  File "/opt/Zope-2.11/lib/python/Products/ZMySQLDA/db.py", line 98, in ?
    from MySQLdb.converters import conversions
  File "/opt/Zope-2.11/lib/python/MySQLdb/__init__.py", line 31, in ?
    raise ImportError, "this is MySQLdb version %s, but _mysql is version %s" %
ImportError: this is MySQLdb version (0, 9, 0, ‘final’, 1), but _mysql is version (1
, 2, 3, ‘gamma’, 1)

很明显ZMYsqlDA和Mysql-python 版本不匹配,ZMYsqlDA需要更新。
下载新版ZMYsqlDA-2.0.8解压到相应目录重新启动zope后仍未发现安装成功。此时log中显示:

2010-05-11T04:35:37 ERROR Application Could not import Products.ZMySQLDA
Traceback (most recent call last):
  File "/opt/Zope-2.11/lib/python/OFS/Application.py", line 709, in import_product
    product=__import__(pname, global_dict, global_dict, silly)
  File "/opt/Zope-2.11/lib/python/Products/ZMySQLDA/__init__.py", line 91, in ?
    import DA
  File "/opt/Zope-2.11/lib/python/Products/ZMySQLDA/DA.py", line 91, in ?
    from db import DB
  File "/opt/Zope-2.11/lib/python/Products/ZMySQLDA/db.py", line 89, in ?
    import _mysql
ImportError: /opt/Zope-2.11/lib/python/_mysql.so: symbol errno, version GLIBC_2.0 no
t defined in file libc.so.6 with link time reference
——
2010-05-11T04:35:38 ERROR Application Couldn’t install ZMySQLDA
Traceback (most recent call last):
  File "/opt/Zope-2.11/lib/python/OFS/Application.py", line 758, in install_product
    global_dict, global_dict, silly)
  File "/opt/Zope-2.11/lib/python/Products/ZMySQLDA/__init__.py", line 91, in ?
    import DA
  File "/opt/Zope-2.11/lib/python/Products/ZMySQLDA/DA.py", line 91, in ?
    from db import DB
  File "/opt/Zope-2.11/lib/python/Products/ZMySQLDA/db.py", line 89, in ?
    import _mysql
ImportError: /opt/Zope-2.11/lib/python/_mysql.so: symbol errno, version GLIBC_2.0 no
t defined in file libc.so.6 with link time reference
 
这个错误是因为python-mysql是一个相对老的python库,很多已编译版本都是在glibc-2.0上编译的,编译的时候会把GLIBC的宏定义以及目标文件GNU符号表对应项设置为2.0,而现在的主流平台上glibc2 已经是第10个版本了即glibc-2.10 或更新,变化非常大。尝试用源码重新编译一下:
下载源码包,解压到任意目录,执行
#python ez_setup.py
安装python ez_setup 支持。

然后执行
#python setup.py build
编译生成 _mysql.so及其他py文件。

最后
#cp -R build/* /opt/Zope-2.11/lib/python
覆盖旧版。重新启动zope 在ZMI可以看到ZMYsqlDA已经安装成功。

关于保护模式下权限检查

这里有几处是比较重要的用来进行权限检查的依赖:
CPL:当前特权级,存在于cpu中cs和ss段寄存器的第0和第1位。(注意:段寄存器加载的是段选择符,而段选择符的第0和第1位是RPL)
DPL:描述符特权级,存在于相关描述符的DPL字段中。
RPL:请求特权级,在使用长跳转等指令通过段选择符来载入段描述符时,段描述符的第0和第1为PRL。
 
根据检查的类别分为
1.数据段访问权限检查
2.代码段访问权限检查
3.各种门机制的访问权限检查
4.堆栈段访问权限检查
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

1. 数据段访问权限检查
 这个比较简单,不过要明确一点,就是数据段的权限问题仅仅是检查,不存在运行级切换,即访问不同级别的数据段不会像代码段那样导致运行级变更。 检查的时候,一方是DPL另一方是CPL和RPL 。必须CPL<=DPL并且RPL<=DPL才能访问。归纳一下就是必须MAX(CPL,RPL)<=DPL。记住加载完之后系统运行级不变哦。所以CPL也不会有任何变化。
 
2.代码段访问权限检查
这个就相当复杂和麻烦了,因为代码段的加载涉及到运行级的改变,以及使用不同方式(门)来加载描述符的过程中所涉及到众多细节。

代码段的加载一般有下面的指令触发:JMP,CALL,RET,INT,IRET以及异常和中断。

其中JMP和CALL后面的操作数可以是如下类型:
(1)操作数是目标代码段的段选择符,这个是最常用到的。
(2)操作数指向一个调用门描述符, 该描述符含有目标代码段的段选择符。
(3)操作数指向一个TSS。该TSS中含目标代码段选择符。
(4)最复杂的一种,结合(2)和(3):操作数指向一个调用门描述符,该描述符含有一个TSS,该TSS中含目标代码段选择符。

这里先说第1种情况,也是最简单和直接的一种:
这种情况下检查权限除了以来CPL,RPL,DPL 还有C标志(代码一致标志)。
当C=0时(非一致代码)时,必须CPL=DPL并且RPL<=DPL才能访问,否则将出现“一般保护性异常”。一旦这个目标非一致代码段被加载到CS,那么CPL不会改变,无论RPL是不是和CPL一致,尽管加载到CS的是段选择服符(包含RPL)。

当C=1时(一致代码)时,必须CPL>=DPL。并且忽略关于RPL的任何检查。同样这种情况下,载入目标一致代码段后,CPL不会变化。但注意这时已加载代码段的DPL和CPL有可能不同了!!一致代码往往用在这种情况下:比如除0错误,发生异常,数学库需要访问更高特权级下的异常处理代码但又要保证不能访问更高特权级下的其他代码。这样一致代码段就扮演了这个角色,毕竟CPL没有变化嘛。
可以把一致代码段看作一种另类的代码段。实际上操作系统中的大部分代码段都是非一致代码段。

接下来是第2种情况,通过门描述符会比较复杂一些
第3种和第4种情况太复杂,很多系统实现都没有采用这种机制,不做介绍。

3.各种门机制的访问权限检查
门描述符又分为4种:
调用门(call gate)
陷阱门(Trap gate)
中断门(Interrupt gate)
任务门(Task gate)

只讲解一下相对简单的调用门:
这里的权限检查依赖以下:
  当前CPL
  调用门选择符RPL
  调用门描述符中的DPL
  目的代码段描述符中的DPL
  目的代码段描述符中的C标志

实际检查时还会根据触发指令的不同而有不同的检查规则:
CALL:
CPL<=调用门的DPL且RPL<=调用们的DPL
一致/非一致目的代码段都只要求CPL>=DPL。如果真的CPL>DPL的话,那么还将会把DPL赋给CPL。这样就能让低特权级的代码切换到高特权级代码了!当然也会引起堆栈切换。

JMP:

CPL<=调用门的DPL且RPL<=调用门的DPL,一致目的代码段要求DPL<=CPL,非一致目的代码段要求DPL=CPL。

输出外接VGA

$ xrandr –output VGA –auto
当前桌面会复制到VGA上面,此时执行xrandr会看到有了VGA-0

$ xrandr –output VGA-0 –auto
断开VGA-0

$xrandr —-output VGA-0 –auto –left-of LVDS
按照当前的配置扩展桌面,需要在/etc/x11/xorg.cong里面添加一段,把整个screen的大小变化一下,实际上你的外接VGA可能是更大的分辨率,这个也很简单,自己修改–auto就可以了

关于flag寄存器中IF标志的疑惑

看二手资料不如看一手资料这句话是太正确了,看了intel 手册的3卷A ,发现之前对中断屏蔽问题有一些误区,现在总结一下吧。
 
 IF=1表示允许,IF=0 表示禁止。关键是禁止和允许什么中断。
其实IF仅影响到cpu intr引脚接受到的可屏蔽硬件中断。也就是说不可屏蔽中断(NMI),处理器产生的异常和软中断(int)均不受影响。看下图一目了然:
 
 
 
当使用中断门处理中断时,IF标志会被清除,也就可以禁止可屏蔽硬件中断。但如果通过陷阱门处理的话则,IF标志不会被清除。下图应该是使用中断门的情况:
 
 
 

YS3 回顾

PSP版的YS3出了一段时间了,一直都没怎么玩,不过看到他的logo总觉得很怀旧。
YS3 恐怕是继YS1&2后最受重视的一部了,X68000,FC,SFC,PC-E ,MD, PS2,X86,PSP……似乎只有是台家用主机就有ys3的身影,而且YS3的音乐质量可真是比另外几作高出一截。

其中只有X86和PSP是用YS6的3D引擎重新制作,并且名称也改为依苏3费尔加纳的誓言,其他的都叫 依苏3来自依苏的冒险者。但YS3每次移植平台,画面质感都会变化,PS2版是传统2D横轴画面质量也是最高,当然3D版的还是X86的最佳,不过PSP版有全程语音,万年哑巴红毛adol除外 ~~

看看06年YSF发布时的官方网站,在看看2010年PSP版发布时的站点,感慨到"物是人非"了 ~~


关于kernel注释中iret手动切运行级

为什么要用iret??前面书上说了是为了从特权0的代码切换到特权3的代码中去,但是为什么不用ret呢?
书上说ret也可以返回到特权级低的程序中去呀!

比如把48~62这样改写:



movl  $TSS0_SEL , %eax


itr  %ax


movl  $LDT0_SEL , %eax


lldt  %ax


movl  $0,  current


sti


pushl  $0x17


pushl  $init_stack


pushl  $0x0f


push  $task0


ret

当然这里需要留意iret还将弹出标志寄存器(popf),不过即使这样也没有影响。

其实这样是可以的,因为:
ret指令的段间跳转会改变特权级,但是只针对(数值上)特权级值低的处理程序,也就是内核态才能用(因为linux只有0和3)。
当ret指令面对的是目标cs的RPL在数值上大于CPL,一个特权级返回才发生。就是由0特权级返回到3。

检查的过程是,CPL的特权级要高于目标CS的RPL,而目标CS的RPL要等于目标段描述符的DPL(针对非一致性代码)!

所以,在内核态,这样也可以实现向用户态的转移。

ret前,特权级是0,CS是0x0f,特权级是3,而0x0f对应的段描述符是非一致代码,而且DPL
=3,满足上面的条件,所以,可以起到特权级的变化,而且堆栈也随之变化。