momo zone

调核人的blog

Monthly Archives: 九月 2010

关于sysrq

之前不知道键盘的这个键是干什么的,以为是以前DOS或Novall的系统专用键 。 看了LDD3 发现这个在linux 下是用来查看系统状态的。

现在的发行版默认都把这个功能编译到了内核中,
CONFIG_MAGIC_SYSRQ=y
不过启动后系统不是默认启用,需要
echo 1 >/proc/sys/kernel/sysrq
如果每次开机需要启用就直接编辑/etc/sysctl.conf
按alt+sysrq 键启用再 +字母键来呼叫打印信息的类别

比如:alt+sysrq+h 就可以看到所有sysrq组合键说明

当 X 锁定时,使用 alt--r ( 就是 PrintScreen 键)回复键盘的控制权,alt--k Kill 掉虚拟终端上的所有程序。
如果整个机器都死了,那么先按 alt--s 把数据同步到硬盘(Sync),alt--u 卸载所有磁盘(Unmount),alt--b 重启(Boot)。

不过这个sysrq 这个keycode 由内核直接控制,所以用xmodmap无法重映射。 意思就是如果你把keycode111 的sysrq 用xmodmap映射到其他keycode,那么即使按下那个键也是没有任何效果,看来我的apple G6 键盘杯具不行了,还要抄起我那落满土的微软basic键盘。 只能改内核的kbd,参看“键码之旅”这篇文章。

Advertisements

刚刚从live spaces 搬到这里感觉很不错

word press 之前就见过,很不错,无奈先上了微软的贼船,直到今天又戏剧性的被微软强制拆迁搬到这里,好有趣啊。我终于可以用chrome顺利的写点东西了。估计live的代码已经乱到不行了,所以直接搬到这里反而痛快。不过搬迁的时候丢了图片,未发布文章也丢了,有空再补一下吧(幸亏我做了备份)。

这样看来微软已经彻底抛弃live spaces了,把他丢给了word press ,而里面充斥这google的插件和Iphone的广告,不知道微软作何感想。另外一个担心是怕我们伟大的party把wordpress给屏蔽掉,我已经发现用GAE 访问比直接访问还要快,这说明GFW进行了过滤…….. 我知道的太多了,还是闭上嘴吧….

Hello world!

Welcome to WordPress.com. This is your first post. Edit or delete it and start blogging!

便宜没好货

买了移动硬盘盒装上测 SMART 竟然测不到

smartctl 5.39 2008-10-24 22:33 [i686-suse-linux-gnu] (openSUSE RPM)
Copyright (C) 2002-8 by Bruce Allen, http://smartmontools.sourceforge.net
Device: IC25N030 ATMR04-0         Version:
scsiModePageOffset: response length too short, resp_len=4 offset=4 bd_len=0
>> Terminate command early due to bad response to IEC mode page
A mandatory SMART command failed: exiting. To continue, add one or more ‘-T permissive’ options.
我的第一反应,坏了,估计是主控不支持。翻了一下资料发现果然是这样(http://www.hdsentinel.com/compatibility_usbharddisks.php): 
VID: 14CD, PID: 6600 Super Top USB 2.0 to IDE No No Not possible

完蛋了,确实不支持,也许这也是硬盘盒价格差异的一个原因。

container_of 宏分析

用法:

各参数含义:

type — 需要操作的数据类型,通常为结构;

member — type结构的成员名称;

ptr — member类型定义的指针变量;
例如:

struct my_t{

int mem0;

float mem2;

double mem4;

char  mem6;
};

struct my_t abc, *pabc;

abc.mem2 = 0.0;

float *pmem2 = &abc.mem2; //已知

//通过成员变量的地址得到它所在结构的首地址
pabc = container_of(pmem2 , struct my_t, mem2 );

这个宏在我读驱动程序的时候经常见到,其功能就是通过一个结构中的成员找到包含这个成员的结构。
这个绝对属于奇技淫巧,不属于正常编程的方法。
现看看他的定义:
include/linux/kernel.h:
/**
 * container_of – cast a member of a structure out to the containing structure
 * @ptr:the pointer to the member.
 * @type:the type of the container struct this is embedded in.
 * @member:the name of the member within the struct.
 *
 */
#define container_of(ptr, type, member) ({
const typeof(((type *)0)->member) * __mptr = (ptr);
(type *)((char *)__mptr – offsetof(type, member)); })
#endif

ok 看到了offsetof 就先从他开始讲:
include/linux/stddef.h:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

(TYPE *)0 //将0转换成TYPE型指针
(TYPE *)0->MEMBER //访问TYPE型里的成员MEMBER
&((TYPE *)0->MEMBER) //取出该成员的地址
(size_t) &((TYPE *)0->MEMBER) //将该成员的地址值转换为size_t类型
说白了这个就是得到一个成员在结构体中的偏移
接下来再回过头看container_of:
type:结构体类型
member:结构体成员
ptr:结构体成员指针
typeof(((type *)0)->member) //获得成员变量的类型(原型)
const typeof(((type *)0)->member) *__mptr=(ptr) //用这个成员变量的类型定义一个值为ptr的指针__mptr(注意这里其实是指针赋值)
((char *)__mptr – offsetof(type, member)) //再把这个指针转化为字节指针(char类型)减去成员在结构体中的偏移
由于__mptr 指向的其实就是成员的绝对地址,减去成员在结构体内的偏移地址,得到的就是包哈该成员的结构体的绝对地址! 
(type *)((char *)__mptr – offsetof(type, member)) //再修正一下,把绝对地址转换为type类型(不这样的话不够严谨啊)
最后外面的一层{} 就是返回{}包裹的语句中最后一行的值

其实这个宏在内核中还有另一个定义:
#define container_of(obj, type, memb)
((type *)(((char *)obj) – offset_of(type, memb)))
这个就简单多了,省掉了__mptr,好像也没有什么问题
猜下原因吧(引用别人的):
linux kernel的开发者是认真严谨的程序员,定义__mptr是用来防止宏的副作用。container_of宏的第一个参数是指针变量,如果我们这样使用宏:container_of(p_member++, struct sample_struct, member_name),那么如果ptr在container_of宏中出现两次,那么ptr就自增了两次!多么危险的副作用!当然实际上container_of宏中ptr只出现了一次,但是认真严谨的程序员为了防止可能出现的可怕的副作用,习惯性的加上了这样一个常量。

内核子系统之初始化宏

看了一下usb子系统的源码,先从subsys_initcall(usb_init) 开始。

这个也是让人一头雾水,用笨的方法慢慢展开吧
subsys_initcall(usb_init)
       ||
       ||  #define subsys_initcall(fn) __define_initcall("4",fn,4)
       ||
__define_initcall("4",usb_init,4)
       ||
       ||  #define __define_initcall(level,fn,id) static initcall_t __initcall_##fn##id __used __attribute__((__section__(".initcall" level".init"))) = fn //可变参数宏,允许替换空值
       ||
static initcall_t __initcall_usb_init4 __used __attribute__((__section__(".initcall"level".init")))=usb_init
       ||
       ||  typedef int (*initcall_t)(void) //定义‘函数指针’类型,被指向的函数不带参数,返回值类型为int。
       ||   #define __used __attribute__((__used__)) //对于gcc4,gcc3.3及以上版本而言
||
static initcall_t __initcall_usb_init4 __attribute__((__used__)) __attribute__((__section__(".initcall"level".init")))=usb_init

这里暂不讨论__attribute__具体是什么,其实到这里就能看出来subsys_initcall 到底怎么回事:
创建一个静态的函数指针,并使之指向usb_init。
在看一下usb_init()的定义:
static int __init usb_init(void)
       ||  
       ||  #define __init __section(.init.text) __cold notrace
       ||
static int __section(.init.text) __cold notrace usb_init(void)
       ||
       ||  #define __section(S) __attribute__((__section__(#S)))
       ||  #define __cold       __attribute__((__cold__))
       ||  #define notrace __attribute__((no_instrument_function))
       ||
static init __attribute__((__section__(.init.text))) __attribute__((__cold__)) __attribute__((no_instrument_function)) init(void)
这样就可以看得更清楚。
ok , 问题是这么一堆__attribute__ 是什么意思
 
这个要扯到gcc的一些扩展特性,不说太多,这里只需要留意一下__section__ 标记,  他是将该段代码(文中是函数)放入执行镜像的指定段中。
文中就是放入.init.text 段中。这样有个好处,就是这些负责初始化的函数执行之后可以立马被请出去,腾出来内存。细节可以在arch/x86/kernel/vmlinux.lds (编译一次内核后才有,用来指示ld 如何编排内核镜像的)中窥视一下:
这个文件虽然是天书(大部分是注释,非常详尽)  ,不过只要搜这个就行了initcall.init。
 __inicall_start = .;
.initcall.init : AT(ADDR(.initcall.init) – 0xC0000000) {
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
}
__initcall_end = .;
那个函数指针
看到这里应该能悟到了
__initcall_usb_init4 这个函数指针就是被放到了这里 *(.initcall4.init)
而真正的函数体是放在.init.text 这里面。内核初始化时会按照1-7的顺序执行这些函数指针所指的函数。这个机制就像/etc/init.d/ 里面的启动脚本。

Linux下静态库和动态库(共享库)的制作与使用


Linux操作系统支持的函数库分为静态库和动态库,动态库又称共享库。linux系统有几个重要的目录存放相应的函数库,如/lib /usr/lib。 

静态函数库: 

  这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进可执行文件了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译,而且体积也较大。 

动态函数库: 

  这类库的名字一般是libxxx.so,动态库又称共享库;相对于静态函数库,动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。而且如果多个应用程序都要使用同一函数库,动态库就非常适合,可以减小应用程序的体积。

下面来介绍linux静态函数库的创建和使用: 



  例程add.h add.c sub.h  sub.c  main.c: 

  add.h 

  #ifndef ADD_H 

  #define ADD_H 

  int add(int x,int y); 

  #endif 

  add.c 

  #include <stdio.h>

  #include "add.h" 

int add(int x,int y)

{ 

      return (x+y);

} 

——————————————————————–

    sub.h 

  #ifndef SUB_H 

  #define SUB_H 

  int sub(int x,int y); 

  #endif 

  sub.c 



  #include <stdio.h>

  #include "sub.h" 

int sub(int x,int y)

{ 

     return (x-y);

  } 

———————————————————————–

main.c 



#include <stdio.h>

  #include "sub.h" 

#include "add.h"



  int main() 

{ 

    int  a,b;

    a = add(1,2);

    b = sub(10,5);

    

    printf(“a=%d,b=%dn”,a,b);

    return 0; 

  } 

———————————————————————–

  不管是静态函数库还是动态函数库,都是由*.o目标文件生成。 



所以先 gcc -c add.c 

       gcc -c sub.c 

生成add.o  sub.o



  静态函数库由ar命令创建 



  本例:ar -cr libaddsub.a add.o sub.o



  -c create的意思 



  -r replace的意思,表示当插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置。 

  到此静态函数库创建完毕。 



  使用方法:通过gcc -o main main.c -L. -laddsub编译main.c就会把静态函数库整合进main。



  其中 



  -L指定静态函数库的位置供查找,注意L后面还有’.’,表示静态函数库在本目录下查找。 



  -l则指定了静态函数库名,由于静态函数库的命名方式是lib***.a,其中的lib和.a忽略。 



  根据静态函数库的特性,此处删除libaddsub.a后main依然可以运行,因为静态库的内容已经整合进去了。 



  动态函数库的创建和使用 



gcc -shared -fpic -o libaddsub.so  add.c sub.c 



-fpic:产生位置无关代码

-shared:生成共享库



用上述命令生成libaddsub.so 动态函数库。



  gcc -o out main.c -L. -laddsub 



  此时还不能立即./out,因为在动态函数库使用时,会查找/usr/lib /lib目录下的动态函数库,而此时我们生成的库不在里边。 



  这个时候有好几种方法可以让他成功运行: 



  最直接最简单的方法就是把libaddsub.so拉到/usr/lib 或/lib中去。 

    

还有一种方法,假设libaddsub.so在/home/linux/addsub

export LD_LIBRARY_PATH=/home/linux/addsub:$LD_LIBRARY_PATH



  另外还可以在/etc/ld.so.conf文件里加入我们生成的库的目录,然后/sbin/ldconfig。 

/etc/ld.so.conf是非常重要的一个目录,里面存放的是链接器和加载器搜索共享库时要检查的目录,默认是从/usr/lib /lib中读取的,所以想要顺利运行,我们也可以把我们库的目录加入到这个文件中并执行/sbin/ldconfig。

分析一下compiz-manager 的脚本

前面讲过用这个脚本可以自动配置compiz 的启动参数。之所以需要一个单独的脚本设定启动参数是因为compiz 牵扯的东西太多,内核dri/drm ,GPU driver, Xorg,GL 渲染方式,桌面环境 等等。
#!/bin/sh
# Compiz Manager wrapper script
# Copyright (c) 2007 Kristian Lyngstøl <kristian@bohemians.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#
#
# Contributions by: Treviño (3v1n0) <trevi55@gmail.com>, Ubuntu Packages
#
# Much of this code is based on Beryl code, also licensed under the GPL.
# This script will detect what options we need to pass to compiz to get it
# started, and start a default plugin and possibly window decorator.
ARCH=`arch`
if [ $ARCH == "x86_64" ]; then
     LIB=lib64
else
     LIB=lib
fi
PREFIX=$(dirname $(dirname $(which compiz)))
COMPIZ_BIN_PATH="${PREFIX}/bin/" # For window decorators and compiz
PLUGIN_PATH="${PREFIX}/${LIB}/compiz/"
GLXINFO=$(which glxinfo)
KWIN=$(which kwin)
METACITY="/usr/bin/metacity"
XFWM="/usr/bin/xfwm"
COMPIZ_NAME="compiz" # Final name for compiz (compiz.real) 
# For Xgl LD_PRELOAD
LIBGL_NVIDIA="/usr/lib/nvidia/libGL.so.1.2.xlibmesa"
LIBGL_FGLRX="/usr/lib/fglrx/libGL.so.1.2.xlibmesa"
# Minimum amount of memory (in kilo bytes) that nVidia cards need
# to be allowed to start
# Set to 262144 to require 256MB
NVIDIA_MEMORY="65536" # 64MB
NVIDIA_SETTINGS="nvidia-settings" # Assume it’s in the path by default
# For detecting what driver is in use, the + is for one or more /’s
XORG_DRIVER_PATH="/usr/${LIB}/+xorg/+modules/+drivers/+"
FALLBACKWM="xterm"
if [ x"$KDE_FULL_SESSION" = x"true" ]; then 
        FALLBACKWM="${KWIN}";
elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ]; then 
        FALLBACKWM="${METACITY}"
elif xprop -root _DT_SAVE_MODE | grep ‘ = "xfce4"$’ >/dev/null 2>&1; then 
        FALLBACKWM="${XFWM}"
fi
FALLBACKWM_OPTIONS="–replace $@"
# Driver whitelist
WHITELIST="nvidia intel ati radeon i810 nouveau"
# blacklist based on the pci ids 
T="   1002:5954 1002:5854 1002:5955" # ati rs480
T="$T 1002:4153" # ATI Rv350
T="$T 8086:2982 8086:2992 8086:29a2 8086:2a02 8086:2a12"  # intel 965
BLACKLIST_PCIIDS="$T"
unset T
COMPIZ_OPTIONS="–ignore-desktop-hints –replace"
# Those are bare minimum plugins. anything else might want to be enabled / disabled by users.
COMPIZ_PLUGINS="core decoration move minimize resize"
ENV=""
#If the user does not yet have a populated Default.ini, we’ll drop a default in his config folder
if [ ! -s "$HOME/.config/compiz/compizconfig-1/Default.ini" ]; then #file exist and not zero size
  install -D "/usr/share/compiz-manager/config.skel" "$HOME/.config/compiz/compizconfig-1/Default.ini"
fi
# Use emerald by default if it exist
USE_EMERALD="yes"
# No indirect by default
INDIRECT="no"
# Default X.org log if xset q doesn’t reveal it
XORG_DEFAULT_LOG="/var/log/Xorg.0.log"
# Set to yes to enable verbose
VERBOSE="yes"
# Echos the arguments if verbose
verbose()
{
if [ "x$VERBOSE" = "xyes" ]; then
printf "$*"
fi
}
# abort script and run fallback windowmanager
abort_with_fallback_wm()
{
if [ "x$SKIP_CHECKS" = "xyes" ]; then
verbose "SKIP_CHECKS is yes, so continuing despite problems.n"
return 0;
fi
if [ "x$CM_DRY" = "xyes" ]; then
verbose "Dry run failed: Problems detected with 3D support.n"
exit 1;
fi
verbose "aborting and using fallback: $FALLBACKWM n"
if [ -x $FALLBACKWM ]; then
exec $FALLBACKWM $FALLBACKWM_OPTIONS
else
printf "no $FALLBACKWM found, exitingn"
exit 1
fi
}
# Check for non power of two texture support(pass when any item applied)
check_npot_texture()
{
verbose "Checking for non power of two support: "
if glxinfo 2> /dev/null | egrep -q ‘(GL_ARB_texture_non_power_of_two|GL_NV_texture_rectangle|GL_EXT_texture_rectangle|GL_ARB_texture_rectangle)’ ; then
verbose "present. n";
return 0;
else
verbose "Not present. n"
return 1;
fi
}
# Check for presence of FBConfig .For radeon drvier , indirect and direct rendering as no difference result for GLX.*fbconfig
check_fbconfig()
{
verbose "Checking for FBConfig: "
if [ "$INDIRECT" = "yes" ]; then
$GLXINFO -i | grep -q GLX.*fbconfig 
FB=$?
else
$GLXINFO | grep -q GLX.*fbconfig 
FB=$?
fi
if [ $FB = "0" ]; then
unset FB
verbose "present. n"
return 0;
else
unset FB
verbose "not present. n"
return 1;
fi
}
# Check for TFP. 
#!!!Attention , var LIBGL_ALWAYS_INDIRECT will affect glxinfo content as GLX_EXT_texture_from_pixmap
#!!!
check_tfp()
{
verbose "Checking for texture_from_pixmap: "
if [ $($GLXINFO 2>/dev/null | grep GLX_EXT_texture_from_pixmap -c) -gt 2 ] ; then
verbose "present. n"
return 0;
else
verbose "not present. n"
if [ "$INDIRECT" = "yes" ]; then
unset LIBGL_ALWAYS_INDIRECT
INDIRECT="no"
return 1;
else
verbose "Trying again with indirect rendering:n";
INDIRECT="yes"
export LIBGL_ALWAYS_INDIRECT=1
check_tfp;
return $?
fi
fi
}
# Check for Software Rasterizer
check_sw()
{
verbose "Checking for software rasterizer: "
if $GLXINFO 2>/dev/null | egrep -q ‘Software Rasterizer’ ; then 
verbose "present. n"
return 1;
else
verbose "not present. n"
return 0;
fi
}
# Check wether the composite extension is present
check_composite()
{
verbose "Checking for Composite extension: "
if xdpyinfo -queryExtensions | grep -q Composite ; then
verbose "present. n";
return 0;
else
verbose "not present. n";
return 1;
fi
}
# Detects if Xgl is running
check_xgl()
{
verbose "Checking for Xgl: "
if xvinfo | grep -q Xgl ; then
verbose "present. n"
return 0;
else
verbose "not present. n"
return 1;
fi
}
# Check if the nVidia card has enough video ram to make sense
check_nvidia_memory()
{
MEM=$(${NVIDIA_SETTINGS} -q VideoRam | egrep Attribute ‘VideoRam’ .*: | cut -d: -f3 | sed ‘s/[^0-9]//g’)
if [ $MEM -lt $NVIDIA_MEMORY ]; then
verbose "Less than ${NVIDIA_MEMORY}kb of memory and nVidia";
return 1;
fi
return 0;
}
# Check for existence if NV-GLX
check_nvidia()
{
if [ ! -z $NVIDIA_INTERNAL_TEST ]; then
return $NVIDIA_INTERNAL_TEST;
fi
verbose "Checking for nVidia: "
if xdpyinfo | grep -q NV-GLX ; then
verbose "present. n"
NVIDIA_INTERNAL_TEST=0
return 0;
else
verbose "not present. n"
NVIDIA_INTERNAL_TEST=1
return 1;
fi
}
# Check if the max texture size is large enough compared to the resolution
check_texture_size()
{
TEXTURE_LIMIT=$(glxinfo -l | grep GL_MAX_TEXTURE_SIZE | sed ‘s/.*=[^0-9]//g’)
RESOLUTION=$(xdpyinfo  | grep -i dimensions: | sed ‘s/[^0-9]*pixels.*(.*).*//’ | sed ‘s/[^0-9x]*//’)
for res in $RESOLUTION; do
   VRES=$(echo $res | sed ‘s/.*x//’)
   HRES=$(echo $res | sed ‘s/x.*//’)
   verbose "Comparing resolution ($res) to maximum 3D texture size ($TEXTURE_LIMIT): ";
   if [ $VRES -gt $TEXTURE_LIMIT ] || [ $HRES -gt $TEXTURE_LIMIT ]; then
verbose "Failed.n"
return 1;
   fi
done
verbose "Passed.n"
return 0
}
# check driver whitelist
running_under_whitelisted_driver()
{
LOG=$(xset q|grep "Log file"|awk ‘{print $3}’)
if [ "$LOG" = "" ]; then
   verbose "xset q doesn’t reveal the location of the log file. Using fallback $XORG_DEFAULT_LOG n"
   LOG=$XORG_DEFAULT_LOG;
fi
if [ -z "$LOG" ];then
verbose "AIEEEEH, no Log file found n"
verbose "$(xset q) n"
return 0
fi
for DRV in ${WHITELIST}; do
if egrep -q "Loading ${XORG_DRIVER_PATH}${DRV}_drv.so" $LOG &&
  ! egrep -q "Unloading ${XORG_DRIVER_PATH}${DRV}_drv.so" $LOG; 
then
return 0
fi
done
verbose "No whitelisted driver foundn"
return 1
}
# check pciid blacklist
have_blacklisted_pciid()
{
OUTPUT=$(/sbin/lspci -n)
for ID in ${BLACKLIST_PCIIDS}; do
if echo "$OUTPUT" | egrep -q "$ID"; then
verbose "Blacklisted PCIID ‘$ID’ found n"
return 0
fi
done
OUTPUT=$(/sbin/lspci -vn | grep -i VGA)
verbose "Detected PCI ID for VGA: $OUTPUTn"
return 1
}
build_env()
{
if check_nvidia; then
ENV="__GL_YIELD=NOTHING "
fi
if [ "$INDIRECT" = "yes" ]; then
ENV="$ENV LIBGL_ALWAYS_INDIRECT=1 "
fi
if check_xgl; then
if [ -f ${LIBGL_NVIDIA} ]; then
ENV="$ENV LD_PRELOAD=${LIBGL_NVIDIA}"
verbose "Enabling Xgl with nVidia drivers…n"
fi
if [ -f ${LIBGL_FGLRX} ]; then
ENV="$ENV LD_PRELOAD=${LIBGL_FGLRX}"
verbose "Enabling Xgl with fglrx ATi drivers…n"
fi
fi
ENV="$ENV FROM_WRAPPER=yes"
if [ -n "$ENV" ]; then
export $ENV
fi
}
build_args()
{
if [ "x$INDIRECT" = "xyes" ]; then
COMPIZ_OPTIONS="$COMPIZ_OPTIONS –indirect-rendering "
fi
if [ ! -z "$DESKTOP_AUTOSTART_ID" ]; then
COMPIZ_OPTIONS="$COMPIZ_OPTIONS –sm-client-id $DESKTOP_AUTOSTART_ID"
fi
if check_nvidia; then
if [ "x$INDIRECT" != "xyes" ]; then
COMPIZ_OPTIONS="$COMPIZ_OPTIONS –loose-binding"
fi
fi
}
####################
# Execution begins here.
# Read configuration from XDG paths
if [ -z "$XDG_CONFIG_DIRS" ]; then
test -f /etc/xdg/compiz/compiz-manager && . /etc/xdg/compiz/compiz-manager
else
test -f $XDG_CONFIG_DIRS/compiz/compiz-manager && . $XDG_CONFIG_DIRS/compiz/compiz-manager
fi
if [ -z "$XDG_CONFIG_HOME" ]; then
test -f $HOME/.config/compiz/compiz-manager && . $HOME/.config/compiz/compiz-manager
else
test -f $XDG_CONFIG_HOME/compiz/compiz-manager && .  $XDG_CONFIG_HOME/compiz/compiz-manager
fi
# Don’t use compiz when running the failsafe session
if [ "x$GNOME_DESKTOP_SESSION_ID" = "xFailsafe" ]; then
abort_with_fallback_wm
fi
if [ "x$LIBGL_ALWAYS_INDIRECT" = "x1" ]; then
INDIRECT="yes";
fi
# if we run under Xgl, we can skip some tests here
if ! check_xgl; then
# if vesa or vga are in use, do not even try glxinfo (LP#119341)
if ! running_under_whitelisted_driver || have_blacklisted_pciid; then
abort_with_fallback_wm
fi
# check if we have the required bits to run compiz and if not, 
# fallback
if ! check_sw || ! check_tfp || ! check_npot_texture || ! check_composite || ! check_texture_size; then
abort_with_fallback_wm
fi
if check_nvidia && ! check_nvidia_memory; then
abort_with_fallback_wm
fi
if ! check_fbconfig; then
abort_with_fallback_wm
fi
fi
# load the ccp plugin if present and fallback to plain gconf if not
if [ -f ${PLUGIN_PATH}libccp.so ]; then
COMPIZ_PLUGINS="$COMPIZ_PLUGINS ccp"
elif [ -f ${PLUGIN_PATH}libgconf.so ]; then
COMPIZ_PLUGINS="$COMPIZ_PLUGINS glib gconf"
fi
# get environment
build_env
build_args
if [ "x$CM_DRY" = "xyes" ]; then
verbose "Dry run finished: everything should work with regards to Compiz and 3D.n"
verbose "Execute: ${COMPIZ_BIN_PATH}${COMPIZ_NAME} $COMPIZ_OPTIONS "$@" $COMPIZ_PLUGINS n"
exit 0;
fi
# start the gtk-window-decorator if present
if [ -x ${COMPIZ_BIN_PATH}emerald ] && [ "$USE_EMERALD" = "yes" ]; then
verbose "Starting emeraldn"
${COMPIZ_BIN_PATH}emerald –replace &
elif [ -x ${COMPIZ_BIN_PATH}gtk-window-decorator ] && [ -n "$GNOME_DESKTOP_SESSION_ID" ]; then
verbose "Starting gtk-window-decoratorn"
${COMPIZ_BIN_PATH}gtk-window-decorator –replace &
elif [ -x ${COMPIZ_BIN_PATH}kde-window-decorator ] && [ -n "$KDE_FULL_SESSION" ]; then
verbose "Starting kde-window-decoratorn"
${COMPIZ_BIN_PATH}kde-window-decorator –replace &
FALLBACKWM="${KWIN}"
fi
# In case we are in a gnome session, we always want gnomecompat plugin loaded (session registering, key bindings)
if [ -f ${PLUGIN_PATH}libgnomecompat.so ] && [ -n "$GNOME_DESKTOP_SESSION_ID" ] ; then
  COMPIZ_PLUGINS="$COMPIZ_PLUGINS gnomecompat"
fi
echo ‘compiz command:’ ${COMPIZ_BIN_PATH}${COMPIZ_NAME} $COMPIZ_OPTIONS "$@" $COMPIZ_PLUGINS
echo ‘fallback WM:’ $FALLBACKWM $FALLBACKWM_OPTIONS
(${COMPIZ_BIN_PATH}${COMPIZ_NAME} $COMPIZ_OPTIONS "$@" $COMPIZ_PLUGINS & )|| $FALLBACKWM $FALLBACKWM_OPTIONS 

openSuSE XGL消散

Novell 以重新发明轮子的执念发明了XGL - 完全以GLX 为基础的X Server ,在本月随着XGL 更新目录的清空而告终结。

07年底第一次在openSuSE10.2 中接触了XGL , 主要是为了打开compiz。说实话我对这个XGL开始感觉还不错,用的R400 GPU +fglrx,视频正常,3D图形正常(因为所有的图形都用openGL描绘),没有现在aiglx中GLX程序支离破碎的问题。而且由于XGL 是direct rendering,而且自己的libGL对很多openGL功能设计了自己的实现, 所以compiz的blur效果也很正常,但aiglx就不行了。到目前也不行~~。 但R400+fglrx+XGL 也有一个致命缺陷 :慢 。
后来就换了R400+radeon+aiglx ,我开始发现,对这类老卡开源驱动已经赶上了闭源驱动。compiz 非常流畅,比目前的win7 AREO 还要流畅, 除了blur无法启用,其他都正常。另外2D 加速方面也比闭源驱动高一个台阶。
不过我我一直用/X11:/XGL里面的compiz-fusion 来更新,本月突然发现这个目录完全清空了,起初以为资源更新。后来去论坛看了一下,原来已经有人讨论了,得到的结果就是:/X11:/XGL完全废弃。  
 
新的compiz-fusion 从0.8开始又统和在一起成为了compiz ,OH my god 这不是折腾吗? 有句话说的好:出来混迟早是要还的。 
ok,开始折腾新源里的compiz。 注意到fusion的字眼已经消失的无影无踪,当然fusion-icon也拜拜了。全部安装完之后用compiz –replace ,如我料想,什么也没发生,那么…..还是请fusion-icon 进来吧,结果还是不能用,另外有一些额外的错误,看来从compiz-fusion 合并到compiz还是改变了不少东西了。肯定是compiz的启动参数要变动一下。参考了openSuSE11.3 的指南发现要装一个包:compiz-manager  这个包和fusion-icon 类似用来自动配置compiz ,不过没有图形界面罢了,无所谓,先试一下。
 
结果真的好了~~ 
不过现在没有emerald 这个窗口装饰器了,默认是kwin。好办,把光盘里的emerald 请出来就行了。也许有人要说KDE4的主题也可以啊 , 对不起我还在用KDE3 … 暂时没有升KDE4的打算。
从这时刻起彻底告别XGL 和compiz-fusion了 ,下一步就等dri2 ,KMS稳定了

提高BSEG簇表处理效率

BSEG于一般的透明表不同,它是一个簇表。对于一个簇表来说,除了主键项目外,其他项目都被编辑到一个长文本项目中,一起存储在表簇RFBLG中的vardata项目中,这就决定了作为簇表的BSEG无法再建立键值以外的索引(INDEX),所以一般我们对于透明表来说当主键项目不全或完全没有时,追加索引的作法对于BSEG表来说就不好用了。而BSEG簇表又是SAP系统中FI 会计模块中最常被使用的数据表,所以运用好对BSEG表的访问技术对于FI会计模块的扩展开发(ADDON)至关重要。

这篇文章我们就来谈谈如何高效地对BSEG进行访问处理。

对於簇表来说,在数据库中没有与之同名的实体物理表相对应,所以虽然其可在ABAP中使用,但还是有一些限制的:
1. 不能使用Select distinct语法
BSEG中的字段存储在VARDATA中,所以不能使用distinct语句对单个项目去除重复。
2. 不能使用Native SQL
在数据库中没有与之同名的实体物理表相对应,所以不能使用Native SQL 对BSEG操作。
3. 不能使用Order by 语法
BSEG中的字段存储在VARDATA中,所以不能使用Order by语句对单个项目排序。
4. 不能再追加创建索引
BSEG中的字段存储在VARDATA中,所以不能再追加创建索引。

除此之外,对BSEG的访问要使用主键项目,如果没有主键项目虽然语法调试能够通过,但是程序执行起来,耗时长,效率低,而且随着业务量的增加执行时间问题会越发严重,甚至导致程序不能正常执行结束。

那么如果当键值不足时怎么办呢?回答,使用二次索引透明表,具体方法如下描述。

比如和销售凭证有关的业务,根据销售凭证编号和明细编号,选取相关会计凭证明细信息。
SELECT *
FROM BSEG
WHERE VBEL2 = ‘XXXXXXXXXX’     “ 销售凭证编号
AND POSN2 = ‘YYYYYY’.      “ 销售凭证明细编号
在这个例子中,对BSEG的检索条件中因为没有主键项目,所以执行起来,程序很慢。
变通的方法:
1)首先根据销售凭证编号和明细编号,从BSID中检索出未清帐明细行项目。
SELECT BURKS “ 公司代码
BELNR “ 财务凭证编号
GJAHR “ 会计年度
BUZEL “ 会计凭证中的行项目
FROM BSID
INTO TABLE TAB_KEY “ 存放主键项目的内部表
WHERE VBEL2 = ‘XXXXXXXXXX’ “ 销售凭证编号
AND POSN2 = ‘YYYYYY’. “ 销售凭证明细编号
2)再根据销售凭证编号和明细编号,从BSAD中检索出已清帐明细行项目。
SELECT BURKS “ 公司代码
BELNR “ 财务凭证编号
GJAHR “ 会计年度
BUZEL “ 会计凭证中的行项目
FROM BSAD
APPEND TABLE TAB_KEY “ 存放主键项目的内部表
WHERE VBEL2 = ‘XXXXXXXXXX’ “ 销售凭证编号
AND POSN2 = ‘YYYYYY’. “ 销售凭证明细编号
3)然后再根据上面检索出的主键列表,从BSEG中检索出相应的明细行项目。
SELECT BSCHL "転記キー
KOART "勘定タイプ
UMSKZ "特殊仕訳コ
SHKZG "借方/貸方
HKONT "総勘定元帳
GSBER "事業領域
DMBTR "国内通貨額
WRBTR "伝票通貨額
ZUONR "ソートキー
SGTXT "明細テキス
ZFBDT "期日計算の
ZTERM "支払条件キ
ZLSCH "支払方法
ZLSPR "支払保留キ
HBKID "取引銀行の
BVTYP "取引先銀行
FROM BSEG
INTO TABLE TAB_BSEG “ 存放检索结果的内部表
FOR ALL ENTRIES IN TAB_KEY “ 存放主键项目的内部表
WHERE BUKRS = TAB_KEY-BUKRS. “ 公司代码
AND GJAHR = TAB_KEY-GJAHR “ 财务凭证编号
AND BELNR = TAB_KEY-BELNR “ 会计年度
AND BUZEI = TAB_KEY-BUZEI. “ 会计凭证中的行项目
4)这么处理之所以能够提高效率,关键还得对透明表BSID和BSAD追加以VBEL2(销售凭证编号)和POSN2(销售凭证明细编号)为键值的索引(对于透明表可追加索引)。
这样一来,1)和2)步骤地操作有索引,3)步骤的操作有全主键项目,检索速度应该有保证。
采购方面的业务、物料方面的业务等都可如法炮制。
最后需要说明一点,不是所有的SAP体统都可以使用这种方法,能否使用取决于R/3系统的设计和配置。所以在试图使用该方法时应充分调查相关透明表与BSEG中的纪录是否相符,别速度提高了,结果处理对象范围减小了或增大了,那就与初衷背道而驰了,效率的提升一定要在确保业务数据正确的基础上再加以考虑。
SAP R/3系统中也有几个专门用来读取BSEG表信息的函数,可适当参考使用,它们是:
READ_BSEG
GET_ALL_BSEG
另外最有效率的方法是改善你的应用和需求,要使需求合理规范,这才能使效率达到最高化。